Merge pull request #8042 from lheckemann/alt-lockfiles
Allow specifying alternative paths for reading/writing flake locks
This commit is contained in:
commit
81491e1379
4 changed files with 63 additions and 12 deletions
|
@ -102,6 +102,28 @@ MixFlakeOptions::MixFlakeOptions()
|
||||||
}}
|
}}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addFlag({
|
||||||
|
.longName = "reference-lock-file",
|
||||||
|
.description = "Read the given lock file instead of `flake.lock` within the top-level flake.",
|
||||||
|
.category = category,
|
||||||
|
.labels = {"flake-lock-path"},
|
||||||
|
.handler = {[&](std::string lockFilePath) {
|
||||||
|
lockFlags.referenceLockFilePath = lockFilePath;
|
||||||
|
}},
|
||||||
|
.completer = completePath
|
||||||
|
});
|
||||||
|
|
||||||
|
addFlag({
|
||||||
|
.longName = "output-lock-file",
|
||||||
|
.description = "Write the given lock file instead of `flake.lock` within the top-level flake.",
|
||||||
|
.category = category,
|
||||||
|
.labels = {"flake-lock-path"},
|
||||||
|
.handler = {[&](std::string lockFilePath) {
|
||||||
|
lockFlags.outputLockFilePath = lockFilePath;
|
||||||
|
}},
|
||||||
|
.completer = completePath
|
||||||
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "inputs-from",
|
.longName = "inputs-from",
|
||||||
.description = "Use the inputs of the specified flake as registry entries.",
|
.description = "Use the inputs of the specified flake as registry entries.",
|
||||||
|
|
|
@ -334,10 +334,14 @@ LockedFlake lockFlake(
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (!fetchSettings.allowDirty && lockFlags.referenceLockFilePath) {
|
||||||
|
throw Error("reference lock file was provided, but the `allow-dirty` setting is set to false");
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: symlink attack
|
// FIXME: symlink attack
|
||||||
auto oldLockFile = LockFile::read(
|
auto oldLockFile = LockFile::read(
|
||||||
flake.sourceInfo->actualPath + "/" + flake.lockedRef.subdir + "/flake.lock");
|
lockFlags.referenceLockFilePath.value_or(
|
||||||
|
flake.sourceInfo->actualPath + "/" + flake.lockedRef.subdir + "/flake.lock"));
|
||||||
|
|
||||||
debug("old lock file: %s", oldLockFile);
|
debug("old lock file: %s", oldLockFile);
|
||||||
|
|
||||||
|
@ -619,13 +623,20 @@ 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 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)) {
|
if (newLockFile != oldLockFile || lockFlags.outputLockFilePath) {
|
||||||
|
|
||||||
auto diff = LockFile::diff(oldLockFile, newLockFile);
|
auto diff = LockFile::diff(oldLockFile, newLockFile);
|
||||||
|
|
||||||
if (lockFlags.writeLockFile) {
|
if (lockFlags.writeLockFile) {
|
||||||
if (auto sourcePath = topRef.input.getSourcePath()) {
|
if (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);
|
||||||
|
@ -633,25 +644,24 @@ 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);
|
||||||
|
|
||||||
auto relPath = (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock";
|
bool lockFileExists = pathExists(*outputLockFilePath);
|
||||||
|
|
||||||
auto path = *sourcePath + "/" + relPath;
|
|
||||||
|
|
||||||
bool lockFileExists = pathExists(path);
|
|
||||||
|
|
||||||
if (lockFileExists) {
|
if (lockFileExists) {
|
||||||
auto s = chomp(diff);
|
auto s = chomp(diff);
|
||||||
if (s.empty())
|
if (s.empty())
|
||||||
warn("updating lock file '%s'", path);
|
warn("updating lock file '%s'", *outputLockFilePath);
|
||||||
else
|
else
|
||||||
warn("updating lock file '%s':\n%s", path, s);
|
warn("updating lock file '%s':\n%s", *outputLockFilePath, s);
|
||||||
} else
|
} else
|
||||||
warn("creating lock file '%s'", path);
|
warn("creating lock file '%s'", *outputLockFilePath);
|
||||||
|
|
||||||
newLockFile.write(path);
|
newLockFile.write(*outputLockFilePath);
|
||||||
|
|
||||||
std::optional<std::string> commitMessage = std::nullopt;
|
std::optional<std::string> commitMessage = std::nullopt;
|
||||||
if (lockFlags.commitLockFile) {
|
if (lockFlags.commitLockFile) {
|
||||||
|
if (lockFlags.outputLockFilePath) {
|
||||||
|
throw Error("--commit-lock-file and --output-lock-file are currently incompatible");
|
||||||
|
}
|
||||||
std::string cm;
|
std::string cm;
|
||||||
|
|
||||||
cm = fetchSettings.commitLockFileSummary.get();
|
cm = fetchSettings.commitLockFileSummary.get();
|
||||||
|
|
|
@ -118,6 +118,12 @@ struct LockFlags
|
||||||
/* Whether to commit changes to flake.lock. */
|
/* Whether to commit changes to flake.lock. */
|
||||||
bool commitLockFile = false;
|
bool commitLockFile = false;
|
||||||
|
|
||||||
|
/* The path to a lock file to read instead of the `flake.lock` file in the top-level flake */
|
||||||
|
std::optional<std::string> referenceLockFilePath;
|
||||||
|
|
||||||
|
/* The path to a lock file to write to instead of the `flake.lock` file in the top-level flake */
|
||||||
|
std::optional<Path> outputLockFilePath;
|
||||||
|
|
||||||
/* Flake inputs to be overridden. */
|
/* Flake inputs to be overridden. */
|
||||||
std::map<InputPath, FlakeRef> inputOverrides;
|
std::map<InputPath, FlakeRef> inputOverrides;
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,9 @@ json=$(nix flake metadata flake1 --json | jq .)
|
||||||
hash1=$(echo "$json" | jq -r .revision)
|
hash1=$(echo "$json" | jq -r .revision)
|
||||||
|
|
||||||
echo -n '# foo' >> $flake1Dir/flake.nix
|
echo -n '# foo' >> $flake1Dir/flake.nix
|
||||||
|
flake1OriginalCommit=$(git -C $flake1Dir rev-parse HEAD)
|
||||||
git -C $flake1Dir commit -a -m 'Foo'
|
git -C $flake1Dir commit -a -m 'Foo'
|
||||||
|
flake1NewCommit=$(git -C $flake1Dir rev-parse HEAD)
|
||||||
hash2=$(nix flake metadata flake1 --json --refresh | jq -r .revision)
|
hash2=$(nix flake metadata flake1 --json --refresh | jq -r .revision)
|
||||||
[[ $hash1 != $hash2 ]]
|
[[ $hash1 != $hash2 ]]
|
||||||
|
|
||||||
|
@ -491,3 +493,14 @@ nix store delete $(nix store add-path $badFlakeDir)
|
||||||
[[ $(nix-instantiate --eval flake:git+file://$flake3Dir -A x) = 123 ]]
|
[[ $(nix-instantiate --eval flake:git+file://$flake3Dir -A x) = 123 ]]
|
||||||
[[ $(nix-instantiate -I flake3=flake:flake3 --eval '<flake3>' -A x) = 123 ]]
|
[[ $(nix-instantiate -I flake3=flake:flake3 --eval '<flake3>' -A x) = 123 ]]
|
||||||
[[ $(NIX_PATH=flake3=flake:flake3 nix-instantiate --eval '<flake3>' -A x) = 123 ]]
|
[[ $(NIX_PATH=flake3=flake:flake3 nix-instantiate --eval '<flake3>' -A x) = 123 ]]
|
||||||
|
|
||||||
|
# Test alternate lockfile paths.
|
||||||
|
nix flake lock $flake2Dir --output-lock-file $TEST_ROOT/flake2.lock
|
||||||
|
cmp $flake2Dir/flake.lock $TEST_ROOT/flake2.lock >/dev/null # lockfiles should be identical, since we're referencing flake2's original one
|
||||||
|
|
||||||
|
nix flake lock $flake2Dir --output-lock-file $TEST_ROOT/flake2-overridden.lock --override-input flake1 git+file://$flake1Dir?rev=$flake1OriginalCommit
|
||||||
|
expectStderr 1 cmp $flake2Dir/flake.lock $TEST_ROOT/flake2-overridden.lock
|
||||||
|
nix flake metadata $flake2Dir --reference-lock-file $TEST_ROOT/flake2-overridden.lock | grepQuiet $flake1OriginalCommit
|
||||||
|
|
||||||
|
# reference-lock-file can only be used if allow-dirty is set.
|
||||||
|
expectStderr 1 nix flake metadata $flake2Dir --no-allow-dirty --reference-lock-file $TEST_ROOT/flake2-overridden.lock
|
||||||
|
|
Loading…
Reference in a new issue