Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,22 @@ correct key is provided set in `git_crypt_key`.
the repository.
</td>
</tr>
<tr>
<td><code>revision</code><br/><i>Optional</i></td>
<td>
If <code>true</code>, clone the repository using <code>git clone
--revision=&lt;ref&gt;</code>, which fetches only the history leading to
the specific <code>version.ref</code> commit. HEAD is detached at that
commit and no remote-tracking branches are created. This is more
efficient than the default clone strategy for large repositories when
the exact commit SHA is known, as it avoids fetching the branch tip and
the deepening loop. Can be combined with <code>depth</code> to further
limit ancestry. Incompatible with <code>branch</code>.
<br/><br/>
<strong>Note:</strong> Requires a git version that supports the
<code>--revision</code> flag.
</td>
</tr>
<tr>
<td><code>fetch</code><br/><i>Optional</i></td>
<td>
Expand Down
24 changes: 22 additions & 2 deletions assets/in
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ timestamp_format=$(jq -r '(.params.timestamp_format // "iso8601")' <<< "$payload
describe_ref_options=$(jq -r '(.params.describe_ref_options // "--always --dirty --broken")' <<< "$payload")
search_remote_refs_flag=$(jq -r '(.source.search_remote_refs // false)' <<< "$payload")
all_branches=$(jq -r '(.params.all_branches // false)' <<< "$payload")
revision=$(jq -r '(.params.revision // false)' <<< "$payload")

# If params not defined, get it from source
if [ -z "$fetch_tags" ] || [ "$fetch_tags" == "null" ] ; then
Expand All @@ -97,6 +98,13 @@ if [ -n "$override_branch" ]; then
branchflag="--branch $override_branch"
fi

if [ "$revision" == "true" ]; then
if [ -n "$branchflag" ]; then
echo "error: revision param is incompatible with branch" >&2
exit 1
fi
fi

depthflag=""
if test "$depth" -gt 0 2> /dev/null; then
depthflag="--depth $depth"
Expand Down Expand Up @@ -124,7 +132,16 @@ if [ "${all_branches,,}" == "true" ]; then
singlebranchflag=""
fi

git clone --progress $singlebranchflag $depthflag $uri $branchflag $destination $tagflag $nocheckoutflag
revisionflag=""
if [ "$revision" == "true" ]; then
revisionflag="--revision=$ref"
fi

if [ "$revision" == "true" ]; then
git clone --progress $depthflag $revisionflag $uri $destination $tagflag $nocheckoutflag
else
git clone --progress $singlebranchflag $depthflag $uri $branchflag $destination $tagflag $nocheckoutflag
fi

cd $destination

Expand All @@ -137,7 +154,10 @@ fi

git fetch origin refs/notes/*:refs/notes/* $tagflag

if [ "$depth" -gt 0 ]; then
if [ "$revision" == "true" ]; then
# --revision already detaches HEAD at $ref, no checkout needed
:
elif [ "$depth" -gt 0 ]; then
"$bin_dir"/deepen_shallow_clone_until_ref_is_found_then_check_out "$depth" "$ref" "$tagflag"
else
if [ "$search_remote_refs_flag" == "true" ] && ! [ -z "$branchflag" ] && ! git rev-list -1 $ref 2> /dev/null > /dev/null; then
Expand Down
3 changes: 2 additions & 1 deletion assets/in_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
"timestamp_format": "",
"describe_ref_options": "",
"all_branches": "",
"debug": ""
"debug": "",
"revision": ""
}
50 changes: 50 additions & 0 deletions test/get.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,53 @@ it_can_get_from_url_at_branch_with_search_remote_refs() {
test "$(git -C $dest rev-parse HEAD)" = $ref2
}

it_can_get_with_revision() {
local repo=$(init_repo)
local ref1=$(make_commit $repo)
local ref2=$(make_commit $repo)
local ref3=$(make_commit $repo)

local dest=$TMPDIR/destination

get_uri_with_revision "file://$repo" $ref2 $dest | jq -e "
.version == {ref: $(echo $ref2 | jq -R .)}
"

test "$(git -C $dest rev-parse HEAD)" = $ref2
test -z "$(git -C $dest branch -r)"
}

it_can_get_with_revision_and_depth() {
local repo=$(init_repo)
local ref1=$(make_commit $repo)
local ref2=$(make_commit $repo)
local ref3=$(make_commit $repo)

local dest=$TMPDIR/destination

get_uri_with_revision_at_depth "file://$repo" 1 $ref2 $dest | jq -e "
.version == {ref: $(echo $ref2 | jq -R .)}
"

test "$(git -C $dest rev-parse HEAD)" = $ref2
test -e $dest/.git/shallow
test "$(git -C $dest rev-list --all --count)" = 1
}

it_errors_with_revision_and_branch() {
local repo=$(init_repo)
local ref=$(make_commit $repo)
local dest=$TMPDIR/destination

set +e
output=$(get_uri_with_revision_and_branch "file://$repo" "master" $ref $dest 2>&1)
exit_code=$?
set -e

test "${exit_code}" != 0
echo "${output}" | grep "error: revision param is incompatible with branch"
}

it_errors_when_there_are_unknown_keys_in_params() {
local failed_output=$TMPDIR/get-unknown-keys-output
if get_uri_unknown_keys "some-uri" "some-dest" 2>"$failed_output"; then
Expand Down Expand Up @@ -1179,4 +1226,7 @@ run it_retains_tags_with_clean_tags_param
run it_returns_list_without_tags_in_metadata
run it_returns_list_of_all_tags_in_metadata
run it_can_get_from_url_at_branch_with_search_remote_refs
run it_can_get_with_revision
run it_can_get_with_revision_and_depth
run it_errors_with_revision_and_branch
run it_errors_when_there_are_unknown_keys_in_params
44 changes: 44 additions & 0 deletions test/helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,50 @@ get_uri_at_depth_at_ref() {
}" | ${resource_dir}/in "$4" | tee -a /dev/stderr
}

get_uri_with_revision() {
jq -n "{
source: {
uri: $(echo $1 | jq -R .)
},
params: {
revision: \"true\"
},
version: {
ref: $(echo $2 | jq -R .)
}
}" | ${resource_dir}/in "$3" | tee /dev/stderr
}

get_uri_with_revision_at_depth() {
jq -n "{
source: {
uri: $(echo $1 | jq -R .)
},
params: {
revision: \"true\",
depth: $(echo $2 | jq -R .)
},
version: {
ref: $(echo $3 | jq -R .)
}
}" | ${resource_dir}/in "$4" | tee /dev/stderr
}

get_uri_with_revision_and_branch() {
jq -n "{
source: {
uri: $(echo $1 | jq -R .),
branch: $(echo $2 | jq -R .)
},
params: {
revision: \"true\"
},
version: {
ref: $(echo $3 | jq -R .)
}
}" | ${resource_dir}/in "$4" | tee /dev/stderr
}

get_uri_with_submodules_at_depth() {
jq -n "{
source: {
Expand Down