Skip to content

Commit

Permalink
Merge branch 'jc/boundary'
Browse files Browse the repository at this point in the history
* jc/boundary:
  git-bundle: prevent overwriting existing bundles
  git-bundle: die if a given ref is not included in bundle
  git-bundle: handle thin packs in subcommand "unbundle"
  git-bundle: Make thin packs
  git-bundle: avoid packing objects which are in the prerequisites
  bundle: fix wrong check of read_header()'s return value & add tests
  revision --boundary: fix uncounted case.
  revision --boundary: fix stupid typo
  git-bundle: make verify a bit more chatty.
  revision traversal: SHOWN means shown
  git-bundle: various fixups
  revision traversal: retire BOUNDARY_SHOW
  revision walker: Fix --boundary when limited
  • Loading branch information
Junio C Hamano committed Mar 12, 2007
2 parents f43cd49 + 2e578f9 commit 2422f1c
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 197 deletions.
180 changes: 97 additions & 83 deletions builtin-bundle.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,28 @@ static int fork_with_pipe(const char **argv, int *in, int *out)
return pid;
}

static int verify_bundle(struct bundle_header *header)
static int list_refs(struct ref_list *r, int argc, const char **argv)
{
int i;

for (i = 0; i < r->nr; i++) {
if (argc > 1) {
int j;
for (j = 1; j < argc; j++)
if (!strcmp(r->list[i].name, argv[j]))
break;
if (j == argc)
continue;
}
printf("%s %s\n", sha1_to_hex(r->list[i].sha1),
r->list[i].name);
}
return 0;
}

#define PREREQ_MARK (1u<<16)

static int verify_bundle(struct bundle_header *header, int verbose)
{
/*
* Do fast check, then if any prereqs are missing then go line by line
Expand All @@ -179,15 +200,15 @@ static int verify_bundle(struct bundle_header *header)
struct ref_list_entry *e = p->list + i;
struct object *o = parse_object(e->sha1);
if (o) {
o->flags |= BOUNDARY_SHOW;
o->flags |= PREREQ_MARK;
add_pending_object(&revs, o, e->name);
continue;
}
if (++ret == 1)
error(message);
error("%s %s", sha1_to_hex(e->sha1), e->name);
}
if (revs.pending.nr == 0)
if (revs.pending.nr != p->nr)
return ret;
req_nr = revs.pending.nr;
setup_revisions(2, argv, &revs, NULL);
Expand All @@ -202,7 +223,7 @@ static int verify_bundle(struct bundle_header *header)

i = req_nr;
while (i && (commit = get_revision(&revs)))
if (commit->object.flags & BOUNDARY_SHOW)
if (commit->object.flags & PREREQ_MARK)
i--;

for (i = 0; i < req_nr; i++)
Expand All @@ -216,76 +237,48 @@ static int verify_bundle(struct bundle_header *header)
for (i = 0; i < refs.nr; i++)
clear_commit_marks((struct commit *)refs.objects[i].item, -1);

if (verbose) {
struct ref_list *r;

r = &header->references;
printf("The bundle contains %d ref%s\n",
r->nr, (1 < r->nr) ? "s" : "");
list_refs(r, 0, NULL);
r = &header->prerequisites;
printf("The bundle requires these %d ref%s\n",
r->nr, (1 < r->nr) ? "s" : "");
list_refs(r, 0, NULL);
}
return ret;
}

static int list_heads(struct bundle_header *header, int argc, const char **argv)
{
int i;
struct ref_list *r = &header->references;

for (i = 0; i < r->nr; i++) {
if (argc > 1) {
int j;
for (j = 1; j < argc; j++)
if (!strcmp(r->list[i].name, argv[j]))
break;
if (j == argc)
continue;
}
printf("%s %s\n", sha1_to_hex(r->list[i].sha1),
r->list[i].name);
}
return 0;
}

static void show_commit(struct commit *commit)
{
write_or_die(1, sha1_to_hex(commit->object.sha1), 40);
write_or_die(1, "\n", 1);
if (commit->parents) {
free_commit_list(commit->parents);
commit->parents = NULL;
}
}

static void show_object(struct object_array_entry *p)
{
/* An object with name "foo\n0000000..." can be used to
* confuse downstream git-pack-objects very badly.
*/
const char *ep = strchr(p->name, '\n');
int len = ep ? ep - p->name : strlen(p->name);
write_or_die(1, sha1_to_hex(p->item->sha1), 40);
write_or_die(1, " ", 1);
if (len)
write_or_die(1, p->name, len);
write_or_die(1, "\n", 1);
}

static void show_edge(struct commit *commit)
{
; /* nothing to do */
return list_refs(&header->references, argc, argv);
}

static int create_bundle(struct bundle_header *header, const char *path,
int argc, const char **argv)
{
int bundle_fd = -1;
const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
const char **argv_pack = xmalloc(4 * sizeof(const char *));
const char **argv_pack = xmalloc(5 * sizeof(const char *));
int pid, in, out, i, status;
char buffer[1024];
struct rev_info revs;

bundle_fd = (!strcmp(path, "-") ? 1 :
open(path, O_CREAT | O_WRONLY, 0666));
open(path, O_CREAT | O_EXCL | O_WRONLY, 0666));
if (bundle_fd < 0)
return error("Could not write to '%s'", path);
return error("Could not create '%s': %s", path, strerror(errno));

/* write signature */
write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));

/* init revs to list objects for pack-objects later */
save_commit_buffer = 0;
init_revisions(&revs, NULL);

/* write prerequisites */
memcpy(argv_boundary + 3, argv + 1, argc * sizeof(const char *));
argv_boundary[0] = "rev-list";
Expand All @@ -296,37 +289,53 @@ static int create_bundle(struct bundle_header *header, const char *path,
pid = fork_with_pipe(argv_boundary, NULL, &out);
if (pid < 0)
return -1;
while ((i = read_string(out, buffer, sizeof(buffer))) > 0)
if (buffer[0] == '-')
while ((i = read_string(out, buffer, sizeof(buffer))) > 0) {
unsigned char sha1[20];
if (buffer[0] == '-') {
write_or_die(bundle_fd, buffer, i);
if (!get_sha1_hex(buffer + 1, sha1)) {
struct object *object = parse_object(sha1);
object->flags |= UNINTERESTING;
add_pending_object(&revs, object, buffer);
}
} else if (!get_sha1_hex(buffer, sha1)) {
struct object *object = parse_object(sha1);
object->flags |= SHOWN;
}
}
while ((i = waitpid(pid, &status, 0)) < 0)
if (errno != EINTR)
return error("rev-list died");
if (!WIFEXITED(status) || WEXITSTATUS(status))
return error("rev-list died %d", WEXITSTATUS(status));

/* write references */
save_commit_buffer = 0;
init_revisions(&revs, NULL);
revs.tag_objects = 1;
revs.tree_objects = 1;
revs.blob_objects = 1;
argc = setup_revisions(argc, argv, &revs, NULL);
if (argc > 1)
return error("unrecognized argument: %s'", argv[1]);

for (i = 0; i < revs.pending.nr; i++) {
struct object_array_entry *e = revs.pending.objects + i;
if (!(e->item->flags & UNINTERESTING)) {
unsigned char sha1[20];
char *ref;
if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
continue;
write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
write_or_die(bundle_fd, " ", 1);
write_or_die(bundle_fd, ref, strlen(ref));
write_or_die(bundle_fd, "\n", 1);
free(ref);
}
unsigned char sha1[20];
char *ref;

if (e->item->flags & UNINTERESTING)
continue;
if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
continue;
/*
* Make sure the refs we wrote out is correct; --max-count and
* other limiting options could have prevented all the tips
* from getting output.
*/
if (!(e->item->flags & SHOWN))
die("ref '%s' is excluded by the rev-list options",
e->name);
write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
write_or_die(bundle_fd, " ", 1);
write_or_die(bundle_fd, ref, strlen(ref));
write_or_die(bundle_fd, "\n", 1);
free(ref);
}

/* end header */
Expand All @@ -336,36 +345,42 @@ static int create_bundle(struct bundle_header *header, const char *path,
argv_pack[0] = "pack-objects";
argv_pack[1] = "--all-progress";
argv_pack[2] = "--stdout";
argv_pack[3] = NULL;
argv_pack[3] = "--thin";
argv_pack[4] = NULL;
in = -1;
out = bundle_fd;
pid = fork_with_pipe(argv_pack, &in, &out);
if (pid < 0)
return error("Could not spawn pack-objects");
close(1);
dup2(in, 1);
for (i = 0; i < revs.pending.nr; i++) {
struct object *object = revs.pending.objects[i].item;
if (object->flags & UNINTERESTING)
write(in, "^", 1);
write(in, sha1_to_hex(object->sha1), 40);
write(in, "\n", 1);
}
close(in);
prepare_revision_walk(&revs);
mark_edges_uninteresting(revs.commits, &revs, show_edge);
traverse_commit_list(&revs, show_commit, show_object);
close(1);
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR)
return -1;
if (!WIFEXITED(status) || WEXITSTATUS(status))
return error ("pack-objects died");
return 0;

return status;
}

static int unbundle(struct bundle_header *header, int bundle_fd,
int argc, const char **argv)
{
const char *argv_index_pack[] = {"index-pack", "--stdin", NULL};
const char *argv_index_pack[] = {"index-pack",
"--fix-thin", "--stdin", NULL};
int pid, status, dev_null;

if (verify_bundle(header))
if (verify_bundle(header, 0))
return -1;
dev_null = open("/dev/null", O_WRONLY);
if (dev_null < 0)
return error("Could not open /dev/null");
pid = fork_with_pipe(argv_index_pack, &bundle_fd, &dev_null);
if (pid < 0)
return error("Could not spawn index-pack");
Expand Down Expand Up @@ -402,12 +417,12 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)

memset(&header, 0, sizeof(header));
if (strcmp(cmd, "create") &&
!(bundle_fd = read_header(bundle_file, &header)))
(bundle_fd = read_header(bundle_file, &header)) < 0)
return 1;

if (!strcmp(cmd, "verify")) {
close(bundle_fd);
if (verify_bundle(&header))
if (verify_bundle(&header, 1))
return 1;
fprintf(stderr, "%s is okay\n", bundle_file);
return 0;
Expand All @@ -427,4 +442,3 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
} else
usage(bundle_usage);
}

Loading

0 comments on commit 2422f1c

Please sign in to comment.