diff options
Diffstat (limited to 'transport.c')
-rw-r--r-- | transport.c | 106 |
1 files changed, 69 insertions, 37 deletions
diff --git a/transport.c b/transport.c index b58f5c8cdc..4d33138a75 100644 --- a/transport.c +++ b/transport.c @@ -116,8 +116,8 @@ struct git_transport_data { struct child_process *conn; int fd[2]; unsigned got_remote_heads : 1; - struct sha1_array extra_have; - struct sha1_array shallow; + struct oid_array extra_have; + struct oid_array shallow; }; static int set_git_option(struct git_transport_options *opts, @@ -303,7 +303,7 @@ void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int v if (verbose) fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); if (ref->deletion) { - delete_ref(rs.dst, NULL, 0); + delete_ref(NULL, rs.dst, NULL, 0); } else update_ref("update by push", rs.dst, ref->new_oid.hash, NULL, 0, 0); @@ -447,7 +447,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, static int measure_abbrev(const struct object_id *oid, int sofar) { - char hex[GIT_SHA1_HEXSZ + 1]; + char hex[GIT_MAX_HEXSZ + 1]; int w = find_unique_abbrev_r(hex, oid->hash, DEFAULT_ABBREV); return (w < sofar) ? sofar : w; @@ -471,11 +471,11 @@ void transport_print_push_status(const char *dest, struct ref *refs, { struct ref *ref; int n = 0; - unsigned char head_sha1[20]; + struct object_id head_oid; char *head; int summary_width = transport_summary_width(refs); - head = resolve_refdup("HEAD", RESOLVE_REF_READING, head_sha1, NULL); + head = resolve_refdup("HEAD", RESOLVE_REF_READING, head_oid.hash, NULL); if (verbose) { for (ref = refs; ref; ref = ref->next) @@ -1023,19 +1023,22 @@ int transport_push(struct transport *transport, TRANSPORT_RECURSE_SUBMODULES_ONLY)) && !is_bare_repository()) { struct ref *ref = remote_refs; - struct sha1_array commits = SHA1_ARRAY_INIT; + struct oid_array commits = OID_ARRAY_INIT; for (; ref; ref = ref->next) if (!is_null_oid(&ref->new_oid)) - sha1_array_append(&commits, ref->new_oid.hash); + oid_array_append(&commits, + &ref->new_oid); if (!push_unpushed_submodules(&commits, - transport->remote->name, + transport->remote, + refspec, refspec_nr, + transport->push_options, pretend)) { - sha1_array_clear(&commits); + oid_array_clear(&commits); die("Failed to push all needed submodules!"); } - sha1_array_clear(&commits); + oid_array_clear(&commits); } if (((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) || @@ -1044,19 +1047,20 @@ int transport_push(struct transport *transport, !pretend)) && !is_bare_repository()) { struct ref *ref = remote_refs; struct string_list needs_pushing = STRING_LIST_INIT_DUP; - struct sha1_array commits = SHA1_ARRAY_INIT; + struct oid_array commits = OID_ARRAY_INIT; for (; ref; ref = ref->next) if (!is_null_oid(&ref->new_oid)) - sha1_array_append(&commits, ref->new_oid.hash); + oid_array_append(&commits, + &ref->new_oid); if (find_unpushed_submodules(&commits, transport->remote->name, &needs_pushing)) { - sha1_array_clear(&commits); + oid_array_clear(&commits); die_with_unpushed_submodules(&needs_pushing); } string_list_clear(&needs_pushing, 0); - sha1_array_clear(&commits); + oid_array_clear(&commits); } if (!(flags & TRANSPORT_RECURSE_SUBMODULES_ONLY)) @@ -1210,6 +1214,42 @@ literal_copy: return xstrdup(url); } +static void read_alternate_refs(const char *path, + alternate_ref_fn *cb, + void *data) +{ + struct child_process cmd = CHILD_PROCESS_INIT; + struct strbuf line = STRBUF_INIT; + FILE *fh; + + cmd.git_cmd = 1; + argv_array_pushf(&cmd.args, "--git-dir=%s", path); + argv_array_push(&cmd.args, "for-each-ref"); + argv_array_push(&cmd.args, "--format=%(objectname) %(refname)"); + cmd.env = local_repo_env; + cmd.out = -1; + + if (start_command(&cmd)) + return; + + fh = xfdopen(cmd.out, "r"); + while (strbuf_getline_lf(&line, fh) != EOF) { + struct object_id oid; + + if (get_oid_hex(line.buf, &oid) || + line.buf[GIT_SHA1_HEXSZ] != ' ') { + warning("invalid line while parsing alternate refs: %s", + line.buf); + break; + } + + cb(line.buf + GIT_SHA1_HEXSZ + 1, &oid, data); + } + + fclose(fh); + finish_command(&cmd); +} + struct alternate_refs_data { alternate_ref_fn *fn; void *data; @@ -1218,34 +1258,26 @@ struct alternate_refs_data { static int refs_from_alternate_cb(struct alternate_object_database *e, void *data) { - char *other; - size_t len; - struct remote *remote; - struct transport *transport; - const struct ref *extra; + struct strbuf path = STRBUF_INIT; + size_t base_len; struct alternate_refs_data *cb = data; - other = real_pathdup(e->path, 1); - len = strlen(other); - - while (other[len-1] == '/') - other[--len] = '\0'; - if (len < 8 || memcmp(other + len - 8, "/objects", 8)) + if (!strbuf_realpath(&path, e->path, 0)) goto out; + if (!strbuf_strip_suffix(&path, "/objects")) + goto out; + base_len = path.len; + /* Is this a git repository with refs? */ - memcpy(other + len - 8, "/refs", 6); - if (!is_directory(other)) + strbuf_addstr(&path, "/refs"); + if (!is_directory(path.buf)) goto out; - other[len - 8] = '\0'; - remote = remote_get(other); - transport = transport_get(remote, other); - for (extra = transport_get_remote_refs(transport); - extra; - extra = extra->next) - cb->fn(extra, cb->data); - transport_disconnect(transport); + strbuf_setlen(&path, base_len); + + read_alternate_refs(path.buf, cb->fn, cb->data); + out: - free(other); + strbuf_release(&path); return 0; } |