1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-27 12:41:15 +02:00

Merge pull request #9239 from edolstra/putFile

Input: Replace markFileChanged() by putFile()
This commit is contained in:
Eelco Dolstra 2023-10-31 14:49:42 +01:00 committed by GitHub
commit fa6bc33604
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 108 additions and 67 deletions

View file

@ -623,12 +623,7 @@ LockedFlake lockFlake(
debug("new lock file: %s", newLockFile); debug("new lock file: %s", newLockFile);
auto relPath = (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock";
auto sourcePath = topRef.input.getSourcePath(); auto sourcePath = topRef.input.getSourcePath();
auto outputLockFilePath = sourcePath ? std::optional{*sourcePath + "/" + relPath} : std::nullopt;
if (lockFlags.outputLockFilePath) {
outputLockFilePath = lockFlags.outputLockFilePath;
}
/* Check whether we need to / can write the new lock file. */ /* Check whether we need to / can write the new lock file. */
if (newLockFile != oldLockFile || lockFlags.outputLockFilePath) { if (newLockFile != oldLockFile || lockFlags.outputLockFilePath) {
@ -636,7 +631,7 @@ LockedFlake lockFlake(
auto diff = LockFile::diff(oldLockFile, newLockFile); auto diff = LockFile::diff(oldLockFile, newLockFile);
if (lockFlags.writeLockFile) { if (lockFlags.writeLockFile) {
if (outputLockFilePath) { if (sourcePath || lockFlags.outputLockFilePath) {
if (auto unlockedInput = newLockFile.isUnlocked()) { if (auto unlockedInput = newLockFile.isUnlocked()) {
if (fetchSettings.warnDirty) if (fetchSettings.warnDirty)
warn("will not write lock file of flake '%s' because it has an unlocked input ('%s')", topRef, *unlockedInput); warn("will not write lock file of flake '%s' because it has an unlocked input ('%s')", topRef, *unlockedInput);
@ -644,41 +639,48 @@ LockedFlake lockFlake(
if (!lockFlags.updateLockFile) if (!lockFlags.updateLockFile)
throw Error("flake '%s' requires lock file changes but they're not allowed due to '--no-update-lock-file'", topRef); throw Error("flake '%s' requires lock file changes but they're not allowed due to '--no-update-lock-file'", topRef);
bool lockFileExists = pathExists(*outputLockFilePath); auto newLockFileS = fmt("%s\n", newLockFile);
if (lockFileExists) { if (lockFlags.outputLockFilePath) {
auto s = chomp(diff); if (lockFlags.commitLockFile)
if (s.empty()) throw Error("'--commit-lock-file' and '--output-lock-file' are incompatible");
warn("updating lock file '%s'", *outputLockFilePath); writeFile(*lockFlags.outputLockFilePath, newLockFileS);
else } else {
warn("updating lock file '%s':\n%s", *outputLockFilePath, s); auto relPath = (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock";
} else auto outputLockFilePath = *sourcePath + "/" + relPath;
warn("creating lock file '%s'", *outputLockFilePath);
newLockFile.write(*outputLockFilePath); bool lockFileExists = pathExists(outputLockFilePath);
std::optional<std::string> commitMessage = std::nullopt; if (lockFileExists) {
if (lockFlags.commitLockFile) { auto s = chomp(diff);
if (lockFlags.outputLockFilePath) { if (s.empty())
throw Error("--commit-lock-file and --output-lock-file are currently incompatible"); warn("updating lock file '%s'", outputLockFilePath);
} else
std::string cm; warn("updating lock file '%s':\n%s", outputLockFilePath, s);
} else
warn("creating lock file '%s'", outputLockFilePath);
cm = fetchSettings.commitLockFileSummary.get(); std::optional<std::string> commitMessage = std::nullopt;
if (cm == "") { if (lockFlags.commitLockFile) {
cm = fmt("%s: %s", relPath, lockFileExists ? "Update" : "Add"); std::string cm;
cm = fetchSettings.commitLockFileSummary.get();
if (cm == "") {
cm = fmt("%s: %s", relPath, lockFileExists ? "Update" : "Add");
}
cm += "\n\nFlake lock file updates:\n\n";
cm += filterANSIEscapes(diff, true);
commitMessage = cm;
} }
cm += "\n\nFlake lock file updates:\n\n"; topRef.input.putFile(
cm += filterANSIEscapes(diff, true); CanonPath((topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock"),
commitMessage = cm; newLockFileS, commitMessage);
} }
topRef.input.markChangedFile(
(topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock",
commitMessage);
/* Rewriting the lockfile changed the top-level /* Rewriting the lockfile changed the top-level
repo, so we should re-read it. FIXME: we could repo, so we should re-read it. FIXME: we could
also just clear the 'rev' field... */ also just clear the 'rev' field... */

View file

@ -214,12 +214,6 @@ std::ostream & operator <<(std::ostream & stream, const LockFile & lockFile)
return stream; return stream;
} }
void LockFile::write(const Path & path) const
{
createDirs(dirOf(path));
writeFile(path, fmt("%s\n", *this));
}
std::optional<FlakeRef> LockFile::isUnlocked() const std::optional<FlakeRef> LockFile::isUnlocked() const
{ {
std::set<ref<const Node>> nodes; std::set<ref<const Node>> nodes;

View file

@ -65,8 +65,6 @@ struct LockFile
static LockFile read(const Path & path); static LockFile read(const Path & path);
void write(const Path & path) const;
/** /**
* Check whether this lock file has any unlocked inputs. * Check whether this lock file has any unlocked inputs.
*/ */

View file

@ -2,6 +2,7 @@
///@file ///@file
#include "fetchers.hh" #include "fetchers.hh"
#include "path.hh"
namespace nix::fetchers { namespace nix::fetchers {

View file

@ -196,12 +196,13 @@ std::optional<Path> Input::getSourcePath() const
return scheme->getSourcePath(*this); return scheme->getSourcePath(*this);
} }
void Input::markChangedFile( void Input::putFile(
std::string_view file, const CanonPath & path,
std::string_view contents,
std::optional<std::string> commitMsg) const std::optional<std::string> commitMsg) const
{ {
assert(scheme); assert(scheme);
return scheme->markChangedFile(*this, file, commitMsg); return scheme->putFile(*this, path, contents, commitMsg);
} }
std::string Input::getName() const std::string Input::getName() const
@ -292,14 +293,18 @@ Input InputScheme::applyOverrides(
return input; return input;
} }
std::optional<Path> InputScheme::getSourcePath(const Input & input) std::optional<Path> InputScheme::getSourcePath(const Input & input) const
{ {
return {}; 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 void InputScheme::clone(const Input & input, const Path & destDir) const

View file

@ -3,13 +3,13 @@
#include "types.hh" #include "types.hh"
#include "hash.hh" #include "hash.hh"
#include "path.hh" #include "canon-path.hh"
#include "attrs.hh" #include "attrs.hh"
#include "url.hh" #include "url.hh"
#include <memory> #include <memory>
namespace nix { class Store; } namespace nix { class Store; class StorePath; }
namespace nix::fetchers { namespace nix::fetchers {
@ -90,8 +90,13 @@ public:
std::optional<Path> getSourcePath() const; 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::optional<std::string> commitMsg) const;
std::string getName() const; std::string getName() const;
@ -135,9 +140,13 @@ struct InputScheme
virtual void clone(const Input & input, const Path & destDir) const; 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; virtual std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) = 0;

View file

@ -354,7 +354,7 @@ struct GitInputScheme : InputScheme
runProgram("git", true, args, {}, true); 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")); auto url = parseURL(getStrAttr(input.attrs, "url"));
if (url.scheme == "file" && !input.getRef() && !input.getRev()) if (url.scheme == "file" && !input.getRef() && !input.getRev())
@ -362,18 +362,26 @@ struct GitInputScheme : InputScheme
return {}; 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); auto root = getSourcePath(input);
assert(sourcePath); 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 gitDir = ".git";
runProgram("git", true, 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) if (commitMsg)
runProgram("git", true, 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 });
} }
std::pair<bool, std::string> getActualUrl(const Input & input) const std::pair<bool, std::string> getActualUrl(const Input & input) const

View file

@ -1,5 +1,6 @@
#include "fetchers.hh" #include "fetchers.hh"
#include "url-parts.hh" #include "url-parts.hh"
#include "path.hh"
namespace nix::fetchers { namespace nix::fetchers {

View file

@ -109,7 +109,7 @@ struct MercurialInputScheme : InputScheme
return res; 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")); auto url = parseURL(getStrAttr(input.attrs, "url"));
if (url.scheme == "file" && !input.getRef() && !input.getRev()) if (url.scheme == "file" && !input.getRef() && !input.getRev())
@ -117,18 +117,27 @@ struct MercurialInputScheme : InputScheme
return {}; 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); auto [isLocal, repoPath] = getActualUrl(input);
assert(sourcePath); 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. // FIXME: shut up if file is already tracked.
runHg( runHg(
{ "add", *sourcePath + "/" + std::string(file) }); { "add", absPath.abs() });
if (commitMsg) if (commitMsg)
runHg( runHg(
{ "commit", *sourcePath + "/" + std::string(file), "-m", *commitMsg }); { "commit", absPath.abs(), "-m", *commitMsg });
} }
std::pair<bool, std::string> getActualUrl(const Input & input) const std::pair<bool, std::string> getActualUrl(const Input & input) const

View file

@ -66,14 +66,28 @@ struct PathInputScheme : InputScheme
}; };
} }
std::optional<Path> getSourcePath(const Input & input) override std::optional<Path> getSourcePath(const Input & input) const override
{ {
return getStrAttr(input.attrs, "path"); 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 std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override