From: Junio C Hamano Date: Fri, 21 Oct 2011 23:04:32 +0000 (-0700) Subject: Merge branch 'jc/unseekable-bundle' X-Git-Tag: v1.7.8-rc0~30 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/b76c561a74cd366786b7b762795fba1551b42149?ds=inline;hp=-c Merge branch 'jc/unseekable-bundle' * jc/unseekable-bundle: bundle: add parse_bundle_header() helper function bundle: allowing to read from an unseekable fd Conflicts: transport.c --- b76c561a74cd366786b7b762795fba1551b42149 diff --combined bundle.c index f82baae3bd,105b005366..08020bc3a2 --- a/bundle.c +++ b/bundle.c @@@ -23,50 -23,102 +23,102 @@@ static void add_to_ref_list(const unsig list->nr++; } - /* returns an fd */ - int read_bundle_header(const char *path, struct bundle_header *header) + /* Eventually this should go to strbuf.[ch] */ + static int strbuf_readline_fd(struct strbuf *sb, int fd) { - char buffer[1024]; - int fd; - long fpos; - FILE *ffd = fopen(path, "rb"); + strbuf_reset(sb); - if (!ffd) - return error("could not open '%s'", path); - if (!fgets(buffer, sizeof(buffer), ffd) || - strcmp(buffer, bundle_signature)) { - fclose(ffd); - return error("'%s' does not look like a v2 bundle file", path); + while (1) { + char ch; + ssize_t len = xread(fd, &ch, 1); + if (len < 0) + return -1; + strbuf_addch(sb, ch); + if (ch == '\n') + break; } - while (fgets(buffer, sizeof(buffer), ffd) - && buffer[0] != '\n') { - int is_prereq = buffer[0] == '-'; - int offset = is_prereq ? 1 : 0; - int len = strlen(buffer); + return 0; + } + + static int parse_bundle_header(int fd, struct bundle_header *header, + const char *report_path) + { + struct strbuf buf = STRBUF_INIT; + int status = 0; + + /* The bundle header begins with the signature */ + if (strbuf_readline_fd(&buf, fd) || + strcmp(buf.buf, bundle_signature)) { + if (report_path) + error("'%s' does not look like a v2 bundle file", + report_path); + status = -1; + goto abort; + } + + /* The bundle header ends with an empty line */ + while (!strbuf_readline_fd(&buf, fd) && + buf.len && buf.buf[0] != '\n') { unsigned char sha1[20]; - struct ref_list *list = is_prereq ? &header->prerequisites - : &header->references; - char delim; - - if (len && buffer[len - 1] == '\n') - buffer[len - 1] = '\0'; - if (get_sha1_hex(buffer + offset, sha1)) { - warning("unrecognized header: %s", buffer); - continue; + int is_prereq = 0; + + if (*buf.buf == '-') { + is_prereq = 1; + strbuf_remove(&buf, 0, 1); } - delim = buffer[40 + offset]; - if (!isspace(delim) && (delim != '\0' || !is_prereq)) - die ("invalid header: %s", buffer); - add_to_ref_list(sha1, isspace(delim) ? - buffer + 41 + offset : "", list); + strbuf_rtrim(&buf); + + /* + * Tip lines have object name, SP, and refname. + * Prerequisites have object name that is optionally + * followed by SP and subject line. + */ + if (get_sha1_hex(buf.buf, sha1) || + (40 <= buf.len && !isspace(buf.buf[40])) || + (!is_prereq && buf.len <= 40)) { + if (report_path) + error("unrecognized header: %s%s (%d)", + (is_prereq ? "-" : ""), buf.buf, (int)buf.len); + status = -1; + break; + } else { + if (is_prereq) + add_to_ref_list(sha1, "", &header->prerequisites); + else + add_to_ref_list(sha1, buf.buf + 41, &header->references); + } + } + + abort: + if (status) { + close(fd); + fd = -1; } - fpos = ftell(ffd); - fclose(ffd); - fd = open(path, O_RDONLY); + strbuf_release(&buf); + return fd; + } + + int read_bundle_header(const char *path, struct bundle_header *header) + { + int fd = open(path, O_RDONLY); + if (fd < 0) return error("could not open '%s'", path); - lseek(fd, fpos, SEEK_SET); - return fd; + return parse_bundle_header(fd, header, path); + } + + int is_bundle(const char *path, int quiet) + { + struct bundle_header header; + int fd = open(path, O_RDONLY); + + if (fd < 0) + return 0; + memset(&header, 0, sizeof(header)); + fd = parse_bundle_header(fd, &header, quiet ? NULL : path); + if (fd >= 0) + close(fd); + return (fd >= 0); } static int list_refs(struct ref_list *r, int argc, const char **argv) @@@ -122,8 -174,11 +174,8 @@@ int verify_bundle(struct bundle_header req_nr = revs.pending.nr; setup_revisions(2, argv, &revs, NULL); - memset(&refs, 0, sizeof(struct object_array)); - for (i = 0; i < revs.pending.nr; i++) { - struct object_array_entry *e = revs.pending.objects + i; - add_object_array(e->item, e->name, &refs); - } + refs = revs.pending; + revs.leak_pending = 1; if (prepare_revision_walk(&revs)) die("revision walk setup failed"); @@@ -141,8 -196,8 +193,8 @@@ refs.objects[i].name); } - for (i = 0; i < refs.nr; i++) - clear_commit_marks((struct commit *)refs.objects[i].item, -1); + clear_commit_marks_for_object_array(&refs, ALL_REV_FLAGS); + free(refs.objects); if (verbose) { struct ref_list *r; @@@ -377,15 -432,12 +429,15 @@@ int create_bundle(struct bundle_header return 0; } -int unbundle(struct bundle_header *header, int bundle_fd) +int unbundle(struct bundle_header *header, int bundle_fd, int flags) { const char *argv_index_pack[] = {"index-pack", - "--fix-thin", "--stdin", NULL}; + "--fix-thin", "--stdin", NULL, NULL}; struct child_process ip; + if (flags & BUNDLE_VERBOSE) + argv_index_pack[3] = "-v"; + if (verify_bundle(header, 0)) return -1; memset(&ip, 0, sizeof(ip)); diff --combined bundle.h index c5a22c8d10,c6228e2102..1584e4d821 --- a/bundle.h +++ b/bundle.h @@@ -14,12 -14,12 +14,13 @@@ struct bundle_header struct ref_list references; }; + int is_bundle(const char *path, int quiet); int read_bundle_header(const char *path, struct bundle_header *header); int create_bundle(struct bundle_header *header, const char *path, int argc, const char **argv); int verify_bundle(struct bundle_header *header, int verbose); -int unbundle(struct bundle_header *header, int bundle_fd); +#define BUNDLE_VERBOSE 1 +int unbundle(struct bundle_header *header, int bundle_fd, int flags); int list_bundle_refs(struct bundle_header *header, int argc, const char **argv); diff --combined transport.c index 57138d908a,84d6480ce6..4ff21ad28d --- a/transport.c +++ b/transport.c @@@ -10,7 -10,6 +10,7 @@@ #include "refs.h" #include "branch.h" #include "url.h" +#include "submodule.h" /* rsync support */ @@@ -432,8 -431,7 +432,8 @@@ static int fetch_refs_from_bundle(struc int nr_heads, struct ref **to_fetch) { struct bundle_transport_data *data = transport->data; - return unbundle(&data->header, data->fd); + return unbundle(&data->header, data->fd, + transport->progress ? BUNDLE_VERBOSE : 0); } static int close_bundle(struct transport *transport) @@@ -755,10 -753,18 +755,10 @@@ void transport_verify_remote_names(int continue; remote = remote ? (remote + 1) : local; - switch (check_ref_format(remote)) { - case 0: /* ok */ - case CHECK_REF_FORMAT_ONELEVEL: - /* ok but a single level -- that is fine for - * a match pattern. - */ - case CHECK_REF_FORMAT_WILDCARD: - /* ok but ends with a pattern-match character */ - continue; - } - die("remote part of refspec is not a valid name in %s", - heads[i]); + if (check_refname_format(remote, + REFNAME_ALLOW_ONELEVEL|REFNAME_REFSPEC_PATTERN)) + die("remote part of refspec is not a valid name in %s", + heads[i]); } } @@@ -859,28 -865,6 +859,6 @@@ static int is_local(const char *url has_dos_drive_prefix(url); } - static int is_gitfile(const char *url) - { - struct stat st; - char buf[9]; - int fd, len; - if (stat(url, &st)) - return 0; - if (!S_ISREG(st.st_mode)) - return 0; - if (st.st_size < 10 || st.st_size > 9 + PATH_MAX) - return 0; - - fd = open(url, O_RDONLY); - if (fd < 0) - die_errno("Error opening '%s'", url); - len = read_in_full(fd, buf, sizeof(buf)); - close(fd); - if (len != sizeof(buf)) - die("Error reading %s", url); - return !prefixcmp(buf, "gitdir: "); - } - static int is_file(const char *url) { struct stat buf; @@@ -929,7 -913,7 +907,7 @@@ struct transport *transport_get(struct ret->fetch = fetch_objs_via_rsync; ret->push = rsync_transport_push; ret->smart_options = NULL; - } else if (is_local(url) && is_file(url) && !is_gitfile(url)) { + } else if (is_local(url) && is_file(url) && is_bundle(url, 1)) { struct bundle_transport_data *data = xcalloc(1, sizeof(*data)); ret->data = data; ret->get_refs_list = get_refs_from_bundle; @@@ -1057,14 -1041,6 +1035,14 @@@ int transport_push(struct transport *tr flags & TRANSPORT_PUSH_MIRROR, flags & TRANSPORT_PUSH_FORCE); + if ((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) && !is_bare_repository()) { + struct ref *ref = remote_refs; + for (; ref; ref = ref->next) + if (!is_null_sha1(ref->new_sha1) && + check_submodule_needs_pushing(ref->new_sha1,transport->remote->name)) + die("There are unpushed submodules, aborting."); + } + push_ret = transport->push_refs(transport, remote_refs, flags); err = push_had_errors(remote_refs); ret = push_ret | err;