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;
|
||||
}
|
||||
|
||||
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 verbose = 0;
|
||||
int force = 0;
|
||||
int sopt = 0;
|
||||
|
||||
while (1 < argc) {
|
||||
const char *arg = argv[1];
|
||||
@ -447,6 +524,8 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
|
||||
verbose = 1;
|
||||
else if (!strcmp("-f", arg))
|
||||
force = 1;
|
||||
else if (!strcmp("-s", arg))
|
||||
sopt = 1;
|
||||
else
|
||||
break;
|
||||
argc--;
|
||||
@ -491,6 +570,11 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
|
||||
reflist = get_stdin();
|
||||
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])) {
|
||||
const char *reflist;
|
||||
if (argc < 4)
|
||||
|
@ -113,6 +113,10 @@ static void show_object(struct object_array_entry *p)
|
||||
* confuse downstream git-pack-objects very badly.
|
||||
*/
|
||||
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) {
|
||||
printf("%s %.*s\n", sha1_to_hex(p->item->sha1),
|
||||
(int) (ep - p->name),
|
||||
|
42
git-fetch.sh
42
git-fetch.sh
@ -177,9 +177,33 @@ fetch_all_at_once () {
|
||||
git-bundle unbundle "$remote" $rref ||
|
||||
echo failed "$remote"
|
||||
else
|
||||
git-fetch-pack --thin $exec $keep $shallow_depth \
|
||||
$quiet $no_progress "$remote" $rref ||
|
||||
echo failed "$remote"
|
||||
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
|
||||
git-fetch-pack --thin $exec $keep $shallow_depth \
|
||||
$quiet $no_progress "$remote" $rref ||
|
||||
echo failed "$remote"
|
||||
fi
|
||||
fi
|
||||
) |
|
||||
(
|
||||
@ -239,16 +263,8 @@ fetch_per_ref () {
|
||||
fi
|
||||
|
||||
# Find $remote_name from ls-remote output.
|
||||
head=$(
|
||||
IFS=' '
|
||||
echo "$ls_remote_result" |
|
||||
while read sha1 name
|
||||
do
|
||||
test "z$name" = "z$remote_name" || continue
|
||||
echo "$sha1"
|
||||
break
|
||||
done
|
||||
)
|
||||
head=$(git-fetch--tool -s pick-rref \
|
||||
"$remote_name" "$ls_remote_result")
|
||||
expr "z$head" : "z$_x40\$" >/dev/null ||
|
||||
die "No such ref $remote_name at $remote"
|
||||
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