#!/bin/sh # # Copyright (c) 2021 Jiang Xin # test_description='Test git-bundle' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY"/lib-bundle.sh # Create a commit or tag and set the variable with the object ID. test_commit_setvar () { notick= signoff= indir= merge= tag= var= while test $# != 0 do case "$1" in --merge) merge=t ;; --tag) tag=t ;; --notick) notick=t ;; --signoff) signoff="$1" ;; -C) shift indir="$1" ;; -*) echo >&2 "error: unknown option $1" return 1 ;; *) break ;; esac shift done if test $# -lt 2 then echo >&2 "error: test_commit_setvar must have at least 2 arguments" return 1 fi var=$1 shift indir=${indir:+"$indir"/} if test -z "$notick" then test_tick fi && if test -n "$merge" then git ${indir:+ -C "$indir"} merge --no-edit --no-ff \ ${2:+-m "$2"} "$1" && oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD) elif test -n "$tag" then git ${indir:+ -C "$indir"} tag -m "$1" "$1" "${2:-HEAD}" && oid=$(git ${indir:+ -C "$indir"} rev-parse "$1") else file=${2:-"$1.t"} && echo "${3-$1}" >"$indir$file" && git ${indir:+ -C "$indir"} add "$file" && git ${indir:+ -C "$indir"} commit $signoff -m "$1" && oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD) fi && eval $var=$oid } # Format the output of git commands to make a user-friendly and stable # text. We can easily prepare the expect text without having to worry # about future changes of the commit ID and spaces of the output. make_user_friendly_and_stable_output () { sed \ -e "s/${A%${A#???????}}[0-9a-f]*//g" \ -e "s/${B%${B#???????}}[0-9a-f]*//g" \ -e "s/${C%${C#???????}}[0-9a-f]*//g" \ -e "s/${D%${D#???????}}[0-9a-f]*//g" \ -e "s/${E%${E#???????}}[0-9a-f]*//g" \ -e "s/${F%${F#???????}}[0-9a-f]*//g" \ -e "s/${G%${G#???????}}[0-9a-f]*//g" \ -e "s/${H%${H#???????}}[0-9a-f]*//g" \ -e "s/${I%${I#???????}}[0-9a-f]*//g" \ -e "s/${J%${J#???????}}[0-9a-f]*//g" \ -e "s/${K%${K#???????}}[0-9a-f]*//g" \ -e "s/${L%${L#???????}}[0-9a-f]*//g" \ -e "s/${M%${M#???????}}[0-9a-f]*//g" \ -e "s/${N%${N#???????}}[0-9a-f]*//g" \ -e "s/${O%${O#???????}}[0-9a-f]*//g" \ -e "s/${P%${P#???????}}[0-9a-f]*//g" \ -e "s/${TAG1%${TAG1#???????}}[0-9a-f]*//g" \ -e "s/${TAG2%${TAG2#???????}}[0-9a-f]*//g" \ -e "s/${TAG3%${TAG3#???????}}[0-9a-f]*//g" \ -e "s/ *\$//" } # (C) (D, pull/1/head, topic/1) # o --- o # / \ (L) # / \ o (H, topic/2) (M, tag:v2) # / (F) \ / (N, tag:v3) # / o --------- o (G, pull/2/head) o --- o --- o (release) # / / \ \ / \ # o --- o --- o -------- o -- o ------------------ o ------- o --- o (main) # (A) (B) (E, tag:v1) (I) (J) (K) (O) (P) # test_expect_success 'setup' ' # Try to make a stable fixed width for abbreviated commit ID, # this fixed-width oid will be replaced with "". git config core.abbrev 7 && # branch main: commit A & B test_commit_setvar A "Commit A" main.txt && test_commit_setvar B "Commit B" main.txt && # branch topic/1: commit C & D, refs/pull/1/head git checkout -b topic/1 && test_commit_setvar C "Commit C" topic-1.txt && test_commit_setvar D "Commit D" topic-1.txt && git update-ref refs/pull/1/head HEAD && # branch topic/1: commit E, tag v1 git checkout main && test_commit_setvar E "Commit E" main.txt && test_commit_setvar --tag TAG1 v1 && # branch topic/2: commit F & G, refs/pull/2/head git checkout -b topic/2 && test_commit_setvar F "Commit F" topic-2.txt && test_commit_setvar G "Commit G" topic-2.txt && git update-ref refs/pull/2/head HEAD && test_commit_setvar H "Commit H" topic-2.txt && # branch main: merge commit I & J git checkout main && test_commit_setvar --merge I topic/1 "Merge commit I" && test_commit_setvar --merge J refs/pull/2/head "Merge commit J" && # branch main: commit K git checkout main && test_commit_setvar K "Commit K" main.txt && # branch release: git checkout -b release && test_commit_setvar L "Commit L" release.txt && test_commit_setvar M "Commit M" release.txt && test_commit_setvar --tag TAG2 v2 && test_commit_setvar N "Commit N" release.txt && test_commit_setvar --tag TAG3 v3 && # branch main: merge commit O, commit P git checkout main && test_commit_setvar --merge O tags/v2 "Merge commit O" && test_commit_setvar P "Commit P" main.txt ' test_expect_success 'create bundle from special rev: main^!' ' git bundle create special-rev.bdl "main^!" && git bundle list-heads special-rev.bdl | make_user_friendly_and_stable_output >actual && cat >expect <<-\EOF && refs/heads/main EOF test_cmp expect actual && git bundle verify special-rev.bdl | make_user_friendly_and_stable_output >actual && cat >expect <<-\EOF && The bundle contains this ref: refs/heads/main The bundle requires this ref: EOF test_cmp expect actual && test_bundle_object_count special-rev.bdl 3 ' test_expect_success 'create bundle with --max-count option' ' git bundle create max-count.bdl --max-count 1 \ main \ "^release" \ refs/tags/v1 \ refs/pull/1/head \ refs/pull/2/head && git bundle verify max-count.bdl | make_user_friendly_and_stable_output >actual && cat >expect <<-\EOF && The bundle contains these 2 refs: refs/heads/main refs/tags/v1 The bundle requires this ref: EOF test_cmp expect actual && test_bundle_object_count max-count.bdl 4 ' test_expect_success 'create bundle with --since option' ' git log -1 --pretty="%ad" $M >actual && cat >expect <<-\EOF && Thu Apr 7 15:26:13 2005 -0700 EOF test_cmp expect actual && git bundle create since.bdl \ --since "Thu Apr 7 15:27:00 2005 -0700" \ --all && git bundle verify since.bdl | make_user_friendly_and_stable_output >actual && cat >expect <<-\EOF && The bundle contains these 5 refs: refs/heads/main refs/heads/release refs/tags/v2 refs/tags/v3 HEAD The bundle requires these 2 refs: EOF test_cmp expect actual && test_bundle_object_count --thin since.bdl 13 ' test_expect_success 'create bundle 1 - no prerequisites' ' # create bundle from args git bundle create 1.bdl topic/1 topic/2 && # create bundle from stdin cat >input <<-\EOF && topic/1 topic/2 EOF git bundle create stdin-1.bdl --stdin expect <<-\EOF && The bundle contains these 2 refs: refs/heads/topic/1 refs/heads/topic/2 The bundle records a complete history. EOF # verify bundle, which has no prerequisites git bundle verify 1.bdl | make_user_friendly_and_stable_output >actual && test_cmp expect actual && git bundle verify stdin-1.bdl | make_user_friendly_and_stable_output >actual && test_cmp expect actual && test_bundle_object_count 1.bdl 24 && test_bundle_object_count stdin-1.bdl 24 ' test_expect_success 'create bundle 2 - has prerequisites' ' # create bundle from args git bundle create 2.bdl \ --ignore-missing \ ^topic/deleted \ ^$D \ ^topic/2 \ release && # create bundle from stdin # input has a non-exist reference: "topic/deleted" cat >input <<-EOF && ^topic/deleted ^$D ^topic/2 EOF git bundle create stdin-2.bdl \ --ignore-missing \ --stdin \ release expect <<-\EOF && The bundle contains this ref: refs/heads/release The bundle requires these 3 refs: EOF git bundle verify 2.bdl | make_user_friendly_and_stable_output >actual && test_cmp expect actual && git bundle verify stdin-2.bdl | make_user_friendly_and_stable_output >actual && test_cmp expect actual && test_bundle_object_count 2.bdl 16 && test_bundle_object_count stdin-2.bdl 16 ' test_expect_success 'fail to verify bundle without prerequisites' ' git init --bare test1.git && cat >expect <<-\EOF && error: Repository lacks these prerequisite commits: error: error: error: EOF test_must_fail git -C test1.git bundle verify ../2.bdl 2>&1 | make_user_friendly_and_stable_output >actual && test_cmp expect actual && test_must_fail git -C test1.git bundle verify ../stdin-2.bdl 2>&1 | make_user_friendly_and_stable_output >actual && test_cmp expect actual ' test_expect_success 'create bundle 3 - two refs, same object' ' # create bundle from args git bundle create --version=3 3.bdl \ ^release \ ^topic/1 \ ^topic/2 \ main \ HEAD && # create bundle from stdin cat >input <<-\EOF && ^release ^topic/1 ^topic/2 EOF git bundle create --version=3 stdin-3.bdl \ --stdin \ main HEAD expect <<-\EOF && The bundle contains these 2 refs: refs/heads/main HEAD The bundle requires these 2 refs: EOF git bundle verify 3.bdl | make_user_friendly_and_stable_output >actual && test_cmp expect actual && git bundle verify stdin-3.bdl | make_user_friendly_and_stable_output >actual && test_cmp expect actual && test_bundle_object_count 3.bdl 4 && test_bundle_object_count stdin-3.bdl 4 ' test_expect_success 'create bundle 4 - with tags' ' # create bundle from args git bundle create 4.bdl \ ^main \ ^release \ ^topic/1 \ ^topic/2 \ --all && # create bundle from stdin cat >input <<-\EOF && ^main ^release ^topic/1 ^topic/2 EOF git bundle create stdin-4.bdl \ --ignore-missing \ --stdin \ --all expect <<-\EOF && The bundle contains these 3 refs: refs/tags/v1 refs/tags/v2 refs/tags/v3 The bundle records a complete history. EOF git bundle verify 4.bdl | make_user_friendly_and_stable_output >actual && test_cmp expect actual && git bundle verify stdin-4.bdl | make_user_friendly_and_stable_output >actual && test_cmp expect actual && test_bundle_object_count 4.bdl 3 && test_bundle_object_count stdin-4.bdl 3 ' test_expect_success 'clone from bundle' ' git clone --mirror 1.bdl mirror.git && git -C mirror.git show-ref | make_user_friendly_and_stable_output >actual && cat >expect <<-\EOF && refs/heads/topic/1 refs/heads/topic/2 EOF test_cmp expect actual && git -C mirror.git fetch ../2.bdl "+refs/*:refs/*" && git -C mirror.git show-ref | make_user_friendly_and_stable_output >actual && cat >expect <<-\EOF && refs/heads/release refs/heads/topic/1 refs/heads/topic/2 EOF test_cmp expect actual && git -C mirror.git fetch ../3.bdl "+refs/*:refs/*" && git -C mirror.git show-ref | make_user_friendly_and_stable_output >actual && cat >expect <<-\EOF && refs/heads/main refs/heads/release refs/heads/topic/1 refs/heads/topic/2 EOF test_cmp expect actual && git -C mirror.git fetch ../4.bdl "+refs/*:refs/*" && git -C mirror.git show-ref | make_user_friendly_and_stable_output >actual && cat >expect <<-\EOF && refs/heads/main refs/heads/release refs/heads/topic/1 refs/heads/topic/2 refs/tags/v1 refs/tags/v2 refs/tags/v3 EOF test_cmp expect actual ' test_done