|  | #!/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]*/<COMMIT-A>/g" \ | 
|  | -e "s/${B%${B#???????}}[0-9a-f]*/<COMMIT-B>/g" \ | 
|  | -e "s/${C%${C#???????}}[0-9a-f]*/<COMMIT-C>/g" \ | 
|  | -e "s/${D%${D#???????}}[0-9a-f]*/<COMMIT-D>/g" \ | 
|  | -e "s/${E%${E#???????}}[0-9a-f]*/<COMMIT-E>/g" \ | 
|  | -e "s/${F%${F#???????}}[0-9a-f]*/<COMMIT-F>/g" \ | 
|  | -e "s/${G%${G#???????}}[0-9a-f]*/<COMMIT-G>/g" \ | 
|  | -e "s/${H%${H#???????}}[0-9a-f]*/<COMMIT-H>/g" \ | 
|  | -e "s/${I%${I#???????}}[0-9a-f]*/<COMMIT-I>/g" \ | 
|  | -e "s/${J%${J#???????}}[0-9a-f]*/<COMMIT-J>/g" \ | 
|  | -e "s/${K%${K#???????}}[0-9a-f]*/<COMMIT-K>/g" \ | 
|  | -e "s/${L%${L#???????}}[0-9a-f]*/<COMMIT-L>/g" \ | 
|  | -e "s/${M%${M#???????}}[0-9a-f]*/<COMMIT-M>/g" \ | 
|  | -e "s/${N%${N#???????}}[0-9a-f]*/<COMMIT-N>/g" \ | 
|  | -e "s/${O%${O#???????}}[0-9a-f]*/<COMMIT-O>/g" \ | 
|  | -e "s/${P%${P#???????}}[0-9a-f]*/<COMMIT-P>/g" \ | 
|  | -e "s/${TAG1%${TAG1#???????}}[0-9a-f]*/<TAG-1>/g" \ | 
|  | -e "s/${TAG2%${TAG2#???????}}[0-9a-f]*/<TAG-2>/g" \ | 
|  | -e "s/${TAG3%${TAG3#???????}}[0-9a-f]*/<TAG-3>/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 "<OID>". | 
|  | 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 && | 
|  | <COMMIT-P> 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: | 
|  | <COMMIT-P> refs/heads/main | 
|  | The bundle requires this ref: | 
|  | <COMMIT-O> | 
|  | 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: | 
|  | <COMMIT-P> refs/heads/main | 
|  | <TAG-1> refs/tags/v1 | 
|  | The bundle requires this ref: | 
|  | <COMMIT-O> | 
|  | 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: | 
|  | <COMMIT-P> refs/heads/main | 
|  | <COMMIT-N> refs/heads/release | 
|  | <TAG-2> refs/tags/v2 | 
|  | <TAG-3> refs/tags/v3 | 
|  | <COMMIT-P> HEAD | 
|  | The bundle requires these 2 refs: | 
|  | <COMMIT-M> | 
|  | <COMMIT-K> | 
|  | 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 <input && | 
|  |  | 
|  | cat >expect <<-\EOF && | 
|  | The bundle contains these 2 refs: | 
|  | <COMMIT-D> refs/heads/topic/1 | 
|  | <COMMIT-H> 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 <input && | 
|  |  | 
|  | cat >expect <<-\EOF && | 
|  | The bundle contains this ref: | 
|  | <COMMIT-N> refs/heads/release | 
|  | The bundle requires these 3 refs: | 
|  | <COMMIT-D> | 
|  | <COMMIT-E> | 
|  | <COMMIT-G> | 
|  | 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: <COMMIT-D> | 
|  | error: <COMMIT-E> | 
|  | error: <COMMIT-G> | 
|  | 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 <input && | 
|  |  | 
|  | cat >expect <<-\EOF && | 
|  | The bundle contains these 2 refs: | 
|  | <COMMIT-P> refs/heads/main | 
|  | <COMMIT-P> HEAD | 
|  | The bundle requires these 2 refs: | 
|  | <COMMIT-M> | 
|  | <COMMIT-K> | 
|  | 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 <input && | 
|  |  | 
|  | cat >expect <<-\EOF && | 
|  | The bundle contains these 3 refs: | 
|  | <TAG-1> refs/tags/v1 | 
|  | <TAG-2> refs/tags/v2 | 
|  | <TAG-3> 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 && | 
|  | <COMMIT-D> refs/heads/topic/1 | 
|  | <COMMIT-H> 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 && | 
|  | <COMMIT-N> refs/heads/release | 
|  | <COMMIT-D> refs/heads/topic/1 | 
|  | <COMMIT-H> 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 && | 
|  | <COMMIT-P> refs/heads/main | 
|  | <COMMIT-N> refs/heads/release | 
|  | <COMMIT-D> refs/heads/topic/1 | 
|  | <COMMIT-H> 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 && | 
|  | <COMMIT-P> refs/heads/main | 
|  | <COMMIT-N> refs/heads/release | 
|  | <COMMIT-D> refs/heads/topic/1 | 
|  | <COMMIT-H> refs/heads/topic/2 | 
|  | <TAG-1> refs/tags/v1 | 
|  | <TAG-2> refs/tags/v2 | 
|  | <TAG-3> refs/tags/v3 | 
|  | EOF | 
|  | test_cmp expect actual | 
|  | ' | 
|  |  | 
|  | test_done |