diff options
author | Junio C Hamano <junio@hera.kernel.org> | 2005-10-20 17:06:15 -0700 |
---|---|---|
committer | Junio C Hamano <junio@hera.kernel.org> | 2005-10-20 17:06:15 -0700 |
commit | bfadbeddd1b54af8ab08a6c556c43c756ec85588 (patch) | |
tree | 50f9bed9a78e1f51178ebf6be3cd9c20b2ffcb0b /fetch-pack.c | |
parent | ea5a65a59916503d2a14369c46b1023384d51645 (diff) | |
parent | 6e1c6c103c522d01829f3a63992a023ff031e851 (diff) | |
download | git-bfadbeddd1b54af8ab08a6c556c43c756ec85588.tar.gz |
Merge /pub/scm/git/git to recover lost side branch
Sorry for the mistake of rewinding something already pushed out.
This recovers the side branch lost by that mistake, specifically
ea5a65a59916503d2a14369c46b1023384d51645 commit.
Signed-off-by: Junio C Hamano <junio@hera.kernel.org>
Diffstat (limited to 'fetch-pack.c')
-rw-r--r-- | fetch-pack.c | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/fetch-pack.c b/fetch-pack.c index 969e72a781..8566ab1744 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -12,31 +12,66 @@ static const char fetch_pack_usage[] = "git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>..."; static const char *exec = "git-upload-pack"; +#define COMPLETE (1U << 0) + static int find_common(int fd[2], unsigned char *result_sha1, struct ref *refs) { int fetching; static char line[1000]; - int count = 0, flushes = 0, retval; + static char rev_command[1024]; + int count = 0, flushes = 0, retval, rev_command_len; FILE *revs; - revs = popen("git-rev-list $(git-rev-parse --all)", "r"); - if (!revs) - die("unable to run 'git-rev-list'"); - + strcpy(rev_command, "git-rev-list $(git-rev-parse --all)"); + rev_command_len = strlen(rev_command); fetching = 0; for ( ; refs ; refs = refs->next) { unsigned char *remote = refs->old_sha1; - unsigned char *local = refs->new_sha1; + struct object *o; - if (!memcmp(remote, local, 20)) + /* + * If that object is complete (i.e. it is an ancestor of a + * local ref), we tell them we have it but do not have to + * tell them about its ancestors, which they already know + * about. + * + * We use lookup_object here because we are only + * interested in the case we *know* the object is + * reachable and we have already scanned it. + */ + if (((o = lookup_object(remote)) != NULL) && + (o->flags & COMPLETE)) { + struct commit_list *p; + struct commit *commit = + (struct commit *) (o = deref_tag(o)); + if (!o) + goto repair; + if (o->type != commit_type) + continue; + p = commit->parents; + while (p && + rev_command_len + 44 < sizeof(rev_command)) { + snprintf(rev_command + rev_command_len, 44, + " ^%s", + sha1_to_hex(p->item->object.sha1)); + rev_command_len += 43; + p = p->next; + } continue; + } + repair: packet_write(fd[1], "want %s\n", sha1_to_hex(remote)); fetching++; } packet_flush(fd[1]); if (!fetching) return 1; + + revs = popen(rev_command, "r"); + if (!revs) + die("unable to run 'git-rev-list'"); + flushes = 1; retval = -1; while (fgets(line, sizeof(line), revs) != NULL) { @@ -81,7 +116,6 @@ static int find_common(int fd[2], unsigned char *result_sha1, return retval; } -#define COMPLETE (1U << 0) static struct commit_list *complete = NULL; static int mark_complete(const char *path, const unsigned char *sha1) @@ -89,10 +123,13 @@ static int mark_complete(const char *path, const unsigned char *sha1) struct object *o = parse_object(sha1); while (o && o->type == tag_type) { + struct tag *t = (struct tag *) o; + if (!t->tagged) + break; /* broken repository */ o->flags |= COMPLETE; - o = parse_object(((struct tag *)o)->tagged->sha1); + o = parse_object(t->tagged->sha1); } - if (o->type == commit_type) { + if (o && o->type == commit_type) { struct commit *commit = (struct commit *)o; commit->object.flags |= COMPLETE; insert_by_date(commit, &complete); |