From c3ca6d4b991ea24192ac4ddec156d0530b462c3e Mon Sep 17 00:00:00 2001 From: tv Date: Fri, 13 Nov 2026 21:08:21 +0000 Subject: 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. --- CHANGELOG.md | 2 ++ pkgs/populate/default.nix | 15 ++++++++------- tests/scenarios.nix | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0f9380..767652b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- 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/default.nix b/pkgs/populate/default.nix index f2e6c80..dd0beab 100644 --- a/pkgs/populate/default.nix +++ b/pkgs/populate/default.nix @@ -1199,26 +1199,27 @@ let ${if source.shallow then /* sh */ '' git init ${quote target.path} '' else /* sh */ '' - git clone --recurse-submodules ${quote source.url} ${quote target.path} + git clone --recurse-submodules -- ${quote source.url} ${quote target.path} ''} fi cd ${quote target.path} if ! url=$(git config remote.origin.url); then - git remote add origin ${quote source.url} + git remote add -- origin ${quote source.url} elif test "$url" != ${quote source.url}; then - git remote set-url origin ${quote source.url} + git remote set-url -- origin ${quote source.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 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. + # After --, a ref can't be taken for an option. ref=${quote source.ref} fetch() { ${if source.shallow then /* sh */ '' - git fetch --depth=1 origin "$1" + git fetch --depth=1 origin -- "$1" '' else /* sh */ '' - git fetch origin "$1" + git fetch origin -- "$1" ''} } if printf %s "$ref" | grep -Eqx '[0-9a-f]{4,40}'; then @@ -1257,7 +1258,7 @@ let if test -e ${quote source.dir}/.git; then local_pass_info=${quote source.name}\ $( - ${git}/bin/git -C ${quote source.dir} log -1 --format=%H ${quote source.name} + ${git}/bin/git -C ${quote source.dir} log -1 --format=%H -- ${quote source.name} # we append a hash for every symlink, otherwise we would miss updates on # files where the symlink points to ${findutils}/bin/find ${quote source.dir}/${quote source.name} -type l \ @@ -1289,7 +1290,7 @@ let pass_out=$PWD/$rel_name ${coreutils}/bin/mkdir -p "$(${coreutils}/bin/dirname "$pass_out")" - PASSWORD_STORE_DIR=${quote source.dir} ${pass}/bin/pass show "$pass_name" > "$pass_out" + PASSWORD_STORE_DIR=${quote source.dir} ${pass}/bin/pass show -- "$pass_name" > "$pass_out" if [ -n "$pass_date" ]; then ${coreutils}/bin/touch -d "$pass_date" "$pass_out" fi diff --git a/tests/scenarios.nix b/tests/scenarios.nix index 2fc1bd7..8093e02 100644 --- a/tests/scenarios.nix +++ b/tests/scenarios.nix @@ -2104,6 +2104,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 = { -- cgit v1.3.1