git-fetch: rewrite expand_ref_wildcard in C
This does not seem to make measurable improvement when dealing with 1000 unpacked refs, but we would need something like it if we were to do a full rewrite in C somedaoy. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
@ -323,6 +323,91 @@ static int parse_reflist(const char *reflist)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int expand_refs_wildcard(const char *ls_remote_result, int numrefs,
|
||||
const char **refs)
|
||||
{
|
||||
int i, matchlen, replacelen;
|
||||
int found_one = 0;
|
||||
const char *remote = *refs++;
|
||||
numrefs--;
|
||||
|
||||
if (numrefs == 0) {
|
||||
fprintf(stderr, "Nothing specified for fetching with remote.%s.fetch\n",
|
||||
remote);
|
||||
printf("empty\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < numrefs; i++) {
|
||||
const char *ref = refs[i];
|
||||
const char *lref = ref;
|
||||
const char *colon;
|
||||
const char *tail;
|
||||
const char *ls;
|
||||
const char *next;
|
||||
|
||||
if (*lref == '+')
|
||||
lref++;
|
||||
colon = strchr(lref, ':');
|
||||
tail = lref + strlen(lref);
|
||||
if (!(colon &&
|
||||
2 < colon - lref &&
|
||||
colon[-1] == '*' &&
|
||||
colon[-2] == '/' &&
|
||||
2 < tail - (colon + 1) &&
|
||||
tail[-1] == '*' &&
|
||||
tail[-2] == '/')) {
|
||||
/* not a glob */
|
||||
if (!found_one++)
|
||||
printf("explicit\n");
|
||||
printf("%s\n", ref);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* glob */
|
||||
if (!found_one++)
|
||||
printf("glob\n");
|
||||
|
||||
/* lref to colon-2 is remote hierarchy name;
|
||||
* colon+1 to tail-2 is local.
|
||||
*/
|
||||
matchlen = (colon-1) - lref;
|
||||
replacelen = (tail-1) - (colon+1);
|
||||
for (ls = ls_remote_result; ls; ls = next) {
|
||||
const char *eol;
|
||||
unsigned char sha1[20];
|
||||
int namelen;
|
||||
|
||||
while (*ls && isspace(*ls))
|
||||
ls++;
|
||||
next = strchr(ls, '\n');
|
||||
eol = !next ? (ls + strlen(ls)) : next;
|
||||
if (!memcmp("^{}", eol-3, 3))
|
||||
continue;
|
||||
if (get_sha1_hex(ls, sha1))
|
||||
continue;
|
||||
ls += 40;
|
||||
while (ls < eol && isspace(*ls))
|
||||
ls++;
|
||||
/* ls to next (or eol) is the name.
|
||||
* is it identical to lref to colon-2?
|
||||
*/
|
||||
if ((eol - ls) <= matchlen ||
|
||||
strncmp(ls, lref, matchlen))
|
||||
continue;
|
||||
|
||||
/* Yes, it is a match */
|
||||
namelen = eol - ls;
|
||||
if (lref != ref)
|
||||
putchar('+');
|
||||
printf("%.*s:%.*s%.*s\n",
|
||||
namelen, ls,
|
||||
replacelen, colon + 1,
|
||||
namelen - matchlen, ls + matchlen);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int verbose = 0;
|
||||
@ -380,6 +465,11 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
|
||||
return error("parse-reflist takes 1 arg");
|
||||
return parse_reflist(argv[2]);
|
||||
}
|
||||
if (!strcmp("expand-refs-wildcard", argv[1])) {
|
||||
if (argc < 4)
|
||||
return error("expand-refs-wildcard takes at least 2 args");
|
||||
return expand_refs_wildcard(argv[2], argc - 3, argv + 3);
|
||||
}
|
||||
|
||||
return error("Unknown subcommand: %s", argv[1]);
|
||||
}
|
||||
|
@ -81,51 +81,7 @@ get_remote_default_refs_for_push () {
|
||||
# is to help prevent randomly "globbed" ref from being chosen as
|
||||
# a merge candidate
|
||||
expand_refs_wildcard () {
|
||||
remote="$1"
|
||||
shift
|
||||
first_one=yes
|
||||
if test "$#" = 0
|
||||
then
|
||||
echo empty
|
||||
echo >&2 "Nothing specified for fetching with remote.$remote.fetch"
|
||||
fi
|
||||
for ref
|
||||
do
|
||||
lref=${ref#'+'}
|
||||
# a non glob pattern is given back as-is.
|
||||
expr "z$lref" : 'zrefs/.*/\*:refs/.*/\*$' >/dev/null || {
|
||||
if test -n "$first_one"
|
||||
then
|
||||
echo "explicit"
|
||||
first_one=
|
||||
fi
|
||||
echo "$ref"
|
||||
continue
|
||||
}
|
||||
|
||||
# glob
|
||||
if test -n "$first_one"
|
||||
then
|
||||
echo "glob"
|
||||
first_one=
|
||||
fi
|
||||
from=`expr "z$lref" : 'z\(refs/.*/\)\*:refs/.*/\*$'`
|
||||
to=`expr "z$lref" : 'zrefs/.*/\*:\(refs/.*/\)\*$'`
|
||||
local_force=
|
||||
test "z$lref" = "z$ref" || local_force='+'
|
||||
echo "$ls_remote_result" |
|
||||
sed -e '/\^{}$/d' |
|
||||
(
|
||||
IFS=' '
|
||||
while read sha1 name
|
||||
do
|
||||
# ignore the ones that do not start with $from
|
||||
mapped=${name#"$from"}
|
||||
test "z$name" = "z$mapped" && continue
|
||||
echo "${local_force}${name}:${to}${mapped}"
|
||||
done
|
||||
)
|
||||
done
|
||||
git fetch--tool expand-refs-wildcard "$ls_remote_result" "$@"
|
||||
}
|
||||
|
||||
# Subroutine to canonicalize remote:local notation.
|
||||
|
Reference in New Issue
Block a user