Merge branch 'jc/quickfetch'
* jc/quickfetch: Make sure quickfetch is not fooled with a previous, incomplete fetch. git-fetch: use fetch--tool pick-rref to avoid local fetch from alternate git-fetch--tool pick-rref
This commit is contained in:
commit
e660e11b20
@ -436,10 +436,87 @@ static int expand_refs_wildcard(const char *ls_remote_result, int numrefs,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pick_rref(int sha1_only, const char *rref, const char *ls_remote_result)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
int lrr_count = lrr_count, i, pass;
|
||||||
|
const char *cp;
|
||||||
|
struct lrr {
|
||||||
|
const char *line;
|
||||||
|
const char *name;
|
||||||
|
int namelen;
|
||||||
|
int shown;
|
||||||
|
} *lrr_list = lrr_list;
|
||||||
|
|
||||||
|
for (pass = 0; pass < 2; pass++) {
|
||||||
|
/* pass 0 counts and allocates, pass 1 fills... */
|
||||||
|
cp = ls_remote_result;
|
||||||
|
i = 0;
|
||||||
|
while (1) {
|
||||||
|
const char *np;
|
||||||
|
while (*cp && isspace(*cp))
|
||||||
|
cp++;
|
||||||
|
if (!*cp)
|
||||||
|
break;
|
||||||
|
np = strchr(cp, '\n');
|
||||||
|
if (!np)
|
||||||
|
np = cp + strlen(cp);
|
||||||
|
if (pass) {
|
||||||
|
lrr_list[i].line = cp;
|
||||||
|
lrr_list[i].name = cp + 41;
|
||||||
|
lrr_list[i].namelen = np - (cp + 41);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
cp = np;
|
||||||
|
}
|
||||||
|
if (!pass) {
|
||||||
|
lrr_count = i;
|
||||||
|
lrr_list = xcalloc(lrr_count, sizeof(*lrr_list));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
const char *next;
|
||||||
|
int rreflen;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while (*rref && isspace(*rref))
|
||||||
|
rref++;
|
||||||
|
if (!*rref)
|
||||||
|
break;
|
||||||
|
next = strchr(rref, '\n');
|
||||||
|
if (!next)
|
||||||
|
next = rref + strlen(rref);
|
||||||
|
rreflen = next - rref;
|
||||||
|
|
||||||
|
for (i = 0; i < lrr_count; i++) {
|
||||||
|
struct lrr *lrr = &(lrr_list[i]);
|
||||||
|
|
||||||
|
if (rreflen == lrr->namelen &&
|
||||||
|
!memcmp(lrr->name, rref, rreflen)) {
|
||||||
|
if (!lrr->shown)
|
||||||
|
printf("%.*s\n",
|
||||||
|
sha1_only ? 40 : lrr->namelen + 41,
|
||||||
|
lrr->line);
|
||||||
|
lrr->shown = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lrr_count <= i) {
|
||||||
|
error("pick-rref: %.*s not found", rreflen, rref);
|
||||||
|
err = 1;
|
||||||
|
}
|
||||||
|
rref = next;
|
||||||
|
}
|
||||||
|
free(lrr_list);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
int force = 0;
|
int force = 0;
|
||||||
|
int sopt = 0;
|
||||||
|
|
||||||
while (1 < argc) {
|
while (1 < argc) {
|
||||||
const char *arg = argv[1];
|
const char *arg = argv[1];
|
||||||
@ -447,6 +524,8 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
|
|||||||
verbose = 1;
|
verbose = 1;
|
||||||
else if (!strcmp("-f", arg))
|
else if (!strcmp("-f", arg))
|
||||||
force = 1;
|
force = 1;
|
||||||
|
else if (!strcmp("-s", arg))
|
||||||
|
sopt = 1;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
argc--;
|
argc--;
|
||||||
@ -491,6 +570,11 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
|
|||||||
reflist = get_stdin();
|
reflist = get_stdin();
|
||||||
return parse_reflist(reflist);
|
return parse_reflist(reflist);
|
||||||
}
|
}
|
||||||
|
if (!strcmp("pick-rref", argv[1])) {
|
||||||
|
if (argc != 4)
|
||||||
|
return error("pick-rref takes 2 args");
|
||||||
|
return pick_rref(sopt, argv[2], argv[3]);
|
||||||
|
}
|
||||||
if (!strcmp("expand-refs-wildcard", argv[1])) {
|
if (!strcmp("expand-refs-wildcard", argv[1])) {
|
||||||
const char *reflist;
|
const char *reflist;
|
||||||
if (argc < 4)
|
if (argc < 4)
|
||||||
|
@ -113,6 +113,10 @@ static void show_object(struct object_array_entry *p)
|
|||||||
* confuse downstream git-pack-objects very badly.
|
* confuse downstream git-pack-objects very badly.
|
||||||
*/
|
*/
|
||||||
const char *ep = strchr(p->name, '\n');
|
const char *ep = strchr(p->name, '\n');
|
||||||
|
|
||||||
|
if (p->item->type == OBJ_BLOB && !has_sha1_file(p->item->sha1))
|
||||||
|
die("missing blob object '%s'", sha1_to_hex(p->item->sha1));
|
||||||
|
|
||||||
if (ep) {
|
if (ep) {
|
||||||
printf("%s %.*s\n", sha1_to_hex(p->item->sha1),
|
printf("%s %.*s\n", sha1_to_hex(p->item->sha1),
|
||||||
(int) (ep - p->name),
|
(int) (ep - p->name),
|
||||||
|
36
git-fetch.sh
36
git-fetch.sh
@ -176,11 +176,35 @@ fetch_all_at_once () {
|
|||||||
die "shallow clone with bundle is not supported"
|
die "shallow clone with bundle is not supported"
|
||||||
git-bundle unbundle "$remote" $rref ||
|
git-bundle unbundle "$remote" $rref ||
|
||||||
echo failed "$remote"
|
echo failed "$remote"
|
||||||
|
else
|
||||||
|
if test -d "$remote" &&
|
||||||
|
|
||||||
|
# The remote might be our alternate. With
|
||||||
|
# this optimization we will bypass fetch-pack
|
||||||
|
# altogether, which means we cannot be doing
|
||||||
|
# the shallow stuff at all.
|
||||||
|
test ! -f "$GIT_DIR/shallow" &&
|
||||||
|
test -z "$shallow_depth" &&
|
||||||
|
|
||||||
|
# See if all of what we are going to fetch are
|
||||||
|
# connected to our repository's tips, in which
|
||||||
|
# case we do not have to do any fetch.
|
||||||
|
theirs=$(git-fetch--tool -s pick-rref \
|
||||||
|
"$rref" "$ls_remote_result") &&
|
||||||
|
|
||||||
|
# This will barf when $theirs reach an object that
|
||||||
|
# we do not have in our repository. Otherwise,
|
||||||
|
# we already have everything the fetch would bring in.
|
||||||
|
git-rev-list --objects $theirs --not --all \
|
||||||
|
>/dev/null 2>/dev/null
|
||||||
|
then
|
||||||
|
git-fetch--tool pick-rref "$rref" "$ls_remote_result"
|
||||||
else
|
else
|
||||||
git-fetch-pack --thin $exec $keep $shallow_depth \
|
git-fetch-pack --thin $exec $keep $shallow_depth \
|
||||||
$quiet $no_progress "$remote" $rref ||
|
$quiet $no_progress "$remote" $rref ||
|
||||||
echo failed "$remote"
|
echo failed "$remote"
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
) |
|
) |
|
||||||
(
|
(
|
||||||
flags=
|
flags=
|
||||||
@ -239,16 +263,8 @@ fetch_per_ref () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Find $remote_name from ls-remote output.
|
# Find $remote_name from ls-remote output.
|
||||||
head=$(
|
head=$(git-fetch--tool -s pick-rref \
|
||||||
IFS=' '
|
"$remote_name" "$ls_remote_result")
|
||||||
echo "$ls_remote_result" |
|
|
||||||
while read sha1 name
|
|
||||||
do
|
|
||||||
test "z$name" = "z$remote_name" || continue
|
|
||||||
echo "$sha1"
|
|
||||||
break
|
|
||||||
done
|
|
||||||
)
|
|
||||||
expr "z$head" : "z$_x40\$" >/dev/null ||
|
expr "z$head" : "z$_x40\$" >/dev/null ||
|
||||||
die "No such ref $remote_name at $remote"
|
die "No such ref $remote_name at $remote"
|
||||||
echo >&2 "Fetching $remote_name from $remote using $proto"
|
echo >&2 "Fetching $remote_name from $remote using $proto"
|
||||||
|
89
t/t5502-quickfetch.sh
Executable file
89
t/t5502-quickfetch.sh
Executable file
@ -0,0 +1,89 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='test quickfetch from local'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
test_expect_success setup '
|
||||||
|
|
||||||
|
test_tick &&
|
||||||
|
echo ichi >file &&
|
||||||
|
git add file &&
|
||||||
|
git commit -m initial &&
|
||||||
|
|
||||||
|
cnt=$( (
|
||||||
|
git count-objects | sed -e "s/ *objects,.*//"
|
||||||
|
) ) &&
|
||||||
|
test $cnt -eq 3
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'clone without alternate' '
|
||||||
|
|
||||||
|
(
|
||||||
|
mkdir cloned &&
|
||||||
|
cd cloned &&
|
||||||
|
git init-db &&
|
||||||
|
git remote add -f origin ..
|
||||||
|
) &&
|
||||||
|
cnt=$( (
|
||||||
|
cd cloned &&
|
||||||
|
git count-objects | sed -e "s/ *objects,.*//"
|
||||||
|
) ) &&
|
||||||
|
test $cnt -eq 3
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'further commits in the original' '
|
||||||
|
|
||||||
|
test_tick &&
|
||||||
|
echo ni >file &&
|
||||||
|
git commit -a -m second &&
|
||||||
|
|
||||||
|
cnt=$( (
|
||||||
|
git count-objects | sed -e "s/ *objects,.*//"
|
||||||
|
) ) &&
|
||||||
|
test $cnt -eq 6
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'copy commit and tree but not blob by hand' '
|
||||||
|
|
||||||
|
git rev-list --objects HEAD |
|
||||||
|
git pack-objects --stdout |
|
||||||
|
(
|
||||||
|
cd cloned &&
|
||||||
|
git unpack-objects
|
||||||
|
) &&
|
||||||
|
|
||||||
|
cnt=$( (
|
||||||
|
cd cloned &&
|
||||||
|
git count-objects | sed -e "s/ *objects,.*//"
|
||||||
|
) ) &&
|
||||||
|
test $cnt -eq 6
|
||||||
|
|
||||||
|
blob=$(git rev-parse HEAD:file | sed -e "s|..|&/|") &&
|
||||||
|
test -f "cloned/.git/objects/$blob" &&
|
||||||
|
rm -f "cloned/.git/objects/$blob" &&
|
||||||
|
|
||||||
|
cnt=$( (
|
||||||
|
cd cloned &&
|
||||||
|
git count-objects | sed -e "s/ *objects,.*//"
|
||||||
|
) ) &&
|
||||||
|
test $cnt -eq 5
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'quickfetch should not leave a corrupted repository' '
|
||||||
|
|
||||||
|
(
|
||||||
|
cd cloned &&
|
||||||
|
git fetch
|
||||||
|
) &&
|
||||||
|
|
||||||
|
cnt=$( (
|
||||||
|
cd cloned &&
|
||||||
|
git count-objects | sed -e "s/ *objects,.*//"
|
||||||
|
) ) &&
|
||||||
|
test $cnt -eq 6
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in New Issue
Block a user