author | Junio C Hamano <gitster@pobox.com> | |
Fri, 21 Oct 2011 23:04:32 +0000 (16:04 -0700) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Fri, 21 Oct 2011 23:04:32 +0000 (16:04 -0700) |
* jc/unseekable-bundle:
bundle: add parse_bundle_header() helper function
bundle: allowing to read from an unseekable fd
Conflicts:
transport.c
bundle: add parse_bundle_header() helper function
bundle: allowing to read from an unseekable fd
Conflicts:
transport.c
1 | 2 | |||
---|---|---|---|---|
bundle.c | patch | | diff1 | | diff2 | | blob | history |
bundle.h | patch | | diff1 | | diff2 | | blob | history |
transport.c | patch | | diff1 | | diff2 | | blob | history |
diff --combined bundle.c
index f82baae3bd2736cd0abca6b2412e3c4fd363b1e6,105b005366ab2bbc349defff3572a7722e6c1ddf..08020bc3a258e055a8f5f6974217cf482edc3ee3
+++ b/bundle.c
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)
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");
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;
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 c5a22c8d10c7bf5e27536a3b84033b77f3542445,c6228e2102c4fe6958d4086061df1f556451cdb9..1584e4d821440d525f10515d6a07c6506b732fec
+++ b/bundle.h
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 57138d908a5749d378af441e8d3cfe8150b27271,84d6480ce65cf4bc45a344d6e9986696cbd8498f..4ff21ad28d89c6a4fc39628d358662bc7790ffde
--- 1/transport.c
--- 2/transport.c
+++ b/transport.c
#include "refs.h"
#include "branch.h"
#include "url.h"
+#include "submodule.h"
/* rsync support */
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)
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]);
}
}
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;
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;
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;