summaryrefslogtreecommitdiff
path: root/fetch-pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'fetch-pack.c')
-rw-r--r--fetch-pack.c148
1 files changed, 105 insertions, 43 deletions
diff --git a/fetch-pack.c b/fetch-pack.c
index 65be043f2a..ba92587023 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -36,7 +36,6 @@ static int agent_supported;
static int server_supports_filtering;
static struct lock_file shallow_lock;
static const char *alternate_shallow_file;
-static char *negotiation_algorithm;
static struct strbuf fsck_msg_types = STRBUF_INIT;
/* Remember to update object flag allocation in object.h */
@@ -168,16 +167,16 @@ static enum ack_type get_ack(struct packet_reader *reader,
if (!strcmp(reader->line, "NAK"))
return NAK;
if (skip_prefix(reader->line, "ACK ", &arg)) {
- if (!get_oid_hex(arg, result_oid)) {
- arg += 40;
- len -= arg - reader->line;
+ const char *p;
+ if (!parse_oid_hex(arg, result_oid, &p)) {
+ len -= p - reader->line;
if (len < 1)
return ACK;
- if (strstr(arg, "continue"))
+ if (strstr(p, "continue"))
return ACK_continue;
- if (strstr(arg, "common"))
+ if (strstr(p, "common"))
return ACK_common;
- if (strstr(arg, "ready"))
+ if (strstr(p, "ready"))
return ACK_ready;
return ACK;
}
@@ -339,12 +338,9 @@ static int find_common(struct fetch_negotiator *negotiator,
}
}
if (server_supports_filtering && args->filter_options.choice) {
- struct strbuf expanded_filter_spec = STRBUF_INIT;
- expand_list_objects_filter_spec(&args->filter_options,
- &expanded_filter_spec);
- packet_buf_write(&req_buf, "filter %s",
- expanded_filter_spec.buf);
- strbuf_release(&expanded_filter_spec);
+ const char *spec =
+ expand_list_objects_filter_spec(&args->filter_options);
+ packet_buf_write(&req_buf, "filter %s", spec);
}
packet_buf_flush(&req_buf);
state_len = req_buf.len;
@@ -386,6 +382,7 @@ static int find_common(struct fetch_negotiator *negotiator,
state_len = 0;
}
+ trace2_region_enter("fetch-pack", "negotiation_v0_v1", the_repository);
flushes = 0;
retval = -1;
if (args->no_dependents)
@@ -470,6 +467,7 @@ static int find_common(struct fetch_negotiator *negotiator,
}
}
done:
+ trace2_region_leave("fetch-pack", "negotiation_v0_v1", the_repository);
if (!got_ready || !no_done) {
packet_buf_write(&req_buf, "done\n");
send_request(args, fd[1], &req_buf);
@@ -675,7 +673,8 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
struct object *o;
if (!has_object_file_with_flags(&ref->old_oid,
- OBJECT_INFO_QUICK))
+ OBJECT_INFO_QUICK |
+ OBJECT_INFO_SKIP_FETCH_OBJECT))
continue;
o = parse_object(the_repository, &ref->old_oid);
if (!o)
@@ -758,8 +757,33 @@ 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)
+{
+ 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");
+ if (!suffix_stripped)
+ BUG("name of pack lockfile should end with .keep (was '%s')",
+ 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);
+
+ strbuf_release(&promisor_name);
+}
+
static int get_pack(struct fetch_pack_args *args,
- int xd[2], char **pack_lockfile)
+ int xd[2], char **pack_lockfile,
+ struct ref **sought, int nr_sought)
{
struct async demux;
int do_keep = args->keep_pack;
@@ -821,7 +845,13 @@ static int get_pack(struct fetch_pack_args *args,
}
if (args->check_self_contained_and_connected)
argv_array_push(&cmd.args, "--check-self-contained-and-connected");
- if (args->from_promisor)
+ /*
+ * 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_lockfile) && args->from_promisor)
argv_array_push(&cmd.args, "--promisor");
}
else {
@@ -875,6 +905,14 @@ static int get_pack(struct fetch_pack_args *args,
die(_("%s failed"), cmd_name);
if (use_sideband && finish_async(&demux))
die(_("error in sideband demultiplexer"));
+
+ /*
+ * Now that index-pack has succeeded, write the promisor file using the
+ * obtained .keep filename if necessary
+ */
+ if (do_keep && pack_lockfile && args->from_promisor)
+ write_promisor_file(*pack_lockfile, sought, nr_sought);
+
return 0;
}
@@ -892,12 +930,20 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
struct shallow_info *si,
char **pack_lockfile)
{
+ struct repository *r = the_repository;
struct ref *ref = copy_ref_list(orig_ref);
struct object_id oid;
const char *agent_feature;
int agent_len;
- struct fetch_negotiator negotiator;
- fetch_negotiator_init(&negotiator, negotiation_algorithm);
+ struct fetch_negotiator negotiator_alloc;
+ struct fetch_negotiator *negotiator;
+
+ if (args->no_dependents) {
+ negotiator = NULL;
+ } else {
+ negotiator = &negotiator_alloc;
+ fetch_negotiator_init(r, negotiator);
+ }
sort_ref_list(&ref, ref_compare_name);
QSORT(sought, nr_sought, cmp_ref_by_name);
@@ -911,7 +957,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
if (server_supports("shallow"))
print_verbose(args, _("Server supports %s"), "shallow");
- else if (args->depth > 0 || is_repository_shallow(the_repository))
+ else if (args->depth > 0 || is_repository_shallow(r))
die(_("Server does not support shallow clients"));
if (args->depth > 0 || args->deepen_since || args->deepen_not)
args->deepen = 1;
@@ -984,7 +1030,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
die(_("Server does not support --deepen"));
if (!args->no_dependents) {
- mark_complete_and_common_ref(&negotiator, args, &ref);
+ mark_complete_and_common_ref(negotiator, args, &ref);
filter_refs(args, &ref, sought, nr_sought);
if (everything_local(args, &ref)) {
packet_flush(fd[1]);
@@ -993,7 +1039,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
} else {
filter_refs(args, &ref, sought, nr_sought);
}
- if (find_common(&negotiator, args, fd, &oid, ref) < 0)
+ if (find_common(negotiator, args, fd, &oid, ref) < 0)
if (!args->keep_pack)
/* When cloning, it is not unusual to have
* no common commit.
@@ -1009,11 +1055,12 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
alternate_shallow_file = setup_temporary_shallow(si->shallow);
else
alternate_shallow_file = NULL;
- if (get_pack(args, fd, pack_lockfile))
+ if (get_pack(args, fd, pack_lockfile, sought, nr_sought))
die(_("git fetch-pack: fetch failed."));
all_done:
- negotiator.release(&negotiator);
+ if (negotiator)
+ negotiator->release(negotiator);
return ref;
}
@@ -1112,7 +1159,7 @@ static int add_haves(struct fetch_negotiator *negotiator,
}
static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
- const struct fetch_pack_args *args,
+ struct fetch_pack_args *args,
const struct ref *wants, struct oidset *common,
int *haves_to_send, int *in_vain,
int sideband_all)
@@ -1153,13 +1200,10 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
/* Add filter */
if (server_supports_feature("fetch", "filter", 0) &&
args->filter_options.choice) {
- struct strbuf expanded_filter_spec = STRBUF_INIT;
+ const char *spec =
+ expand_list_objects_filter_spec(&args->filter_options);
print_verbose(args, _("Server supports filter"));
- expand_list_objects_filter_spec(&args->filter_options,
- &expanded_filter_spec);
- packet_buf_write(&req_buf, "filter %s",
- expanded_filter_spec.buf);
- strbuf_release(&expanded_filter_spec);
+ packet_buf_write(&req_buf, "filter %s", spec);
} else if (args->filter_options.choice) {
warning("filtering not recognized by server, ignoring");
}
@@ -1234,7 +1278,8 @@ static int process_acks(struct fetch_negotiator *negotiator,
struct commit *commit;
oidset_insert(common, &oid);
commit = lookup_commit(the_repository, &oid);
- negotiator->ack(negotiator, commit);
+ if (negotiator)
+ negotiator->ack(negotiator, commit);
}
continue;
}
@@ -1379,14 +1424,23 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
struct shallow_info *si,
char **pack_lockfile)
{
+ struct repository *r = the_repository;
struct ref *ref = copy_ref_list(orig_ref);
enum fetch_state state = FETCH_CHECK_LOCAL;
struct oidset common = OIDSET_INIT;
struct packet_reader reader;
- int in_vain = 0;
+ int in_vain = 0, negotiation_started = 0;
int haves_to_send = INITIAL_FLUSH;
- struct fetch_negotiator negotiator;
- fetch_negotiator_init(&negotiator, negotiation_algorithm);
+ struct fetch_negotiator negotiator_alloc;
+ struct fetch_negotiator *negotiator;
+
+ if (args->no_dependents) {
+ negotiator = NULL;
+ } else {
+ negotiator = &negotiator_alloc;
+ fetch_negotiator_init(r, negotiator);
+ }
+
packet_reader_init(&reader, fd[0], NULL, 0,
PACKET_READ_CHOMP_NEWLINE |
PACKET_READ_DIE_ON_ERR_PACKET);
@@ -1410,15 +1464,15 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
/* Filter 'ref' by 'sought' and those that aren't local */
if (!args->no_dependents) {
- mark_complete_and_common_ref(&negotiator, args, &ref);
+ 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,
+ mark_tips(negotiator, args->negotiation_tips);
+ for_each_cached_alternate(negotiator,
insert_one_alternate_object);
} else {
filter_refs(args, &ref, sought, nr_sought);
@@ -1426,7 +1480,13 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
}
break;
case FETCH_SEND_REQUEST:
- if (send_fetch_request(&negotiator, fd[1], args, ref,
+ if (!negotiation_started) {
+ negotiation_started = 1;
+ trace2_region_enter("fetch-pack",
+ "negotiation_v2",
+ the_repository);
+ }
+ if (send_fetch_request(negotiator, fd[1], args, ref,
&common,
&haves_to_send, &in_vain,
reader.use_sideband))
@@ -1436,7 +1496,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
break;
case FETCH_PROCESS_ACKS:
/* Process ACKs/NAKs */
- switch (process_acks(&negotiator, &reader, &common)) {
+ switch (process_acks(negotiator, &reader, &common)) {
case 2:
state = FETCH_GET_PACK;
break;
@@ -1449,6 +1509,9 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
}
break;
case FETCH_GET_PACK:
+ trace2_region_leave("fetch-pack",
+ "negotiation_v2",
+ the_repository);
/* Check for shallow-info section */
if (process_section_header(&reader, "shallow-info", 1))
receive_shallow_info(args, &reader, shallows, si);
@@ -1458,7 +1521,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
/* get the pack */
process_section_header(&reader, "packfile", 0);
- if (get_pack(args, fd, pack_lockfile))
+ if (get_pack(args, fd, pack_lockfile, sought, nr_sought))
die(_("git fetch-pack: fetch failed."));
state = FETCH_DONE;
@@ -1468,7 +1531,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
}
}
- negotiator.release(&negotiator);
+ if (negotiator)
+ negotiator->release(negotiator);
oidset_clear(&common);
return ref;
}
@@ -1505,8 +1569,6 @@ 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_string("fetch.negotiationalgorithm",
- &negotiation_algorithm);
git_config(fetch_pack_config_cb, NULL);
}