summaryrefslogtreecommitdiff
path: root/fetch-pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'fetch-pack.c')
-rw-r--r--fetch-pack.c384
1 files changed, 206 insertions, 178 deletions
diff --git a/fetch-pack.c b/fetch-pack.c
index 30a0867..2318ebe 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -35,8 +35,10 @@ static int fetch_fsck_objects = -1;
static int transfer_fsck_objects = -1;
static int agent_supported;
static int server_supports_filtering;
+static int advertise_sid;
static struct shallow_lock shallow_lock;
static const char *alternate_shallow_file;
+static struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES;
static struct strbuf fsck_msg_types = STRBUF_INIT;
static struct string_list uri_protocols = STRING_LIST_INIT_DUP;
@@ -108,24 +110,48 @@ static void for_each_cached_alternate(struct fetch_negotiator *negotiator,
cb(negotiator, cache.items[i]);
}
+static struct commit *deref_without_lazy_fetch(const struct object_id *oid,
+ int mark_tags_complete)
+{
+ enum object_type type;
+ struct object_info info = { .typep = &type };
+
+ while (1) {
+ if (oid_object_info_extended(the_repository, oid, &info,
+ OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK))
+ return NULL;
+ if (type == OBJ_TAG) {
+ struct tag *tag = (struct tag *)
+ parse_object(the_repository, oid);
+
+ if (!tag->tagged)
+ return NULL;
+ if (mark_tags_complete)
+ tag->object.flags |= COMPLETE;
+ oid = &tag->tagged->oid;
+ } else {
+ break;
+ }
+ }
+ if (type == OBJ_COMMIT)
+ return (struct commit *) parse_object(the_repository, oid);
+ return NULL;
+}
+
static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
- const char *refname,
const struct object_id *oid)
{
- struct object *o = deref_tag(the_repository,
- parse_object(the_repository, oid),
- refname, 0);
-
- if (o && o->type == OBJ_COMMIT)
- negotiator->add_tip(negotiator, (struct commit *)o);
+ struct commit *c = deref_without_lazy_fetch(oid, 0);
+ if (c)
+ negotiator->add_tip(negotiator, c);
return 0;
}
static int rev_list_insert_ref_oid(const char *refname, const struct object_id *oid,
int flag, void *cb_data)
{
- return rev_list_insert_ref(cb_data, refname, oid);
+ return rev_list_insert_ref(cb_data, oid);
}
enum ack_type {
@@ -201,7 +227,7 @@ static void send_request(struct fetch_pack_args *args,
static void insert_one_alternate_object(struct fetch_negotiator *negotiator,
struct object *obj)
{
- rev_list_insert_ref(negotiator, NULL, &obj->oid);
+ rev_list_insert_ref(negotiator, &obj->oid);
}
#define INITIAL_FLUSH 16
@@ -230,13 +256,12 @@ static void mark_tips(struct fetch_negotiator *negotiator,
int i;
if (!negotiation_tips) {
- for_each_ref(rev_list_insert_ref_oid, negotiator);
+ for_each_rawref(rev_list_insert_ref_oid, negotiator);
return;
}
for (i = 0; i < negotiation_tips->nr; i++)
- rev_list_insert_ref(negotiator, NULL,
- &negotiation_tips->oid[i]);
+ rev_list_insert_ref(negotiator, &negotiation_tips->oid[i]);
return;
}
@@ -262,10 +287,8 @@ static int find_common(struct fetch_negotiator *negotiator,
PACKET_READ_CHOMP_NEWLINE |
PACKET_READ_DIE_ON_ERR_PACKET);
- if (!args->no_dependents) {
- mark_tips(negotiator, args->negotiation_tips);
- for_each_cached_alternate(negotiator, insert_one_alternate_object);
- }
+ mark_tips(negotiator, args->negotiation_tips);
+ for_each_cached_alternate(negotiator, insert_one_alternate_object);
fetching = 0;
for ( ; refs ; refs = refs->next) {
@@ -282,12 +305,8 @@ static int find_common(struct fetch_negotiator *negotiator,
* 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.
- *
- * Do this only if args->no_dependents is false (if it is true,
- * we cannot trust the object flags).
*/
- if (!args->no_dependents &&
- ((o = lookup_object(the_repository, remote)) != NULL) &&
+ if (((o = lookup_object(the_repository, remote)) != NULL) &&
(o->flags & COMPLETE)) {
continue;
}
@@ -309,6 +328,8 @@ static int find_common(struct fetch_negotiator *negotiator,
if (deepen_not_ok) strbuf_addstr(&c, " deepen-not");
if (agent_supported) strbuf_addf(&c, " agent=%s",
git_user_agent_sanitized());
+ if (advertise_sid)
+ strbuf_addf(&c, " session-id=%s", trace2_session_id());
if (args->filter_options.choice)
strbuf_addstr(&c, " filter");
packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
@@ -387,8 +408,6 @@ static int find_common(struct fetch_negotiator *negotiator,
trace2_region_enter("fetch-pack", "negotiation_v0_v1", the_repository);
flushes = 0;
retval = -1;
- if (args->no_dependents)
- goto done;
while ((oid = negotiator->next(negotiator))) {
packet_buf_write(&req_buf, "have %s\n", oid_to_hex(oid));
print_verbose(args, "have %s", oid_to_hex(oid));
@@ -503,21 +522,11 @@ static struct commit_list *complete;
static int mark_complete(const struct object_id *oid)
{
- struct object *o = parse_object(the_repository, oid);
-
- while (o && o->type == OBJ_TAG) {
- struct tag *t = (struct tag *) o;
- if (!t->tagged)
- break; /* broken repository */
- o->flags |= COMPLETE;
- o = parse_object(the_repository, &t->tagged->oid);
- }
- if (o && o->type == OBJ_COMMIT) {
- struct commit *commit = (struct commit *)o;
- if (!(commit->object.flags & COMPLETE)) {
- commit->object.flags |= COMPLETE;
- commit_list_insert(commit, &complete);
- }
+ struct commit *commit = deref_without_lazy_fetch(oid, 1);
+
+ if (commit && !(commit->object.flags & COMPLETE)) {
+ commit->object.flags |= COMPLETE;
+ commit_list_insert(commit, &complete);
}
return 0;
}
@@ -653,9 +662,7 @@ struct loose_object_iter {
/*
* Mark recent commits available locally and reachable from a local ref as
- * COMPLETE. If args->no_dependents is false, also mark COMPLETE remote refs as
- * COMMON_REF (otherwise, we are not planning to participate in negotiation, and
- * thus do not need COMMON_REF marks).
+ * COMPLETE.
*
* The cutoff time for recency is determined by this heuristic: it is the
* earliest commit time of the objects in refs that are commits and that we know
@@ -702,7 +709,7 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
*/
trace2_region_enter("fetch-pack", "mark_complete_local_refs", NULL);
if (!args->deepen) {
- for_each_ref(mark_complete_oid, NULL);
+ for_each_rawref(mark_complete_oid, NULL);
for_each_cached_alternate(NULL, mark_alternate_complete);
commit_list_sort_by_date(&complete);
if (cutoff)
@@ -716,16 +723,12 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
*/
trace2_region_enter("fetch-pack", "mark_common_remote_refs", NULL);
for (ref = *refs; ref; ref = ref->next) {
- struct object *o = deref_tag(the_repository,
- lookup_object(the_repository,
- &ref->old_oid),
- NULL, 0);
+ struct commit *c = deref_without_lazy_fetch(&ref->old_oid, 0);
- if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
+ if (!c || !(c->object.flags & COMPLETE))
continue;
- negotiator->known_common(negotiator,
- (struct commit *)o);
+ negotiator->known_common(negotiator, c);
}
trace2_region_leave("fetch-pack", "mark_common_remote_refs", NULL);
@@ -770,13 +773,11 @@ static int sideband_demux(int in, int out, void *data)
return ret;
}
-static void write_promisor_file(const char *keep_name,
- struct ref **sought, int nr_sought)
+static void create_promisor_file(const char *keep_name,
+ struct ref **sought, int nr_sought)
{
struct strbuf promisor_name = STRBUF_INIT;
int suffix_stripped;
- FILE *output;
- int i;
strbuf_addstr(&promisor_name, keep_name);
suffix_stripped = strbuf_strip_suffix(&promisor_name, ".keep");
@@ -785,19 +786,41 @@ static void write_promisor_file(const char *keep_name,
keep_name);
strbuf_addstr(&promisor_name, ".promisor");
- output = xfopen(promisor_name.buf, "w");
- for (i = 0; i < nr_sought; i++)
- fprintf(output, "%s %s\n", oid_to_hex(&sought[i]->old_oid),
- sought[i]->name);
- fclose(output);
+ write_promisor_file(promisor_name.buf, sought, nr_sought);
strbuf_release(&promisor_name);
}
+static void parse_gitmodules_oids(int fd, struct oidset *gitmodules_oids)
+{
+ int len = the_hash_algo->hexsz + 1; /* hash + NL */
+
+ do {
+ char hex_hash[GIT_MAX_HEXSZ + 1];
+ int read_len = read_in_full(fd, hex_hash, len);
+ struct object_id oid;
+ const char *end;
+
+ if (!read_len)
+ return;
+ if (read_len != len)
+ die("invalid length read %d", read_len);
+ if (parse_oid_hex(hex_hash, &oid, &end) || *end != '\n')
+ die("invalid hash");
+ oidset_insert(gitmodules_oids, &oid);
+ } while (1);
+}
+
+/*
+ * If packfile URIs were provided, pass a non-NULL pointer to index_pack_args.
+ * The strings to pass as the --index-pack-arg arguments to http-fetch will be
+ * stored there. (It must be freed by the caller.)
+ */
static int get_pack(struct fetch_pack_args *args,
int xd[2], struct string_list *pack_lockfiles,
- int only_packfile,
- struct ref **sought, int nr_sought)
+ struct strvec *index_pack_args,
+ struct ref **sought, int nr_sought,
+ struct oidset *gitmodules_oids)
{
struct async demux;
int do_keep = args->keep_pack;
@@ -805,6 +828,7 @@ static int get_pack(struct fetch_pack_args *args,
struct pack_header header;
int pass_header = 0;
struct child_process cmd = CHILD_PROCESS_INIT;
+ int fsck_objects = 0;
int ret;
memset(&demux, 0, sizeof(demux));
@@ -823,7 +847,7 @@ static int get_pack(struct fetch_pack_args *args,
else
demux.out = xd[0];
- if (!args->keep_pack && unpack_limit) {
+ if (!args->keep_pack && unpack_limit && !index_pack_args) {
if (read_pack_header(demux.out, &header))
die(_("protocol error: bad pack header"));
@@ -835,30 +859,37 @@ static int get_pack(struct fetch_pack_args *args,
}
if (alternate_shallow_file) {
- argv_array_push(&cmd.args, "--shallow-file");
- argv_array_push(&cmd.args, alternate_shallow_file);
+ strvec_push(&cmd.args, "--shallow-file");
+ strvec_push(&cmd.args, alternate_shallow_file);
}
- if (do_keep || args->from_promisor) {
- if (pack_lockfiles)
+ if (fetch_fsck_objects >= 0
+ ? fetch_fsck_objects
+ : transfer_fsck_objects >= 0
+ ? transfer_fsck_objects
+ : 0)
+ fsck_objects = 1;
+
+ if (do_keep || args->from_promisor || index_pack_args || fsck_objects) {
+ if (pack_lockfiles || fsck_objects)
cmd.out = -1;
cmd_name = "index-pack";
- argv_array_push(&cmd.args, cmd_name);
- argv_array_push(&cmd.args, "--stdin");
+ strvec_push(&cmd.args, cmd_name);
+ strvec_push(&cmd.args, "--stdin");
if (!args->quiet && !args->no_progress)
- argv_array_push(&cmd.args, "-v");
+ strvec_push(&cmd.args, "-v");
if (args->use_thin_pack)
- argv_array_push(&cmd.args, "--fix-thin");
- if (do_keep && (args->lock_pack || unpack_limit)) {
+ strvec_push(&cmd.args, "--fix-thin");
+ if ((do_keep || index_pack_args) && (args->lock_pack || unpack_limit)) {
char hostname[HOST_NAME_MAX + 1];
if (xgethostname(hostname, sizeof(hostname)))
xsnprintf(hostname, sizeof(hostname), "localhost");
- argv_array_pushf(&cmd.args,
- "--keep=fetch-pack %"PRIuMAX " on %s",
- (uintmax_t)getpid(), hostname);
+ strvec_pushf(&cmd.args,
+ "--keep=fetch-pack %"PRIuMAX " on %s",
+ (uintmax_t)getpid(), hostname);
}
- if (only_packfile && args->check_self_contained_and_connected)
- argv_array_push(&cmd.args, "--check-self-contained-and-connected");
+ if (!index_pack_args && args->check_self_contained_and_connected)
+ strvec_push(&cmd.args, "--check-self-contained-and-connected");
else
/*
* We cannot perform any connectivity checks because
@@ -866,51 +897,63 @@ static int get_pack(struct fetch_pack_args *args,
* have this responsibility.
*/
args->check_self_contained_and_connected = 0;
- /*
- * If we're obtaining the filename of a lockfile, we'll use
- * that filename to write a .promisor file with more
- * information below. If not, we need index-pack to do it for
- * us.
- */
- if (!(do_keep && pack_lockfiles) && args->from_promisor)
- argv_array_push(&cmd.args, "--promisor");
+
+ if (args->from_promisor)
+ /*
+ * create_promisor_file() may be called afterwards but
+ * we still need index-pack to know that this is a
+ * promisor pack. For example, if transfer.fsckobjects
+ * is true, index-pack needs to know that .gitmodules
+ * is a promisor object (so that it won't complain if
+ * it is missing).
+ */
+ strvec_push(&cmd.args, "--promisor");
}
else {
cmd_name = "unpack-objects";
- argv_array_push(&cmd.args, cmd_name);
+ strvec_push(&cmd.args, cmd_name);
if (args->quiet || args->no_progress)
- argv_array_push(&cmd.args, "-q");
+ strvec_push(&cmd.args, "-q");
args->check_self_contained_and_connected = 0;
}
if (pass_header)
- argv_array_pushf(&cmd.args, "--pack_header=%"PRIu32",%"PRIu32,
- ntohl(header.hdr_version),
+ strvec_pushf(&cmd.args, "--pack_header=%"PRIu32",%"PRIu32,
+ ntohl(header.hdr_version),
ntohl(header.hdr_entries));
- if (fetch_fsck_objects >= 0
- ? fetch_fsck_objects
- : transfer_fsck_objects >= 0
- ? transfer_fsck_objects
- : 0) {
- if (args->from_promisor)
+ if (fsck_objects) {
+ if (args->from_promisor || index_pack_args)
/*
* We cannot use --strict in index-pack because it
* checks both broken objects and links, but we only
* want to check for broken objects.
*/
- argv_array_push(&cmd.args, "--fsck-objects");
+ strvec_push(&cmd.args, "--fsck-objects");
else
- argv_array_pushf(&cmd.args, "--strict%s",
- fsck_msg_types.buf);
+ strvec_pushf(&cmd.args, "--strict%s",
+ fsck_msg_types.buf);
+ }
+
+ if (index_pack_args) {
+ int i;
+
+ for (i = 0; i < cmd.args.nr; i++)
+ strvec_push(index_pack_args, cmd.args.v[i]);
}
cmd.in = demux.out;
cmd.git_cmd = 1;
if (start_command(&cmd))
die(_("fetch-pack: unable to fork off %s"), cmd_name);
- if (do_keep && pack_lockfiles) {
- string_list_append_nodup(pack_lockfiles,
- index_pack_lockfile(cmd.out));
+ if (do_keep && (pack_lockfiles || fsck_objects)) {
+ int is_well_formed;
+ char *pack_lockfile = index_pack_lockfile(cmd.out, &is_well_formed);
+
+ if (!is_well_formed)
+ die(_("fetch-pack: invalid index-pack output"));
+ if (pack_lockfile)
+ string_list_append_nodup(pack_lockfiles, pack_lockfile);
+ parse_gitmodules_oids(cmd.out, gitmodules_oids);
close(cmd.out);
}
@@ -933,7 +976,7 @@ static int get_pack(struct fetch_pack_args *args,
* obtained .keep filename if necessary
*/
if (do_keep && pack_lockfiles && pack_lockfiles->nr && args->from_promisor)
- write_promisor_file(pack_lockfiles->items[0].string, sought, nr_sought);
+ create_promisor_file(pack_lockfiles->items[0].string, sought, nr_sought);
return 0;
}
@@ -960,12 +1003,8 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
struct fetch_negotiator negotiator_alloc;
struct fetch_negotiator *negotiator;
- if (args->no_dependents) {
- negotiator = NULL;
- } else {
- negotiator = &negotiator_alloc;
- fetch_negotiator_init(r, negotiator);
- }
+ negotiator = &negotiator_alloc;
+ fetch_negotiator_init(r, negotiator);
sort_ref_list(&ref, ref_compare_name);
QSORT(sought, nr_sought, cmp_ref_by_name);
@@ -977,6 +1016,9 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
agent_len, agent_feature);
}
+ if (!server_supports("session-id"))
+ advertise_sid = 0;
+
if (server_supports("shallow"))
print_verbose(args, _("Server supports %s"), "shallow");
else if (args->depth > 0 || is_repository_shallow(r))
@@ -1053,15 +1095,11 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
if (!server_supports_hash(the_hash_algo->name, NULL))
die(_("Server does not support this repository's object format"));
- if (!args->no_dependents) {
- mark_complete_and_common_ref(negotiator, args, &ref);
- filter_refs(args, &ref, sought, nr_sought);
- if (everything_local(args, &ref)) {
- packet_flush(fd[1]);
- goto all_done;
- }
- } else {
- filter_refs(args, &ref, sought, nr_sought);
+ mark_complete_and_common_ref(negotiator, args, &ref);
+ filter_refs(args, &ref, sought, nr_sought);
+ if (everything_local(args, &ref)) {
+ packet_flush(fd[1]);
+ goto all_done;
}
if (find_common(negotiator, args, fd, &oid, ref) < 0)
if (!args->keep_pack)
@@ -1075,12 +1113,17 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
if (args->deepen)
setup_alternate_shallow(&shallow_lock, &alternate_shallow_file,
NULL);
- else if (si->nr_ours || si->nr_theirs)
+ else if (si->nr_ours || si->nr_theirs) {
+ if (args->reject_shallow_remote)
+ die(_("source repository is shallow, reject to clone."));
alternate_shallow_file = setup_temporary_shallow(si->shallow);
- else
+ } else
alternate_shallow_file = NULL;
- if (get_pack(args, fd, pack_lockfiles, 1, sought, nr_sought))
+ if (get_pack(args, fd, pack_lockfiles, NULL, sought, nr_sought,
+ &fsck_options.gitmodules_found))
die(_("git fetch-pack: fetch failed."));
+ if (fsck_finish(&fsck_options))
+ die("fsck failed");
all_done:
if (negotiator)
@@ -1110,7 +1153,7 @@ static void add_shallow_requests(struct strbuf *req_buf,
packet_buf_write(req_buf, "deepen-relative\n");
}
-static void add_wants(int no_dependents, const struct ref *wants, struct strbuf *req_buf)
+static void add_wants(const struct ref *wants, struct strbuf *req_buf)
{
int use_ref_in_want = server_supports_feature("fetch", "ref-in-want", 0);
@@ -1127,12 +1170,8 @@ static void add_wants(int no_dependents, const struct ref *wants, struct strbuf
* 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.
- *
- * Do this only if args->no_dependents is false (if it is true,
- * we cannot trust the object flags).
*/
- if (!no_dependents &&
- ((o = lookup_object(the_repository, remote)) != NULL) &&
+ if (((o = lookup_object(the_repository, remote)) != NULL) &&
(o->flags & COMPLETE)) {
continue;
}
@@ -1197,6 +1236,8 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
packet_buf_write(&req_buf, "command=fetch");
if (server_supports_v2("agent", 0))
packet_buf_write(&req_buf, "agent=%s", git_user_agent_sanitized());
+ if (advertise_sid && server_supports_v2("session-id", 0))
+ packet_buf_write(&req_buf, "session-id=%s", trace2_session_id());
if (args->server_options && args->server_options->nr &&
server_supports_v2("server-option", 1)) {
int i;
@@ -1266,19 +1307,14 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
}
/* add wants */
- add_wants(args->no_dependents, wants, &req_buf);
+ add_wants(wants, &req_buf);
- if (args->no_dependents) {
- packet_buf_write(&req_buf, "done");
- ret = 1;
- } else {
- /* Add all of the common commits we've found in previous rounds */
- add_common(&req_buf, common);
+ /* Add all of the common commits we've found in previous rounds */
+ add_common(&req_buf, common);
- /* Add initial haves */
- ret = add_haves(negotiator, seen_ack, &req_buf,
- haves_to_send, in_vain);
- }
+ /* Add initial haves */
+ ret = add_haves(negotiator, seen_ack, &req_buf,
+ haves_to_send, in_vain);
/* Send request */
packet_buf_flush(&req_buf);
@@ -1449,10 +1485,12 @@ static void receive_shallow_info(struct fetch_pack_args *args,
* rejected (unless --update-shallow is set); do the same.
*/
prepare_shallow_info(si, shallows);
- if (si->nr_ours || si->nr_theirs)
+ if (si->nr_ours || si->nr_theirs) {
+ if (args->reject_shallow_remote)
+ die(_("source repository is shallow, reject to clone."));
alternate_shallow_file =
setup_temporary_shallow(si->shallow);
- else
+ } else
alternate_shallow_file = NULL;
} else {
alternate_shallow_file = NULL;
@@ -1537,13 +1575,10 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
int seen_ack = 0;
struct string_list packfile_uris = STRING_LIST_INIT_DUP;
int i;
+ struct strvec index_pack_args = STRVEC_INIT;
- if (args->no_dependents) {
- negotiator = NULL;
- } else {
- negotiator = &negotiator_alloc;
- fetch_negotiator_init(r, negotiator);
- }
+ negotiator = &negotiator_alloc;
+ fetch_negotiator_init(r, negotiator);
packet_reader_init(&reader, fd[0], NULL, 0,
PACKET_READ_CHOMP_NEWLINE |
@@ -1567,21 +1602,16 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
args->deepen = 1;
/* Filter 'ref' by 'sought' and those that aren't local */
- if (!args->no_dependents) {
- mark_complete_and_common_ref(negotiator, args, &ref);
- filter_refs(args, &ref, sought, nr_sought);
- if (everything_local(args, &ref))
- state = FETCH_DONE;
- else
- state = FETCH_SEND_REQUEST;
-
- mark_tips(negotiator, args->negotiation_tips);
- for_each_cached_alternate(negotiator,
- insert_one_alternate_object);
- } else {
- filter_refs(args, &ref, sought, nr_sought);
+ mark_complete_and_common_ref(negotiator, args, &ref);
+ filter_refs(args, &ref, sought, nr_sought);
+ if (everything_local(args, &ref))
+ state = FETCH_DONE;
+ else
state = FETCH_SEND_REQUEST;
- }
+
+ mark_tips(negotiator, args->negotiation_tips);
+ for_each_cached_alternate(negotiator,
+ insert_one_alternate_object);
break;
case FETCH_SEND_REQUEST:
if (!negotiation_started) {
@@ -1635,7 +1665,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
receive_packfile_uris(&reader, &packfile_uris);
process_section_header(&reader, "packfile", 0);
if (get_pack(args, fd, pack_lockfiles,
- !packfile_uris.nr, sought, nr_sought))
+ packfile_uris.nr ? &index_pack_args : NULL,
+ sought, nr_sought, &fsck_options.gitmodules_found))
die(_("git fetch-pack: fetch failed."));
do_check_stateless_delimiter(args, &reader);
@@ -1647,16 +1678,20 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
}
for (i = 0; i < packfile_uris.nr; i++) {
+ int j;
struct child_process cmd = CHILD_PROCESS_INIT;
char packname[GIT_MAX_HEXSZ + 1];
const char *uri = packfile_uris.items[i].string +
the_hash_algo->hexsz + 1;
- argv_array_push(&cmd.args, "http-fetch");
- argv_array_pushf(&cmd.args, "--packfile=%.*s",
- (int) the_hash_algo->hexsz,
- packfile_uris.items[i].string);
- argv_array_push(&cmd.args, uri);
+ strvec_push(&cmd.args, "http-fetch");
+ strvec_pushf(&cmd.args, "--packfile=%.*s",
+ (int) the_hash_algo->hexsz,
+ packfile_uris.items[i].string);
+ for (j = 0; j < index_pack_args.nr; j++)
+ strvec_pushf(&cmd.args, "--index-pack-arg=%s",
+ index_pack_args.v[j]);
+ strvec_push(&cmd.args, uri);
cmd.git_cmd = 1;
cmd.no_stdin = 1;
cmd.out = -1;
@@ -1674,6 +1709,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
packname[the_hash_algo->hexsz] = '\0';
+ parse_gitmodules_oids(cmd.out, &fsck_options.gitmodules_found);
+
close(cmd.out);
if (finish_command(&cmd))
@@ -1691,6 +1728,10 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
packname));
}
string_list_clear(&packfile_uris, 0);
+ strvec_clear(&index_pack_args);
+
+ if (fsck_finish(&fsck_options))
+ die("fsck failed");
if (negotiator)
negotiator->release(negotiator);
@@ -1731,6 +1772,7 @@ static void fetch_pack_config(void)
git_config_get_bool("repack.usedeltabaseoffset", &prefer_ofs_delta);
git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
+ git_config_get_bool("transfer.advertisesid", &advertise_sid);
if (!uri_protocols.nr) {
char *str;
@@ -1863,7 +1905,7 @@ static void update_shallow(struct fetch_pack_args *args,
* remote is also shallow, check what ref is safe to update
* without updating .git/shallow
*/
- status = xcalloc(nr_sought, sizeof(*status));
+ CALLOC_ARRAY(status, nr_sought);
assign_shallow_commits_to_refs(si, NULL, status);
if (si->nr_ours || si->nr_theirs) {
for (i = 0; i < nr_sought; i++)
@@ -1902,20 +1944,6 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
if (nr_sought)
nr_sought = remove_duplicates_in_refs(sought, nr_sought);
- if (args->no_dependents && !args->filter_options.choice) {
- /*
- * The protocol does not support requesting that only the
- * wanted objects be sent, so approximate this by setting a
- * "blob:none" filter if no filter is already set. This works
- * for all object types: note that wanted blobs will still be
- * sent because they are directly specified as a "want".
- *
- * NEEDSWORK: Add an option in the protocol to request that
- * only the wanted objects be sent, and implement it.
- */
- parse_list_objects_filter(&args->filter_options, "blob:none");
- }
-
if (version != protocol_v2 && !ref) {
packet_flush(fd[1]);
die(_("no matching remote head"));