aboutsummaryrefslogtreecommitdiff
path: root/src/libfetchers
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2023-10-25 18:18:15 +0200
committerlunaphied <lunaphied@lunaphied.me>2024-03-25 15:30:36 +0000
commitb525d0f20c4fd94b89d6d34d8acd0ca4c579a5fc (patch)
tree89f2259054c2afec58c56993b70c2ed45efe5529 /src/libfetchers
parent3d065192c08b3dcb76b9cf70cd0104974106ae8f (diff)
Input: Replace markFileChanged() by putFile()
Committing a lock file using markFileChanged() required the input to be writable by the caller in the local filesystem (using the path returned by getSourcePath()). putFile() abstracts over this. (cherry picked from commit 95d657c8b3ae4282e24628ba7426edb90c8f3942) Change-Id: Ie081c5d9eb4e923b229191c5e23ece85145557ff
Diffstat (limited to 'src/libfetchers')
-rw-r--r--src/libfetchers/cache.hh1
-rw-r--r--src/libfetchers/fetchers.cc17
-rw-r--r--src/libfetchers/fetchers.hh20
-rw-r--r--src/libfetchers/git.cc22
-rw-r--r--src/libfetchers/indirect.cc1
-rw-r--r--src/libfetchers/mercurial.cc21
-rw-r--r--src/libfetchers/path.cc20
7 files changed, 75 insertions, 27 deletions
diff --git a/src/libfetchers/cache.hh b/src/libfetchers/cache.hh
index ae398d040..af34e66ce 100644
--- a/src/libfetchers/cache.hh
+++ b/src/libfetchers/cache.hh
@@ -2,6 +2,7 @@
///@file
#include "fetchers.hh"
+#include "path.hh"
namespace nix::fetchers {
diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc
index 530473023..dc8df2217 100644
--- a/src/libfetchers/fetchers.cc
+++ b/src/libfetchers/fetchers.cc
@@ -200,12 +200,13 @@ std::optional<Path> Input::getSourcePath() const
return scheme->getSourcePath(*this);
}
-void Input::markChangedFile(
- std::string_view file,
+void Input::putFile(
+ const CanonPath & path,
+ std::string_view contents,
std::optional<std::string> commitMsg) const
{
assert(scheme);
- return scheme->markChangedFile(*this, file, commitMsg);
+ return scheme->putFile(*this, path, contents, commitMsg);
}
std::string Input::getName() const
@@ -295,14 +296,18 @@ Input InputScheme::applyOverrides(
return input;
}
-std::optional<Path> InputScheme::getSourcePath(const Input & input)
+std::optional<Path> InputScheme::getSourcePath(const Input & input) const
{
return {};
}
-void InputScheme::markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg)
+void InputScheme::putFile(
+ const Input & input,
+ const CanonPath & path,
+ std::string_view contents,
+ std::optional<std::string> commitMsg) const
{
- assert(false);
+ throw Error("input '%s' does not support modifying file '%s'", input.to_string(), path);
}
void InputScheme::clone(const Input & input, const Path & destDir) const
diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh
index 6e10e9513..e1067ce1c 100644
--- a/src/libfetchers/fetchers.hh
+++ b/src/libfetchers/fetchers.hh
@@ -3,13 +3,14 @@
#include "types.hh"
#include "hash.hh"
+#include "canon-path.hh"
#include "path.hh"
#include "attrs.hh"
#include "url.hh"
#include <memory>
-namespace nix { class Store; }
+namespace nix { class Store; class StorePath; }
namespace nix::fetchers {
@@ -97,8 +98,13 @@ public:
std::optional<Path> getSourcePath() const;
- void markChangedFile(
- std::string_view file,
+ /**
+ * Write a file to this input, for input types that support
+ * writing. Optionally commit the change (for e.g. Git inputs).
+ */
+ void putFile(
+ const CanonPath & path,
+ std::string_view contents,
std::optional<std::string> commitMsg) const;
std::string getName() const;
@@ -144,9 +150,13 @@ struct InputScheme
virtual void clone(const Input & input, const Path & destDir) const;
- virtual std::optional<Path> getSourcePath(const Input & input);
+ virtual std::optional<Path> getSourcePath(const Input & input) const;
- virtual void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg);
+ virtual void putFile(
+ const Input & input,
+ const CanonPath & path,
+ std::string_view contents,
+ std::optional<std::string> commitMsg) const;
virtual std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) = 0;
};
diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc
index 48e1bd6e3..671779f84 100644
--- a/src/libfetchers/git.cc
+++ b/src/libfetchers/git.cc
@@ -363,7 +363,7 @@ struct GitInputScheme : InputScheme
runProgram("git", true, args, {}, true);
}
- std::optional<Path> getSourcePath(const Input & input) override
+ std::optional<Path> getSourcePath(const Input & input) const override
{
auto url = parseURL(getStrAttr(input.attrs, "url"));
if (url.scheme == "file" && !input.getRef() && !input.getRev())
@@ -371,22 +371,30 @@ struct GitInputScheme : InputScheme
return {};
}
- void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg) override
+ void putFile(
+ const Input & input,
+ const CanonPath & path,
+ std::string_view contents,
+ std::optional<std::string> commitMsg) const override
{
- auto sourcePath = getSourcePath(input);
- assert(sourcePath);
+ auto root = getSourcePath(input);
+ if (!root)
+ throw Error("cannot commit '%s' to Git repository '%s' because it's not a working tree", path, input.to_string());
+
+ writeFile((CanonPath(*root) + path).abs(), contents);
+
auto gitDir = ".git";
auto result = runProgram(RunOptions {
.program = "git",
- .args = {"-C", *sourcePath, "--git-dir", gitDir, "check-ignore", "--quiet", std::string(file)},
+ .args = {"-C", *root, "--git-dir", gitDir, "check-ignore", "--quiet", std::string(path.rel())},
});
auto exitCode = WEXITSTATUS(result.first);
if (exitCode != 0) {
// The path is not `.gitignore`d, we can add the file.
runProgram("git", true,
- { "-C", *sourcePath, "--git-dir", gitDir, "add", "--intent-to-add", "--", std::string(file) });
+ { "-C", *root, "--git-dir", gitDir, "add", "--intent-to-add", "--", std::string(path.rel()) });
if (commitMsg) {
@@ -394,7 +402,7 @@ struct GitInputScheme : InputScheme
logger->pause();
Finally restoreLogger([]() { logger->resume(); });
runProgram("git", true,
- { "-C", *sourcePath, "--git-dir", gitDir, "commit", std::string(file), "-m", *commitMsg });
+ { "-C", *root, "--git-dir", gitDir, "commit", std::string(path.rel()), "-m", *commitMsg });
}
}
}
diff --git a/src/libfetchers/indirect.cc b/src/libfetchers/indirect.cc
index 4874a43ff..c73505b31 100644
--- a/src/libfetchers/indirect.cc
+++ b/src/libfetchers/indirect.cc
@@ -1,5 +1,6 @@
#include "fetchers.hh"
#include "url-parts.hh"
+#include "path.hh"
namespace nix::fetchers {
diff --git a/src/libfetchers/mercurial.cc b/src/libfetchers/mercurial.cc
index a70403660..87fecfca3 100644
--- a/src/libfetchers/mercurial.cc
+++ b/src/libfetchers/mercurial.cc
@@ -116,7 +116,7 @@ struct MercurialInputScheme : InputScheme
return res;
}
- std::optional<Path> getSourcePath(const Input & input) override
+ std::optional<Path> getSourcePath(const Input & input) const override
{
auto url = parseURL(getStrAttr(input.attrs, "url"));
if (url.scheme == "file" && !input.getRef() && !input.getRev())
@@ -124,18 +124,27 @@ struct MercurialInputScheme : InputScheme
return {};
}
- void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg) override
+ void putFile(
+ const Input & input,
+ const CanonPath & path,
+ std::string_view contents,
+ std::optional<std::string> commitMsg) const override
{
- auto sourcePath = getSourcePath(input);
- assert(sourcePath);
+ auto [isLocal, repoPath] = getActualUrl(input);
+ if (!isLocal)
+ throw Error("cannot commit '%s' to Mercurial repository '%s' because it's not a working tree", path, input.to_string());
+
+ auto absPath = CanonPath(repoPath) + path;
+
+ writeFile(absPath.abs(), contents);
// FIXME: shut up if file is already tracked.
runHg(
- { "add", *sourcePath + "/" + std::string(file) });
+ { "add", absPath.abs() });
if (commitMsg)
runHg(
- { "commit", *sourcePath + "/" + std::string(file), "-m", *commitMsg });
+ { "commit", absPath.abs(), "-m", *commitMsg });
}
std::pair<bool, std::string> getActualUrl(const Input & input) const
diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc
index 01f1be978..11c952dc2 100644
--- a/src/libfetchers/path.cc
+++ b/src/libfetchers/path.cc
@@ -71,14 +71,28 @@ struct PathInputScheme : InputScheme
return true;
}
- std::optional<Path> getSourcePath(const Input & input) override
+ std::optional<Path> getSourcePath(const Input & input) const override
{
return getStrAttr(input.attrs, "path");
}
- void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg) override
+ void putFile(
+ const Input & input,
+ const CanonPath & path,
+ std::string_view contents,
+ std::optional<std::string> commitMsg) const override
{
- // nothing to do
+ writeFile((CanonPath(getAbsPath(input)) + path).abs(), contents);
+ }
+
+ CanonPath getAbsPath(const Input & input) const
+ {
+ auto path = getStrAttr(input.attrs, "path");
+
+ if (path[0] == '/')
+ return CanonPath(path);
+
+ throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string());
}
std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override