Skip to content

Commit df6b7bf

Browse files
author
Junio C Hamano
committed
Merge branch 'jc/globfetch'
* jc/globfetch: fetch-pack: do not barf when duplicate re patterns are given git-fetch: allow forcing glob pattern in refspec git-fetch: allow glob pattern in refspec git-fetch: fix dumb protocol transport to fetch from pack-pruned ref git-fetch: reuse ls-remote result.
2 parents 2570458 + 310b86d commit df6b7bf

File tree

3 files changed

+85
-20
lines changed

3 files changed

+85
-20
lines changed

fetch-pack.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,29 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
566566
return 0;
567567
}
568568

569+
static int remove_duplicates(int nr_heads, char **heads)
570+
{
571+
int src, dst;
572+
573+
for (src = dst = 0; src < nr_heads; src++) {
574+
/* If heads[src] is different from any of
575+
* heads[0..dst], push it in.
576+
*/
577+
int i;
578+
for (i = 0; i < dst; i++) {
579+
if (!strcmp(heads[i], heads[src]))
580+
break;
581+
}
582+
if (i < dst)
583+
continue;
584+
if (src != dst)
585+
heads[dst] = heads[src];
586+
dst++;
587+
}
588+
heads[dst] = 0;
589+
return dst;
590+
}
591+
569592
int main(int argc, char **argv)
570593
{
571594
int i, ret, nr_heads;
@@ -617,6 +640,8 @@ int main(int argc, char **argv)
617640
pid = git_connect(fd, dest, exec);
618641
if (pid < 0)
619642
return 1;
643+
if (heads && nr_heads)
644+
nr_heads = remove_duplicates(nr_heads, heads);
620645
ret = fetch_pack(fd, nr_heads, heads);
621646
close(fd[0]);
622647
close(fd[1]);

git-fetch.sh

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ then
8888
: >"$GIT_DIR/FETCH_HEAD"
8989
fi
9090

91+
# Global that is reused later
92+
ls_remote_result=$(git ls-remote $upload_pack "$remote") ||
93+
die "Cannot find the reflist at $remote"
94+
9195
append_fetch_head () {
9296
head_="$1"
9397
remote_="$2"
@@ -233,10 +237,7 @@ reflist=$(get_remote_refs_for_fetch "$@")
233237
if test "$tags"
234238
then
235239
taglist=`IFS=" " &&
236-
(
237-
git-ls-remote $upload_pack --tags "$remote" ||
238-
echo fail ouch
239-
) |
240+
echo "$ls_remote_result" |
240241
while read sha1 name
241242
do
242243
case "$sha1" in
@@ -245,6 +246,8 @@ then
245246
esac
246247
case "$name" in
247248
*^*) continue ;;
249+
refs/tags/*) ;;
250+
*) continue ;;
248251
esac
249252
if git-check-ref-format "$name"
250253
then
@@ -304,22 +307,20 @@ fetch_main () {
304307
"`git-repo-config --bool http.noEPSV`" = true ]; then
305308
noepsv_opt="--disable-epsv"
306309
fi
307-
max_depth=5
308-
depth=0
309-
head="ref: $remote_name"
310-
while (expr "z$head" : "zref:" && expr $depth \< $max_depth) >/dev/null
311-
do
312-
remote_name_quoted=$(@@PERL@@ -e '
313-
my $u = $ARGV[0];
314-
$u =~ s/^ref:\s*//;
315-
$u =~ s{([^-a-zA-Z0-9/.])}{sprintf"%%%02x",ord($1)}eg;
316-
print "$u";
317-
' "$head")
318-
head=$(curl -nsfL $curl_extra_args $noepsv_opt "$remote/$remote_name_quoted")
319-
depth=$( expr \( $depth + 1 \) )
320-
done
310+
311+
# Find $remote_name from ls-remote output.
312+
head=$(
313+
IFS=' '
314+
echo "$ls_remote_result" |
315+
while read sha1 name
316+
do
317+
test "z$name" = "z$remote_name" || continue
318+
echo "$sha1"
319+
break
320+
done
321+
)
321322
expr "z$head" : "z$_x40\$" >/dev/null ||
322-
die "Failed to fetch $remote_name from $remote"
323+
die "No such ref $remote_name at $remote"
323324
echo >&2 "Fetching $remote_name from $remote using $proto"
324325
git-http-fetch -v -a "$head" "$remote/" || exit
325326
;;
@@ -432,7 +433,7 @@ case "$no_tags$tags" in
432433
# effective only when we are following remote branch
433434
# using local tracking branch.
434435
taglist=$(IFS=" " &&
435-
git-ls-remote $upload_pack --tags "$remote" |
436+
echo "$ls_remote_result" |
436437
sed -n -e 's|^\('"$_x40"'\) \(refs/tags/.*\)^{}$|\1 \2|p' \
437438
-e 's|^\('"$_x40"'\) \(refs/tags/.*\)$|\1 \2|p' |
438439
while read sha1 name

git-parse-remote.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,43 @@ get_remote_default_refs_for_push () {
9090
esac
9191
}
9292

93+
# Called from canon_refs_list_for_fetch -d "$remote", which
94+
# is called from get_remote_default_refs_for_fetch to grok
95+
# refspecs that are retrieved from the configuration, but not
96+
# from get_remote_refs_for_fetch when it deals with refspecs
97+
# supplied on the command line. $ls_remote_result has the list
98+
# of refs available at remote.
99+
expand_refs_wildcard () {
100+
for ref
101+
do
102+
lref=${ref#'+'}
103+
# a non glob pattern is given back as-is.
104+
expr "z$lref" : 'zrefs/.*/\*:refs/.*/\*$' >/dev/null || {
105+
echo "$ref"
106+
continue
107+
}
108+
109+
from=`expr "z$lref" : 'z\(refs/.*/\)\*:refs/.*/\*$'`
110+
to=`expr "z$lref" : 'zrefs/.*/\*:\(refs/.*/\)\*$'`
111+
local_force=
112+
test "z$lref" = "z$ref" || local_force='+'
113+
echo "$ls_remote_result" |
114+
(
115+
IFS=' '
116+
while read sha1 name
117+
do
118+
mapped=${name#"$from"}
119+
if test "z$name" != "z${name#'^{}'}" ||
120+
test "z$name" = "z$mapped"
121+
then
122+
continue
123+
fi
124+
echo "${local_force}${name}:${to}${mapped}"
125+
done
126+
)
127+
done
128+
}
129+
93130
# Subroutine to canonicalize remote:local notation.
94131
canon_refs_list_for_fetch () {
95132
# If called from get_remote_default_refs_for_fetch
@@ -107,6 +144,8 @@ canon_refs_list_for_fetch () {
107144
merge_branches=$(git-repo-config \
108145
--get-all "branch.${curr_branch}.merge")
109146
fi
147+
set x $(expand_refs_wildcard "$@")
148+
shift
110149
fi
111150
for ref
112151
do

0 commit comments

Comments
 (0)