aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-13 20:27:48 +0000
committertv <tv@krebsco.de>2026-11-13 21:58:36 +0100
commitef581c93f391919b35b903b93af45f33d90de15d (patch)
tree13ab36537f805dcba0534c8f3e1b3f4d6b8e13b4
parente9256952f16eb33f9b7e49777ec76878489a5053 (diff)
populate: keep URLs, refs, and names from being taken for options
A git source's url and ref are strings, and git clone, git remote, and git fetch took ones starting with - for options, e.g. --upload-pack, which runs a command where the repository is local. They come after -- now, and so does a pass source's name for git log and pass show. git-ref-option gives a ref that git fetch would take for --upload-pack.
-rw-r--r--CHANGELOG.md2
-rw-r--r--pkgs/populate/src/sh.rs17
-rw-r--r--tests/scenarios.nix23
3 files changed, 34 insertions, 8 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index af40bb0..7f5f2c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@
as JSON. The store gets one program for each version of krops, instead
of a script for each set of arguments. `pkgs.populate`, `writeDeploy`,
and the other functions keep their arguments.
+- Git can't take a `git` source's `url` or `ref`, or a `pass` source's
+ `name`, for an option.
- `git` sources with a branch or tag as `ref` follow it: populate fetches
the branch or tag on every run, and resets the work tree to what it
fetched.
diff --git a/pkgs/populate/src/sh.rs b/pkgs/populate/src/sh.rs
index 8282370..ce42e12 100644
--- a/pkgs/populate/src/sh.rs
+++ b/pkgs/populate/src/sh.rs
@@ -352,24 +352,25 @@ if ! test -e "$path"; then
if test -n "$shallow"; then
git init "$path"
else
- git clone --recurse-submodules "$url" "$path"
+ git clone --recurse-submodules -- "$url" "$path"
fi
fi
cd "$path"
if ! origin=$(git config remote.origin.url); then
- git remote add origin "$url"
+ git remote add -- origin "$url"
elif test "$origin" != "$url"; then
- git remote set-url origin "$url"
+ git remote set-url -- origin "$url"
fi
# A commit, given by its hash or a prefix thereof, gets fetched only if the
-# work tree lacks it, unless fetchAlways is set. A branch or tag gets
+# work tree lacks it, unless fetchAlways is set. After --, a ref can't be
+# taken for an option. A branch or tag gets
# fetched on every run, so the work tree follows it: resetting to its name
# would reset to a local branch, which fetching doesn't move.
fetch() {
if test -n "$shallow"; then
- git fetch --depth=1 origin "$1"
+ git fetch --depth=1 origin -- "$1"
else
- git fetch origin "$1"
+ git fetch origin -- "$1"
fi
}
fetch_commit() {
@@ -418,7 +419,7 @@ pub mod local {
dir=$1 name=$2
if test -e "$dir"/.git; then
printf '%s %s\n' "$name" "$(
- git -C "$dir" log -1 --format=%H "$name"
+ git -C "$dir" log -1 --format=%H -- "$name"
find "$dir"/"$name" -type l -exec realpath {} + |
sort |
xargs -r -n 1 git -C "$dir" log -1 --format=%H
@@ -446,7 +447,7 @@ while read -r gpg_path; do
pass_name=$name/$rel_name
pass_out=$PWD/$rel_name
mkdir -p "$(dirname "$pass_out")"
- PASSWORD_STORE_DIR=$dir pass show "$pass_name" > "$pass_out"
+ PASSWORD_STORE_DIR=$dir pass show -- "$pass_name" > "$pass_out"
if [ -n "$pass_date" ]; then
touch -d "$pass_date" "$pass_out"
fi
diff --git a/tests/scenarios.nix b/tests/scenarios.nix
index 14a2c91..85b481e 100644
--- a/tests/scenarios.nix
+++ b/tests/scenarios.nix
@@ -2105,6 +2105,29 @@ assert !(krops.isLocalTarget (targets.remote "/"));
}
];
}))
+ # A ref that git fetch would take for an option: --upload-pack runs a
+ # command where the repository is local.
+ (s "git-ref-option" (let
+ elsewhere = "/var/krops-elsewhere";
+ in {
+ isolate = true;
+ prepare = ''
+ rm -fR ${elsewhere}
+ git clone -q --bare ${gitUrl} ${elsewhere}/repo.git
+ '';
+ phases = [
+ {
+ sources.x.git = {
+ url = "${elsewhere}/repo.git";
+ ref = "--upload-pack=touch ${elsewhere}/ran; git-upload-pack";
+ };
+ expect.fail = "invalid refspec";
+ check = ''
+ test ! -e ${elsewhere}/ran || fail "the ref ran a command"
+ '';
+ }
+ ];
+ }))
# A file in populate's state replaced by a symlink to a file outside.
(s "state-key" (let
sources.x.flake-input = {