Skip to content

Commit 1f7d1a5

Browse files
author
Junio C Hamano
committed
git-clone --reference: saner handling of borrowed symrefs.
When using --reference to borrow objects from a neighbouring repository while cloning, we copy the entire set of refs under temporary "refs/reference-tmp/refs" space and set up the object alternates. However, a textual symref copied this way would not point at the right place, and causes later steps to emit error messages (which is harmless but still alarming). This is most visible when using a clone created with the separate-remote layout as a reference, because such a repository would have refs/remotes/origin/HEAD with 'ref: refs/remotes/origin/master' as its contents. Although we do not create symbolic-link based refs anymore, they have the same problem because they are always supposed to be relative to refs/ hierarchy (we dereference by hand, so it only is good for HEAD and nothing else). In either case, the solution is simply to remove them after copying under refs/reference-tmp; if a symref points at a true ref, that true ref itself is enough to ensure that objects reachable from it do not needlessly get fetched. Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent ec80489 commit 1f7d1a5

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

git-clone.sh

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,34 @@ then
190190
(cd "$GIT_DIR/refs" &&
191191
mkdir reference-tmp &&
192192
cd reference-tmp &&
193-
tar xf -)
193+
tar xf - &&
194+
find refs ! -type d -print |
195+
while read ref
196+
do
197+
if test -h "$ref"
198+
then
199+
# Old-style symbolic link ref. Not likely
200+
# to appear under refs/ but we might as well
201+
# deal with them.
202+
:
203+
elif test -f "$ref"
204+
then
205+
point=$(cat "$ref") &&
206+
case "$point" in
207+
'ref: '*) ;;
208+
*) continue ;;
209+
esac
210+
fi
211+
# The above makes true ref to 'continue' and
212+
# we will come here when we are looking at
213+
# symbolic link ref or a textual symref (or
214+
# garbage, like fifo).
215+
# The true ref pointed at by it is enough to
216+
# ensure that we do not fetch objects reachable
217+
# from it.
218+
rm -f "$ref"
219+
done
220+
)
194221
else
195222
die "reference repository '$reference' is not a local directory."
196223
fi

t/t5700-clone-reference.sh

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ git prune'
2626

2727
cd "$base_dir"
2828

29-
test_expect_success 'cloning with reference' \
29+
test_expect_success 'cloning with reference (-l -s)' \
3030
'git clone -l -s --reference B A C'
3131

3232
cd "$base_dir"
@@ -50,6 +50,28 @@ diff expected current'
5050

5151
cd "$base_dir"
5252

53+
test_expect_success 'cloning with reference (no -l -s)' \
54+
'git clone --reference B A D'
55+
56+
cd "$base_dir"
57+
58+
test_expect_success 'existence of info/alternates' \
59+
'test `wc -l <D/.git/objects/info/alternates` = 1'
60+
61+
cd "$base_dir"
62+
63+
test_expect_success 'pulling from reference' \
64+
'cd D && git pull ../B'
65+
66+
cd "$base_dir"
67+
68+
test_expect_success 'that reference gets used' \
69+
'cd D && echo "0 objects, 0 kilobytes" > expected &&
70+
git count-objects > current &&
71+
diff expected current'
72+
73+
cd "$base_dir"
74+
5375
test_expect_success 'updating origin' \
5476
'cd A &&
5577
echo third > file3 &&
@@ -75,4 +97,20 @@ diff expected current'
7597

7698
cd "$base_dir"
7799

100+
test_expect_success 'pulling changes from origin' \
101+
'cd D &&
102+
git pull origin'
103+
104+
cd "$base_dir"
105+
106+
# the 5 local objects are expected; file3 blob, commit in A to add it
107+
# and its tree, and 2 are our tree and the merge commit.
108+
test_expect_success 'check objects expected to exist locally' \
109+
'cd D &&
110+
echo "5 objects" > expected &&
111+
git count-objects | cut -d, -f1 > current &&
112+
diff expected current'
113+
114+
cd "$base_dir"
115+
78116
test_done

0 commit comments

Comments
 (0)