Browse Source

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
maint
Junio C Hamano 18 years ago
parent
commit
e660e11b20
  1. 84
      builtin-fetch--tool.c
  2. 4
      builtin-rev-list.c
  3. 42
      git-fetch.sh
  4. 89
      t/t5502-quickfetch.sh

84
builtin-fetch--tool.c

@ -436,10 +436,87 @@ static int expand_refs_wildcard(const char *ls_remote_result, int numrefs, @@ -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) @@ -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) @@ -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)

4
builtin-rev-list.c

@ -113,6 +113,10 @@ static void show_object(struct object_array_entry *p) @@ -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

@ -177,9 +177,33 @@ fetch_all_at_once () { @@ -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 () { @@ -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

@ -0,0 +1,89 @@ @@ -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…
Cancel
Save