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;
|
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 cmd_fetch__tool(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int verbose = 0;
|
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 error("parse-reflist takes 1 arg");
|
||||||
return parse_reflist(argv[2]);
|
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]);
|
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
|
# is to help prevent randomly "globbed" ref from being chosen as
|
||||||
# a merge candidate
|
# a merge candidate
|
||||||
expand_refs_wildcard () {
|
expand_refs_wildcard () {
|
||||||
remote="$1"
|
git fetch--tool expand-refs-wildcard "$ls_remote_result" "$@"
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Subroutine to canonicalize remote:local notation.
|
# Subroutine to canonicalize remote:local notation.
|
||||||
|
Reference in New Issue
Block a user