blob: e16dee783dd7ac07e27b7f1307d1cfddd8ff654b [file] [log] [blame]
Elijah Newren5579f442023-04-11 00:41:48 -07001#include "git-compat-util.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07002#include "config.h"
Elijah Newren32a8f512023-03-21 06:26:03 +00003#include "environment.h"
Elijah Newrenf394e092023-03-21 06:25:54 +00004#include "gettext.h"
Elijah Newren41771fa2023-02-24 00:09:27 +00005#include "hex.h"
Linus Torvaldsdef88e92005-07-04 13:26:53 -07006#include "refs.h"
7#include "pkt-line.h"
Junio C Hamano958c24b2006-09-10 03:20:24 -07008#include "sideband.h"
Stefan Beller109cd762018-06-28 18:21:51 -07009#include "repository.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -070010#include "object-store.h"
Elijah Newren6f2d7432023-04-11 03:00:42 +000011#include "oid-array.h"
Junio C Hamanof6b42a82005-10-13 18:57:40 -070012#include "tag.h"
13#include "object.h"
Johannes Schindelinf0243f22005-10-28 04:48:32 +020014#include "commit.h"
Johannes Schindelin9b8dc262006-10-30 20:08:43 +010015#include "diff.h"
16#include "revision.h"
17#include "list-objects.h"
Jeff Hostetler10ac85c2017-12-08 15:58:39 +000018#include "list-objects-filter.h"
19#include "list-objects-filter-options.h"
Johannes Sixtcc41fa82007-10-19 21:47:59 +020020#include "run-command.h"
Junio C Hamano47a59182013-07-08 13:56:53 -070021#include "connect.h"
Junio C Hamano051e4002011-08-05 13:54:06 -070022#include "sigchain.h"
Jeff Kingff5effd2012-08-03 12:19:16 -040023#include "version.h"
Junio C Hamanodaebaa72013-01-18 16:08:30 -080024#include "string-list.h"
Jeff Kingdbbcd442020-07-28 16:23:39 -040025#include "strvec.h"
Elijah Newren74ea5c92023-04-11 03:00:38 +000026#include "trace2.h"
Jeff King5411b102016-10-11 17:20:16 -040027#include "prio-queue.h"
Brandon Williamsaa9bab22017-10-16 10:55:26 -070028#include "protocol.h"
Jeff Hostetler10ac85c2017-12-08 15:58:39 +000029#include "quote.h"
Brandon Williamsa3d6b532018-03-14 11:31:41 -070030#include "upload-pack.h"
Brandon Williams3145ea92018-03-15 10:31:27 -070031#include "serve.h"
Derrick Stolee829a3212018-08-20 18:24:34 +000032#include "commit-graph.h"
Derrick Stoleeba3ca1e2018-07-20 16:33:13 +000033#include "commit-reach.h"
Taylor Blau120ad2b2020-04-30 13:48:50 -060034#include "shallow.h"
Elijah Newren65156bb2023-04-11 00:42:02 -070035#include "wrapper.h"
Elijah Newrend48be352023-03-21 06:26:07 +000036#include "write-or-die.h"
Linus Torvaldsdef88e92005-07-04 13:26:53 -070037
Nguyễn Thái Ngọc Duy208acbf2014-03-25 20:23:26 +070038/* Remember to update object flag allocation in object.h */
Junio C Hamano937a5152006-07-05 21:28:20 -070039#define THEY_HAVE (1u << 11)
40#define OUR_REF (1u << 12)
41#define WANTED (1u << 13)
42#define COMMON_KNOWN (1u << 14)
Junio C Hamano937a5152006-07-05 21:28:20 -070043
Johannes Schindelinf53514b2006-10-30 20:09:53 +010044#define SHALLOW (1u << 16)
45#define NOT_SHALLOW (1u << 17)
46#define CLIENT_SHALLOW (1u << 18)
Junio C Hamano390eb362013-01-28 21:49:57 -080047#define HIDDEN_REF (1u << 19)
Johannes Schindelinf53514b2006-10-30 20:09:53 +010048
Jonathan Tand1035ca2018-10-18 13:43:29 -070049#define ALL_FLAGS (THEY_HAVE | OUR_REF | WANTED | COMMON_KNOWN | SHALLOW | \
50 NOT_SHALLOW | CLIENT_SHALLOW | HIDDEN_REF)
51
Christian Couder629060d2020-06-11 14:05:12 +020052/* Enum for allowed unadvertised object request (UOR) */
53enum allow_uor {
54 /* Allow specifying sha1 if it is a ref tip. */
55 ALLOW_TIP_SHA1 = 0x01,
56 /* Allow request of a sha1 if it is reachable from a ref (possibly hidden ref). */
57 ALLOW_REACHABLE_SHA1 = 0x02,
58 /* Allow request of any sha1. Implies ALLOW_TIP_SHA1 and ALLOW_REACHABLE_SHA1. */
59 ALLOW_ANY_SHA1 = 0x07
60};
H. Peter Anvin960decc2005-10-19 14:27:01 -070061
Christian Coudera8497282020-06-04 19:54:39 +020062/*
63 * Please annotate, and if possible group together, fields used only
64 * for protocol v0 or only for protocol v2.
65 */
Christian Coudere8498322020-05-15 12:04:44 +020066struct upload_pack_data {
Christian Coudera8497282020-06-04 19:54:39 +020067 struct string_list symref; /* v0 only */
Christian Coudere8498322020-05-15 12:04:44 +020068 struct object_array want_obj;
69 struct object_array have_obj;
Christian Coudera8497282020-06-04 19:54:39 +020070 struct oid_array haves; /* v2 only */
71 struct string_list wanted_refs; /* v2 only */
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +010072 struct string_list hidden_refs;
Christian Coudere8498322020-05-15 12:04:44 +020073
74 struct object_array shallows;
75 struct string_list deepen_not;
Christian Couderde0e9f72020-06-11 14:05:10 +020076 struct object_array extra_edge_obj;
Christian Coudere8498322020-05-15 12:04:44 +020077 int depth;
78 timestamp_t deepen_since;
79 int deepen_rev_list;
80 int deepen_relative;
Christian Couderf203a882020-06-04 19:54:46 +020081 int keepalive;
Christian Couder35b43a12020-06-11 14:05:09 +020082 int shallow_nr;
Christian Couderf01c7912020-06-11 14:05:17 +020083 timestamp_t oldest_have;
Christian Coudere8498322020-05-15 12:04:44 +020084
Christian Couderd40f04e2020-06-04 19:54:40 +020085 unsigned int timeout; /* v0 only */
Christian Coudere9d882b2020-06-04 19:54:44 +020086 enum {
87 NO_MULTI_ACK = 0,
88 MULTI_ACK = 1,
89 MULTI_ACK_DETAILED = 2
90 } multi_ack; /* v0 only */
Christian Couderd40f04e2020-06-04 19:54:40 +020091
Christian Couderf8edd1c2020-06-04 19:54:41 +020092 /* 0 for no sideband, otherwise DEFAULT_PACKET_MAX or LARGE_PACKET_MAX */
93 int use_sideband;
94
Jonathan Tandd4b7322020-06-10 13:57:23 -070095 struct string_list uri_protocols;
Christian Couder629060d2020-06-11 14:05:12 +020096 enum allow_uor allow_uor;
Christian Couderf1514c62020-06-11 14:05:11 +020097
Christian Coudere8498322020-05-15 12:04:44 +020098 struct list_objects_filter_options filter_options;
Taylor Blau6dd34562020-08-03 14:00:10 -040099 struct string_list allowed_filters;
Christian Coudere8498322020-05-15 12:04:44 +0200100
101 struct packet_writer writer;
102
Christian Couder339a9842020-06-04 19:54:50 +0200103 const char *pack_objects_hook;
104
Christian Coudera8497282020-06-04 19:54:39 +0200105 unsigned stateless_rpc : 1; /* v0 only */
Christian Couderd40f04e2020-06-04 19:54:40 +0200106 unsigned no_done : 1; /* v0 only */
107 unsigned daemon_mode : 1; /* v0 only */
Christian Couder59a90262020-06-04 19:54:42 +0200108 unsigned filter_capability_requested : 1; /* v0 only */
Christian Coudere8498322020-05-15 12:04:44 +0200109
110 unsigned use_thin_pack : 1;
111 unsigned use_ofs_delta : 1;
112 unsigned no_progress : 1;
113 unsigned use_include_tag : 1;
Jonathan Tan9c1e6572021-05-04 14:16:01 -0700114 unsigned wait_for_done : 1;
Christian Couder59abe192020-06-04 19:54:47 +0200115 unsigned allow_filter : 1;
Taylor Blau6dd34562020-08-03 14:00:10 -0400116 unsigned allow_filter_fallback : 1;
Taylor Blau5b01a4e2020-08-03 14:00:17 -0400117 unsigned long tree_filter_max_depth;
Christian Coudera8497282020-06-04 19:54:39 +0200118
119 unsigned done : 1; /* v2 only */
Christian Couderd1d7a942020-06-04 19:54:48 +0200120 unsigned allow_ref_in_want : 1; /* v2 only */
Christian Coudere3835cd2020-06-04 19:54:49 +0200121 unsigned allow_sideband_all : 1; /* v2 only */
Josh Steadmon791e1ad2020-11-11 15:29:27 -0800122 unsigned advertise_sid : 1;
Christian Coudere8498322020-05-15 12:04:44 +0200123};
124
125static void upload_pack_data_init(struct upload_pack_data *data)
126{
Christian Couder438528f2020-05-15 12:04:49 +0200127 struct string_list symref = STRING_LIST_INIT_DUP;
Christian Coudere8498322020-05-15 12:04:44 +0200128 struct string_list wanted_refs = STRING_LIST_INIT_DUP;
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +0100129 struct string_list hidden_refs = STRING_LIST_INIT_DUP;
Christian Coudere8498322020-05-15 12:04:44 +0200130 struct object_array want_obj = OBJECT_ARRAY_INIT;
131 struct object_array have_obj = OBJECT_ARRAY_INIT;
132 struct oid_array haves = OID_ARRAY_INIT;
133 struct object_array shallows = OBJECT_ARRAY_INIT;
134 struct string_list deepen_not = STRING_LIST_INIT_DUP;
Jonathan Tandd4b7322020-06-10 13:57:23 -0700135 struct string_list uri_protocols = STRING_LIST_INIT_DUP;
Christian Couderde0e9f72020-06-11 14:05:10 +0200136 struct object_array extra_edge_obj = OBJECT_ARRAY_INIT;
Taylor Blau6dd34562020-08-03 14:00:10 -0400137 struct string_list allowed_filters = STRING_LIST_INIT_DUP;
Christian Coudere8498322020-05-15 12:04:44 +0200138
139 memset(data, 0, sizeof(*data));
Christian Couder438528f2020-05-15 12:04:49 +0200140 data->symref = symref;
Christian Coudere8498322020-05-15 12:04:44 +0200141 data->wanted_refs = wanted_refs;
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +0100142 data->hidden_refs = hidden_refs;
Christian Coudere8498322020-05-15 12:04:44 +0200143 data->want_obj = want_obj;
144 data->have_obj = have_obj;
145 data->haves = haves;
146 data->shallows = shallows;
147 data->deepen_not = deepen_not;
Jonathan Tandd4b7322020-06-10 13:57:23 -0700148 data->uri_protocols = uri_protocols;
Christian Couderde0e9f72020-06-11 14:05:10 +0200149 data->extra_edge_obj = extra_edge_obj;
Taylor Blau6dd34562020-08-03 14:00:10 -0400150 data->allowed_filters = allowed_filters;
151 data->allow_filter_fallback = 1;
Taylor Blau5b01a4e2020-08-03 14:00:17 -0400152 data->tree_filter_max_depth = ULONG_MAX;
Christian Coudere8498322020-05-15 12:04:44 +0200153 packet_writer_init(&data->writer, 1);
Jeff King2a01bde2022-09-11 01:03:07 -0400154 list_objects_filter_init(&data->filter_options);
Christian Couderf203a882020-06-04 19:54:46 +0200155
156 data->keepalive = 5;
Josh Steadmon791e1ad2020-11-11 15:29:27 -0800157 data->advertise_sid = 0;
Christian Coudere8498322020-05-15 12:04:44 +0200158}
159
160static void upload_pack_data_clear(struct upload_pack_data *data)
161{
Christian Couder438528f2020-05-15 12:04:49 +0200162 string_list_clear(&data->symref, 1);
Christian Coudere8498322020-05-15 12:04:44 +0200163 string_list_clear(&data->wanted_refs, 1);
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +0100164 string_list_clear(&data->hidden_refs, 0);
Christian Coudere8498322020-05-15 12:04:44 +0200165 object_array_clear(&data->want_obj);
166 object_array_clear(&data->have_obj);
167 oid_array_clear(&data->haves);
168 object_array_clear(&data->shallows);
169 string_list_clear(&data->deepen_not, 0);
Christian Couderde0e9f72020-06-11 14:05:10 +0200170 object_array_clear(&data->extra_edge_obj);
Christian Coudere8498322020-05-15 12:04:44 +0200171 list_objects_filter_release(&data->filter_options);
Taylor Blau8d133f52020-12-03 13:55:18 -0500172 string_list_clear(&data->allowed_filters, 0);
Christian Couder339a9842020-06-04 19:54:50 +0200173
174 free((char *)data->pack_objects_hook);
Christian Coudere8498322020-05-15 12:04:44 +0200175}
176
Christian Couderd40f04e2020-06-04 19:54:40 +0200177static void reset_timeout(unsigned int timeout)
H. Peter Anvin960decc2005-10-19 14:27:01 -0700178{
179 alarm(timeout);
180}
Linus Torvaldsfb9040c2005-07-04 15:29:17 -0700181
Christian Couderf8edd1c2020-06-04 19:54:41 +0200182static void send_client_data(int fd, const char *data, ssize_t sz,
183 int use_sideband)
Junio C Hamano583b7ea2006-06-21 00:30:21 -0700184{
Lukas Fleischer4c4b7d12016-06-14 16:49:16 +0200185 if (use_sideband) {
186 send_sideband(1, fd, data, sz, use_sideband);
Lukas Fleischerfcf0fe92016-06-14 16:49:17 +0200187 return;
Lukas Fleischer4c4b7d12016-06-14 16:49:16 +0200188 }
Junio C Hamano958c24b2006-09-10 03:20:24 -0700189 if (fd == 3)
190 /* emergency quit */
191 fd = 2;
192 if (fd == 2) {
Andy Whitcroft93822c22007-01-08 15:58:23 +0000193 /* XXX: are we happy to lose stuff here? */
Junio C Hamano958c24b2006-09-10 03:20:24 -0700194 xwrite(fd, data, sz);
Lukas Fleischerfcf0fe92016-06-14 16:49:17 +0200195 return;
Junio C Hamano583b7ea2006-06-21 00:30:21 -0700196 }
Jeff Kingcdf4fb82013-02-20 15:01:56 -0500197 write_or_die(fd, data, sz);
Junio C Hamano583b7ea2006-06-21 00:30:21 -0700198}
199
Nguyễn Thái Ngọc Duyb790e0f2014-03-11 19:59:46 +0700200static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
201{
202 FILE *fp = cb_data;
203 if (graft->nr_parent == -1)
brian m. carlson7683e2e2015-03-13 23:39:34 +0000204 fprintf(fp, "--shallow %s\n", oid_to_hex(&graft->oid));
Nguyễn Thái Ngọc Duyb790e0f2014-03-11 19:59:46 +0700205 return 0;
206}
207
Jonathan Tanacaaca72020-06-10 13:57:21 -0700208struct output_state {
Jacob Vosmaer55a96512021-12-14 20:46:26 +0100209 /*
210 * We do writes no bigger than LARGE_PACKET_DATA_MAX - 1, because with
211 * sideband-64k the band designator takes up 1 byte of space. Because
212 * relay_pack_data keeps the last byte to itself, we make the buffer 1
213 * byte bigger than the intended maximum write size.
214 */
215 char buffer[(LARGE_PACKET_DATA_MAX - 1) + 1];
Jonathan Tanacaaca72020-06-10 13:57:21 -0700216 int used;
Jonathan Tandd4b7322020-06-10 13:57:23 -0700217 unsigned packfile_uris_started : 1;
218 unsigned packfile_started : 1;
Jonathan Tanacaaca72020-06-10 13:57:21 -0700219};
220
221static int relay_pack_data(int pack_objects_out, struct output_state *os,
Jonathan Tandd4b7322020-06-10 13:57:23 -0700222 int use_sideband, int write_packfile_line)
Jonathan Tanacaaca72020-06-10 13:57:21 -0700223{
224 /*
225 * We keep the last byte to ourselves
226 * in case we detect broken rev-list, so that we
227 * can leave the stream corrupted. This is
228 * unfortunate -- unpack-objects would happily
229 * accept a valid packdata with trailing garbage,
230 * so appending garbage after we pass all the
231 * pack data is not good enough to signal
232 * breakage to downstream.
233 */
234 ssize_t readsz;
235
236 readsz = xread(pack_objects_out, os->buffer + os->used,
237 sizeof(os->buffer) - os->used);
238 if (readsz < 0) {
239 return readsz;
240 }
241 os->used += readsz;
242
Jonathan Tandd4b7322020-06-10 13:57:23 -0700243 while (!os->packfile_started) {
244 char *p;
245 if (os->used >= 4 && !memcmp(os->buffer, "PACK", 4)) {
246 os->packfile_started = 1;
247 if (write_packfile_line) {
248 if (os->packfile_uris_started)
249 packet_delim(1);
250 packet_write_fmt(1, "\1packfile\n");
251 }
252 break;
253 }
254 if ((p = memchr(os->buffer, '\n', os->used))) {
255 if (!os->packfile_uris_started) {
256 os->packfile_uris_started = 1;
257 if (!write_packfile_line)
258 BUG("packfile_uris requires sideband-all");
259 packet_write_fmt(1, "\1packfile-uris\n");
260 }
261 *p = '\0';
262 packet_write_fmt(1, "\1%s\n", os->buffer);
263
264 os->used -= p - os->buffer + 1;
265 memmove(os->buffer, p + 1, os->used);
266 } else {
267 /*
268 * Incomplete line.
269 */
270 return readsz;
271 }
272 }
273
Jonathan Tanacaaca72020-06-10 13:57:21 -0700274 if (os->used > 1) {
275 send_client_data(1, os->buffer, os->used - 1, use_sideband);
276 os->buffer[0] = os->buffer[os->used - 1];
277 os->used = 1;
278 } else {
279 send_client_data(1, os->buffer, os->used, use_sideband);
280 os->used = 0;
281 }
282
283 return readsz;
284}
285
Jonathan Tandd4b7322020-06-10 13:57:23 -0700286static void create_pack_file(struct upload_pack_data *pack_data,
287 const struct string_list *uri_protocols)
Linus Torvaldsfb9040c2005-07-04 15:29:17 -0700288{
René Scharfed3180272014-08-19 21:09:35 +0200289 struct child_process pack_objects = CHILD_PROCESS_INIT;
Jacob Vosmaer55a96512021-12-14 20:46:26 +0100290 struct output_state *output_state = xcalloc(1, sizeof(struct output_state));
Jonathan Tanacaaca72020-06-10 13:57:21 -0700291 char progress[128];
Junio C Hamano583b7ea2006-06-21 00:30:21 -0700292 char abort_msg[] = "aborting due to possible repository "
293 "corruption on the remote side.";
Junio C Hamano1456b042009-12-10 12:17:11 -0800294 ssize_t sz;
Michael Procter65a36292016-02-25 12:13:26 +0000295 int i;
Nguyễn Thái Ngọc Duycdab4852013-08-16 16:52:05 +0700296 FILE *pipe_fd;
Linus Torvalds75bfc6c2005-07-04 16:35:13 -0700297
Christian Couder339a9842020-06-04 19:54:50 +0200298 if (!pack_data->pack_objects_hook)
Jeff King20b20a22016-05-18 18:45:37 -0400299 pack_objects.git_cmd = 1;
300 else {
Jeff Kingc972bf42020-07-28 16:25:12 -0400301 strvec_push(&pack_objects.args, pack_data->pack_objects_hook);
302 strvec_push(&pack_objects.args, "git");
Jeff King20b20a22016-05-18 18:45:37 -0400303 pack_objects.use_shell = 1;
304 }
305
Christian Couder35b43a12020-06-11 14:05:09 +0200306 if (pack_data->shallow_nr) {
Jeff Kingc972bf42020-07-28 16:25:12 -0400307 strvec_push(&pack_objects.args, "--shallow-file");
308 strvec_push(&pack_objects.args, "");
Nick Edelenf0cea832009-06-10 01:50:18 +0200309 }
Jeff Kingc972bf42020-07-28 16:25:12 -0400310 strvec_push(&pack_objects.args, "pack-objects");
311 strvec_push(&pack_objects.args, "--revs");
Jeff Kingb5a20682020-06-04 19:54:38 +0200312 if (pack_data->use_thin_pack)
Jeff Kingc972bf42020-07-28 16:25:12 -0400313 strvec_push(&pack_objects.args, "--thin");
Linus Torvalds75bfc6c2005-07-04 16:35:13 -0700314
Jeff Kingc972bf42020-07-28 16:25:12 -0400315 strvec_push(&pack_objects.args, "--stdout");
Christian Couder35b43a12020-06-11 14:05:09 +0200316 if (pack_data->shallow_nr)
Jeff Kingc972bf42020-07-28 16:25:12 -0400317 strvec_push(&pack_objects.args, "--shallow");
Jeff Kingb5a20682020-06-04 19:54:38 +0200318 if (!pack_data->no_progress)
Jeff Kingc972bf42020-07-28 16:25:12 -0400319 strvec_push(&pack_objects.args, "--progress");
Jeff Kingb5a20682020-06-04 19:54:38 +0200320 if (pack_data->use_ofs_delta)
Jeff Kingc972bf42020-07-28 16:25:12 -0400321 strvec_push(&pack_objects.args, "--delta-base-offset");
Jeff Kingb5a20682020-06-04 19:54:38 +0200322 if (pack_data->use_include_tag)
Jeff Kingc972bf42020-07-28 16:25:12 -0400323 strvec_push(&pack_objects.args, "--include-tag");
Christian Couderc9f03252020-05-15 12:04:53 +0200324 if (pack_data->filter_options.choice) {
Matthew DeVorecf9ceb52019-06-27 15:54:10 -0700325 const char *spec =
Christian Couderc9f03252020-05-15 12:04:53 +0200326 expand_list_objects_filter_spec(&pack_data->filter_options);
Jacob Vosmaerad5df6b2021-01-28 17:04:53 +0100327 strvec_pushf(&pack_objects.args, "--filter=%s", spec);
Jeff Hostetler10ac85c2017-12-08 15:58:39 +0000328 }
Jonathan Tandd4b7322020-06-10 13:57:23 -0700329 if (uri_protocols) {
330 for (i = 0; i < uri_protocols->nr; i++)
Jeff Kingc972bf42020-07-28 16:25:12 -0400331 strvec_pushf(&pack_objects.args, "--uri-protocol=%s",
Jonathan Tandd4b7322020-06-10 13:57:23 -0700332 uri_protocols->items[i].string);
333 }
Johannes Sixtcc41fa82007-10-19 21:47:59 +0200334
Jeff Kingb9612192011-04-06 17:33:33 -0400335 pack_objects.in = -1;
Johannes Sixtcc41fa82007-10-19 21:47:59 +0200336 pack_objects.out = -1;
337 pack_objects.err = -1;
Jeff King309a4022020-12-01 07:15:13 -0500338 pack_objects.clean_on_exit = 1;
Johannes Sixt21edd3f2007-10-19 21:48:03 +0200339
Johannes Sixt4c324c02007-11-04 20:46:48 +0100340 if (start_command(&pack_objects))
Junio C Hamano7e44c932008-08-31 09:39:19 -0700341 die("git upload-pack: unable to fork git-pack-objects");
Johannes Schindelin83a5ad62007-02-20 03:01:44 +0100342
Nguyễn Thái Ngọc Duycdab4852013-08-16 16:52:05 +0700343 pipe_fd = xfdopen(pack_objects.in, "w");
Nick Edelenf0cea832009-06-10 01:50:18 +0200344
Christian Couder35b43a12020-06-11 14:05:09 +0200345 if (pack_data->shallow_nr)
Nguyễn Thái Ngọc Duyb790e0f2014-03-11 19:59:46 +0700346 for_each_commit_graft(write_one_shallow, pipe_fd);
347
Christian Couderc9f03252020-05-15 12:04:53 +0200348 for (i = 0; i < pack_data->want_obj.nr; i++)
Nguyễn Thái Ngọc Duycdab4852013-08-16 16:52:05 +0700349 fprintf(pipe_fd, "%s\n",
Christian Couderc9f03252020-05-15 12:04:53 +0200350 oid_to_hex(&pack_data->want_obj.objects[i].item->oid));
Nguyễn Thái Ngọc Duycdab4852013-08-16 16:52:05 +0700351 fprintf(pipe_fd, "--not\n");
Christian Couderc9f03252020-05-15 12:04:53 +0200352 for (i = 0; i < pack_data->have_obj.nr; i++)
Nguyễn Thái Ngọc Duycdab4852013-08-16 16:52:05 +0700353 fprintf(pipe_fd, "%s\n",
Christian Couderc9f03252020-05-15 12:04:53 +0200354 oid_to_hex(&pack_data->have_obj.objects[i].item->oid));
Christian Couderde0e9f72020-06-11 14:05:10 +0200355 for (i = 0; i < pack_data->extra_edge_obj.nr; i++)
Nguyễn Thái Ngọc Duycdab4852013-08-16 16:52:05 +0700356 fprintf(pipe_fd, "%s\n",
Christian Couderde0e9f72020-06-11 14:05:10 +0200357 oid_to_hex(&pack_data->extra_edge_obj.objects[i].item->oid));
Nguyễn Thái Ngọc Duycdab4852013-08-16 16:52:05 +0700358 fprintf(pipe_fd, "\n");
359 fflush(pipe_fd);
360 fclose(pipe_fd);
Nick Edelenf0cea832009-06-10 01:50:18 +0200361
Johannes Sixtcc41fa82007-10-19 21:47:59 +0200362 /* We read from pack_objects.err to capture stderr output for
363 * progress bar, and pack_objects.out to capture the pack data.
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700364 */
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700365
366 while (1) {
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700367 struct pollfd pfd[2];
Christian Couderf203a882020-06-04 19:54:46 +0200368 int pe, pu, pollsize, polltimeout;
Jeff King05e95152013-09-08 05:01:31 -0400369 int ret;
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700370
Christian Couderd40f04e2020-06-04 19:54:40 +0200371 reset_timeout(pack_data->timeout);
Matthias Lederhofer0d516ad2006-07-18 19:14:51 +0200372
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700373 pollsize = 0;
Junio C Hamano363b7812006-06-20 22:48:23 -0700374 pe = pu = -1;
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700375
Johannes Sixtcc41fa82007-10-19 21:47:59 +0200376 if (0 <= pack_objects.out) {
377 pfd[pollsize].fd = pack_objects.out;
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700378 pfd[pollsize].events = POLLIN;
379 pu = pollsize;
380 pollsize++;
381 }
Johannes Sixtcc41fa82007-10-19 21:47:59 +0200382 if (0 <= pack_objects.err) {
383 pfd[pollsize].fd = pack_objects.err;
Junio C Hamano363b7812006-06-20 22:48:23 -0700384 pfd[pollsize].events = POLLIN;
385 pe = pollsize;
386 pollsize++;
387 }
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700388
Johannes Sixt4c324c02007-11-04 20:46:48 +0100389 if (!pollsize)
390 break;
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700391
Christian Couderf203a882020-06-04 19:54:46 +0200392 polltimeout = pack_data->keepalive < 0
393 ? -1
394 : 1000 * pack_data->keepalive;
395
396 ret = poll(pfd, pollsize, polltimeout);
Edward Thomson6c71f8b2014-08-22 15:19:11 +0000397
Jeff King05e95152013-09-08 05:01:31 -0400398 if (ret < 0) {
Johannes Sixt4c324c02007-11-04 20:46:48 +0100399 if (errno != EINTR) {
Nguyễn Thái Ngọc Duyd2b6afa2016-05-08 16:47:59 +0700400 error_errno("poll failed, resuming");
Johannes Sixt4c324c02007-11-04 20:46:48 +0100401 sleep(1);
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700402 }
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700403 continue;
Johannes Sixt4c324c02007-11-04 20:46:48 +0100404 }
Nicolas Pitre6b59f512009-11-11 17:24:42 -0500405 if (0 <= pe && (pfd[pe].revents & (POLLIN|POLLHUP))) {
406 /* Status ready; we ship that in the side-band
407 * or dump to the standard error.
408 */
409 sz = xread(pack_objects.err, progress,
410 sizeof(progress));
411 if (0 < sz)
Christian Couderf8edd1c2020-06-04 19:54:41 +0200412 send_client_data(2, progress, sz,
413 pack_data->use_sideband);
Nicolas Pitre6b59f512009-11-11 17:24:42 -0500414 else if (sz == 0) {
415 close(pack_objects.err);
416 pack_objects.err = -1;
417 }
418 else
419 goto fail;
420 /* give priority to status messages */
421 continue;
422 }
Johannes Sixt4c324c02007-11-04 20:46:48 +0100423 if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
Jonathan Tanacaaca72020-06-10 13:57:21 -0700424 int result = relay_pack_data(pack_objects.out,
Jacob Vosmaer55a96512021-12-14 20:46:26 +0100425 output_state,
Jonathan Tandd4b7322020-06-10 13:57:23 -0700426 pack_data->use_sideband,
427 !!uri_protocols);
Jonathan Tanacaaca72020-06-10 13:57:21 -0700428
429 if (result == 0) {
Johannes Sixt4c324c02007-11-04 20:46:48 +0100430 close(pack_objects.out);
431 pack_objects.out = -1;
Jonathan Tanacaaca72020-06-10 13:57:21 -0700432 } else if (result < 0) {
Johannes Sixt4c324c02007-11-04 20:46:48 +0100433 goto fail;
Johannes Sixt4c324c02007-11-04 20:46:48 +0100434 }
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700435 }
Jeff King05e95152013-09-08 05:01:31 -0400436
437 /*
438 * We hit the keepalive timeout without saying anything; send
439 * an empty message on the data sideband just to let the other
440 * side know we're still working on it, but don't have any data
441 * yet.
442 *
443 * If we don't have a sideband channel, there's no room in the
444 * protocol to say anything, so those clients are just out of
445 * luck.
446 */
Christian Couderf8edd1c2020-06-04 19:54:41 +0200447 if (!ret && pack_data->use_sideband) {
Jeff King05e95152013-09-08 05:01:31 -0400448 static const char buf[] = "0005\1";
449 write_or_die(1, buf, 5);
450 }
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700451 }
Johannes Sixt4c324c02007-11-04 20:46:48 +0100452
453 if (finish_command(&pack_objects)) {
Junio C Hamano7e44c932008-08-31 09:39:19 -0700454 error("git upload-pack: git-pack-objects died with error.");
Johannes Sixt4c324c02007-11-04 20:46:48 +0100455 goto fail;
456 }
Johannes Sixt4c324c02007-11-04 20:46:48 +0100457
458 /* flush the data */
Jacob Vosmaer55a96512021-12-14 20:46:26 +0100459 if (output_state->used > 0) {
460 send_client_data(1, output_state->buffer, output_state->used,
Christian Couderf8edd1c2020-06-04 19:54:41 +0200461 pack_data->use_sideband);
Johannes Sixt4c324c02007-11-04 20:46:48 +0100462 fprintf(stderr, "flushed.\n");
463 }
Jacob Vosmaer55a96512021-12-14 20:46:26 +0100464 free(output_state);
Christian Couderf8edd1c2020-06-04 19:54:41 +0200465 if (pack_data->use_sideband)
Johannes Sixt4c324c02007-11-04 20:46:48 +0100466 packet_flush(1);
467 return;
468
Junio C Hamanob1c71b72006-06-20 18:26:34 -0700469 fail:
Ævar Arnfjörð Bjarmasonc68d5db2022-07-28 01:13:42 +0200470 free(output_state);
Christian Couderf8edd1c2020-06-04 19:54:41 +0200471 send_client_data(3, abort_msg, sizeof(abort_msg),
472 pack_data->use_sideband);
Junio C Hamano7e44c932008-08-31 09:39:19 -0700473 die("git upload-pack: %s", abort_msg);
Linus Torvaldsfb9040c2005-07-04 15:29:17 -0700474}
475
Christian Couderea2c6e62020-06-11 14:05:18 +0200476static int do_got_oid(struct upload_pack_data *data, const struct object_id *oid)
Linus Torvaldsdef88e92005-07-04 13:26:53 -0700477{
Junio C Hamano937a5152006-07-05 21:28:20 -0700478 int we_knew_they_have = 0;
Christian Couderea2c6e62020-06-11 14:05:18 +0200479 struct object *o = parse_object(the_repository, oid);
Junio C Hamanob1e9fff2006-07-05 18:00:02 -0700480
Junio C Hamanob1e9fff2006-07-05 18:00:02 -0700481 if (!o)
brian m. carlsoncf939822017-05-06 22:10:28 +0000482 die("oops (%s)", oid_to_hex(oid));
Junio C Hamano182a8da2006-08-12 22:16:51 -0700483 if (o->type == OBJ_COMMIT) {
Junio C Hamanob1e9fff2006-07-05 18:00:02 -0700484 struct commit_list *parents;
Junio C Hamano937a5152006-07-05 21:28:20 -0700485 struct commit *commit = (struct commit *)o;
Junio C Hamanob1e9fff2006-07-05 18:00:02 -0700486 if (o->flags & THEY_HAVE)
Junio C Hamano937a5152006-07-05 21:28:20 -0700487 we_knew_they_have = 1;
488 else
489 o->flags |= THEY_HAVE;
Christian Couderf01c7912020-06-11 14:05:17 +0200490 if (!data->oldest_have || (commit->date < data->oldest_have))
491 data->oldest_have = commit->date;
Junio C Hamano937a5152006-07-05 21:28:20 -0700492 for (parents = commit->parents;
Junio C Hamanob1e9fff2006-07-05 18:00:02 -0700493 parents;
494 parents = parents->next)
495 parents->item->object.flags |= THEY_HAVE;
Linus Torvaldsfb9040c2005-07-04 15:29:17 -0700496 }
Junio C Hamano937a5152006-07-05 21:28:20 -0700497 if (!we_knew_they_have) {
Christian Couder460ed0d2020-06-11 14:05:16 +0200498 add_object_array(o, NULL, &data->have_obj);
Junio C Hamano937a5152006-07-05 21:28:20 -0700499 return 1;
500 }
501 return 0;
502}
503
Christian Couderea2c6e62020-06-11 14:05:18 +0200504static int got_oid(struct upload_pack_data *data,
505 const char *hex, struct object_id *oid)
506{
507 if (get_oid_hex(hex, oid))
508 die("git upload-pack: expected SHA1 object, got '%s'", hex);
Ævar Arnfjörð Bjarmasonbc726bd2023-03-28 15:58:50 +0200509 if (!repo_has_object_file_with_flags(the_repository, oid,
510 OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT))
Christian Couderea2c6e62020-06-11 14:05:18 +0200511 return -1;
512 return do_got_oid(data, oid);
513}
514
Christian Couder08667342020-06-11 14:05:15 +0200515static int ok_to_give_up(struct upload_pack_data *data)
Junio C Hamano937a5152006-07-05 21:28:20 -0700516{
Abhishek Kumard7f92782021-01-16 18:11:13 +0000517 timestamp_t min_generation = GENERATION_NUMBER_ZERO;
Junio C Hamano937a5152006-07-05 21:28:20 -0700518
Christian Couder08667342020-06-11 14:05:15 +0200519 if (!data->have_obj.nr)
Junio C Hamano937a5152006-07-05 21:28:20 -0700520 return 0;
521
Christian Couder08667342020-06-11 14:05:15 +0200522 return can_all_from_reach_with_flag(&data->want_obj, THEY_HAVE,
Christian Couderf01c7912020-06-11 14:05:17 +0200523 COMMON_KNOWN, data->oldest_have,
Derrick Stolee4fbcca42018-07-20 16:33:28 +0000524 min_generation);
Linus Torvaldsdef88e92005-07-04 13:26:53 -0700525}
526
Christian Couder07977692020-05-15 12:04:46 +0200527static int get_common_commits(struct upload_pack_data *data,
528 struct packet_reader *reader)
Linus Torvaldsdef88e92005-07-04 13:26:53 -0700529{
brian m. carlsoncf939822017-05-06 22:10:28 +0000530 struct object_id oid;
531 char last_hex[GIT_MAX_HEXSZ + 1];
Shawn O. Pearce49bee712011-03-14 16:48:39 -0700532 int got_common = 0;
533 int got_other = 0;
Junio C Hamano4e10cf92011-03-29 12:29:10 -0700534 int sent_ready = 0;
Linus Torvaldsdef88e92005-07-04 13:26:53 -0700535
Johannes Schindelinf0243f22005-10-28 04:48:32 +0200536 save_commit_buffer = 0;
537
Brian Gianforcaroeeefa7c2009-09-01 01:35:10 -0400538 for (;;) {
Nguyễn Thái Ngọc Duy8bf3b752016-06-12 17:53:49 +0700539 const char *arg;
540
Christian Couderd40f04e2020-06-04 19:54:40 +0200541 reset_timeout(data->timeout);
Linus Torvaldsdef88e92005-07-04 13:26:53 -0700542
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800543 if (packet_reader_read(reader) != PACKET_READ_NORMAL) {
Christian Coudere9d882b2020-06-04 19:54:44 +0200544 if (data->multi_ack == MULTI_ACK_DETAILED
Christian Couder07977692020-05-15 12:04:46 +0200545 && got_common
546 && !got_other
Christian Couder08667342020-06-11 14:05:15 +0200547 && ok_to_give_up(data)) {
Junio C Hamano4e10cf92011-03-29 12:29:10 -0700548 sent_ready = 1;
Lars Schneider81c634e2016-10-16 16:20:29 -0700549 packet_write_fmt(1, "ACK %s ready\n", last_hex);
Junio C Hamano4e10cf92011-03-29 12:29:10 -0700550 }
Christian Couder53d69502020-06-04 19:54:43 +0200551 if (data->have_obj.nr == 0 || data->multi_ack)
Lars Schneider81c634e2016-10-16 16:20:29 -0700552 packet_write_fmt(1, "NAK\n");
Junio C Hamano4e10cf92011-03-29 12:29:10 -0700553
Christian Couderd40f04e2020-06-04 19:54:40 +0200554 if (data->no_done && sent_ready) {
Lars Schneider81c634e2016-10-16 16:20:29 -0700555 packet_write_fmt(1, "ACK %s\n", last_hex);
Junio C Hamano4e10cf92011-03-29 12:29:10 -0700556 return 0;
557 }
Christian Couderdf654ab2020-05-15 12:04:52 +0200558 if (data->stateless_rpc)
Shawn O. Pearce42526b42009-10-30 17:47:33 -0700559 exit(0);
Shawn O. Pearce49bee712011-03-14 16:48:39 -0700560 got_common = 0;
561 got_other = 0;
Linus Torvaldsdef88e92005-07-04 13:26:53 -0700562 continue;
563 }
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800564 if (skip_prefix(reader->line, "have ", &arg)) {
Christian Couder460ed0d2020-06-11 14:05:16 +0200565 switch (got_oid(data, arg, &oid)) {
Junio C Hamano937a5152006-07-05 21:28:20 -0700566 case -1: /* they have what we do not */
Shawn O. Pearce49bee712011-03-14 16:48:39 -0700567 got_other = 1;
Christian Couder53d69502020-06-04 19:54:43 +0200568 if (data->multi_ack
Christian Couder08667342020-06-11 14:05:15 +0200569 && ok_to_give_up(data)) {
brian m. carlsoncf939822017-05-06 22:10:28 +0000570 const char *hex = oid_to_hex(&oid);
Christian Coudere9d882b2020-06-04 19:54:44 +0200571 if (data->multi_ack == MULTI_ACK_DETAILED) {
Junio C Hamano4e10cf92011-03-29 12:29:10 -0700572 sent_ready = 1;
Lars Schneider81c634e2016-10-16 16:20:29 -0700573 packet_write_fmt(1, "ACK %s ready\n", hex);
Junio C Hamano4e10cf92011-03-29 12:29:10 -0700574 } else
Lars Schneider81c634e2016-10-16 16:20:29 -0700575 packet_write_fmt(1, "ACK %s continue\n", hex);
Shawn O. Pearce78affc42009-10-30 17:47:25 -0700576 }
Junio C Hamano937a5152006-07-05 21:28:20 -0700577 break;
578 default:
Shawn O. Pearce49bee712011-03-14 16:48:39 -0700579 got_common = 1;
brian m. carlson55dc2272018-05-02 00:25:51 +0000580 oid_to_hex_r(last_hex, &oid);
Christian Coudere9d882b2020-06-04 19:54:44 +0200581 if (data->multi_ack == MULTI_ACK_DETAILED)
Lars Schneider81c634e2016-10-16 16:20:29 -0700582 packet_write_fmt(1, "ACK %s common\n", last_hex);
Christian Couder53d69502020-06-04 19:54:43 +0200583 else if (data->multi_ack)
Lars Schneider81c634e2016-10-16 16:20:29 -0700584 packet_write_fmt(1, "ACK %s continue\n", last_hex);
Christian Couder07977692020-05-15 12:04:46 +0200585 else if (data->have_obj.nr == 1)
Lars Schneider81c634e2016-10-16 16:20:29 -0700586 packet_write_fmt(1, "ACK %s\n", last_hex);
Junio C Hamano937a5152006-07-05 21:28:20 -0700587 break;
Junio C Hamanoaf2d3aa2005-10-25 14:55:24 -0700588 }
Linus Torvaldsdef88e92005-07-04 13:26:53 -0700589 continue;
590 }
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800591 if (!strcmp(reader->line, "done")) {
Christian Couder07977692020-05-15 12:04:46 +0200592 if (data->have_obj.nr > 0) {
Christian Couder53d69502020-06-04 19:54:43 +0200593 if (data->multi_ack)
Lars Schneider81c634e2016-10-16 16:20:29 -0700594 packet_write_fmt(1, "ACK %s\n", last_hex);
Johannes Schindelin1bd8c8f2005-10-28 04:49:16 +0200595 return 0;
596 }
Lars Schneider81c634e2016-10-16 16:20:29 -0700597 packet_write_fmt(1, "NAK\n");
Linus Torvaldsdef88e92005-07-04 13:26:53 -0700598 return -1;
599 }
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800600 die("git upload-pack: expected SHA1 list, got '%s'", reader->line);
Linus Torvaldsdef88e92005-07-04 13:26:53 -0700601 }
Linus Torvaldsdef88e92005-07-04 13:26:53 -0700602}
603
Christian Couder629060d2020-06-11 14:05:12 +0200604static int is_our_ref(struct object *o, enum allow_uor allow_uor)
Junio C Hamano390eb362013-01-28 21:49:57 -0800605{
Christian Couder629060d2020-06-11 14:05:12 +0200606 int allow_hidden_ref = (allow_uor &
607 (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1));
Fredrik Medley7199c092015-05-21 22:23:38 +0200608 return o->flags & ((allow_hidden_ref ? HIDDEN_REF : 0) | OUR_REF);
Junio C Hamano390eb362013-01-28 21:49:57 -0800609}
610
Nguyễn Thái Ngọc Duy29971782016-06-12 17:54:07 +0700611/*
612 * on successful case, it's up to the caller to close cmd->out
613 */
614static int do_reachable_revlist(struct child_process *cmd,
Nguyễn Thái Ngọc Duy079aa972016-06-12 17:54:08 +0700615 struct object_array *src,
Christian Couderf1514c62020-06-11 14:05:11 +0200616 struct object_array *reachable,
Christian Couder629060d2020-06-11 14:05:12 +0200617 enum allow_uor allow_uor)
Junio C Hamano051e4002011-08-05 13:54:06 -0700618{
Junio C Hamano051e4002011-08-05 13:54:06 -0700619 struct object *o;
René Scharfea698d672020-08-12 18:52:55 +0200620 FILE *cmd_in = NULL;
Junio C Hamano051e4002011-08-05 13:54:06 -0700621 int i;
622
Ævar Arnfjörð Bjarmason2b709892021-11-25 23:52:20 +0100623 strvec_pushl(&cmd->args, "rev-list", "--stdin", NULL);
Nguyễn Thái Ngọc Duy29971782016-06-12 17:54:07 +0700624 cmd->git_cmd = 1;
625 cmd->no_stderr = 1;
626 cmd->in = -1;
627 cmd->out = -1;
Junio C Hamano051e4002011-08-05 13:54:06 -0700628
629 /*
Nguyễn Thái Ngọc Duy7fcbd372016-06-12 17:53:51 +0700630 * If the next rev-list --stdin encounters an unknown commit,
631 * it terminates, which will cause SIGPIPE in the write loop
Junio C Hamano051e4002011-08-05 13:54:06 -0700632 * below.
633 */
634 sigchain_push(SIGPIPE, SIG_IGN);
635
Nguyễn Thái Ngọc Duy29971782016-06-12 17:54:07 +0700636 if (start_command(cmd))
Nguyễn Thái Ngọc Duy7fcbd372016-06-12 17:53:51 +0700637 goto error;
638
René Scharfea698d672020-08-12 18:52:55 +0200639 cmd_in = xfdopen(cmd->in, "w");
640
Junio C Hamano051e4002011-08-05 13:54:06 -0700641 for (i = get_max_object_index(); 0 < i; ) {
642 o = get_indexed_object(--i);
Brian Harring2a745322011-08-23 22:47:17 -0700643 if (!o)
644 continue;
Nguyễn Thái Ngọc Duy079aa972016-06-12 17:54:08 +0700645 if (reachable && o->type == OBJ_COMMIT)
646 o->flags &= ~TMP_MARK;
Christian Couder629060d2020-06-11 14:05:12 +0200647 if (!is_our_ref(o, allow_uor))
Junio C Hamano051e4002011-08-05 13:54:06 -0700648 continue;
René Scharfea698d672020-08-12 18:52:55 +0200649 if (fprintf(cmd_in, "^%s\n", oid_to_hex(&o->oid)) < 0)
Junio C Hamano051e4002011-08-05 13:54:06 -0700650 goto error;
651 }
Nguyễn Thái Ngọc Duy3f0f6622016-06-12 17:53:52 +0700652 for (i = 0; i < src->nr; i++) {
653 o = src->objects[i].item;
Christian Couder629060d2020-06-11 14:05:12 +0200654 if (is_our_ref(o, allow_uor)) {
Nguyễn Thái Ngọc Duy079aa972016-06-12 17:54:08 +0700655 if (reachable)
656 add_object_array(o, NULL, reachable);
Junio C Hamano051e4002011-08-05 13:54:06 -0700657 continue;
Nguyễn Thái Ngọc Duy079aa972016-06-12 17:54:08 +0700658 }
659 if (reachable && o->type == OBJ_COMMIT)
660 o->flags |= TMP_MARK;
René Scharfea698d672020-08-12 18:52:55 +0200661 if (fprintf(cmd_in, "%s\n", oid_to_hex(&o->oid)) < 0)
Junio C Hamano051e4002011-08-05 13:54:06 -0700662 goto error;
663 }
René Scharfea698d672020-08-12 18:52:55 +0200664 if (ferror(cmd_in) || fflush(cmd_in))
665 goto error;
666 fclose(cmd_in);
Nguyễn Thái Ngọc Duy29971782016-06-12 17:54:07 +0700667 cmd->in = -1;
Junio C Hamano051e4002011-08-05 13:54:06 -0700668 sigchain_pop(SIGPIPE);
669
Nguyễn Thái Ngọc Duy29971782016-06-12 17:54:07 +0700670 return 0;
671
672error:
673 sigchain_pop(SIGPIPE);
674
René Scharfea698d672020-08-12 18:52:55 +0200675 if (cmd_in)
676 fclose(cmd_in);
Nguyễn Thái Ngọc Duy29971782016-06-12 17:54:07 +0700677 if (cmd->out >= 0)
678 close(cmd->out);
679 return -1;
680}
681
Christian Couderf1514c62020-06-11 14:05:11 +0200682static int get_reachable_list(struct upload_pack_data *data,
Nguyễn Thái Ngọc Duy079aa972016-06-12 17:54:08 +0700683 struct object_array *reachable)
684{
685 struct child_process cmd = CHILD_PROCESS_INIT;
686 int i;
687 struct object *o;
brian m. carlson55dc2272018-05-02 00:25:51 +0000688 char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */
689 const unsigned hexsz = the_hash_algo->hexsz;
Nguyễn Thái Ngọc Duy079aa972016-06-12 17:54:08 +0700690
Christian Couderf1514c62020-06-11 14:05:11 +0200691 if (do_reachable_revlist(&cmd, &data->shallows, reachable,
Christian Couder629060d2020-06-11 14:05:12 +0200692 data->allow_uor) < 0)
Nguyễn Thái Ngọc Duy079aa972016-06-12 17:54:08 +0700693 return -1;
694
brian m. carlson55dc2272018-05-02 00:25:51 +0000695 while ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) {
Jeff King62b89d42019-06-20 03:40:54 -0400696 struct object_id oid;
brian m. carlson55dc2272018-05-02 00:25:51 +0000697 const char *p;
Nguyễn Thái Ngọc Duy079aa972016-06-12 17:54:08 +0700698
Jeff King62b89d42019-06-20 03:40:54 -0400699 if (parse_oid_hex(namebuf, &oid, &p) || *p != '\n')
Nguyễn Thái Ngọc Duy079aa972016-06-12 17:54:08 +0700700 break;
701
Jeff Kingd0229ab2019-06-20 03:41:14 -0400702 o = lookup_object(the_repository, &oid);
Nguyễn Thái Ngọc Duy079aa972016-06-12 17:54:08 +0700703 if (o && o->type == OBJ_COMMIT) {
704 o->flags &= ~TMP_MARK;
705 }
706 }
707 for (i = get_max_object_index(); 0 < i; i--) {
708 o = get_indexed_object(i - 1);
709 if (o && o->type == OBJ_COMMIT &&
710 (o->flags & TMP_MARK)) {
711 add_object_array(o, NULL, reachable);
712 o->flags &= ~TMP_MARK;
713 }
714 }
715 close(cmd.out);
716
717 if (finish_command(&cmd))
718 return -1;
719
720 return 0;
721}
722
Christian Couder629060d2020-06-11 14:05:12 +0200723static int has_unreachable(struct object_array *src, enum allow_uor allow_uor)
Nguyễn Thái Ngọc Duy29971782016-06-12 17:54:07 +0700724{
725 struct child_process cmd = CHILD_PROCESS_INIT;
726 char buf[1];
727 int i;
728
Christian Couder629060d2020-06-11 14:05:12 +0200729 if (do_reachable_revlist(&cmd, src, NULL, allow_uor) < 0)
Nguyễn Thái Ngọc Duy29971782016-06-12 17:54:07 +0700730 return 1;
Junio C Hamano051e4002011-08-05 13:54:06 -0700731
732 /*
733 * The commits out of the rev-list are not ancestors of
734 * our ref.
735 */
Nguyễn Thái Ngọc Duy29971782016-06-12 17:54:07 +0700736 i = read_in_full(cmd.out, buf, 1);
Junio C Hamano051e4002011-08-05 13:54:06 -0700737 if (i)
738 goto error;
739 close(cmd.out);
Nguyễn Thái Ngọc Duy7fcbd372016-06-12 17:53:51 +0700740 cmd.out = -1;
Junio C Hamano051e4002011-08-05 13:54:06 -0700741
742 /*
743 * rev-list may have died by encountering a bad commit
744 * in the history, in which case we do want to bail out
745 * even when it showed no commit.
746 */
747 if (finish_command(&cmd))
748 goto error;
749
750 /* All the non-tip ones are ancestors of what we advertised */
Nguyễn Thái Ngọc Duy3f0f6622016-06-12 17:53:52 +0700751 return 0;
Junio C Hamano051e4002011-08-05 13:54:06 -0700752
753error:
Nguyễn Thái Ngọc Duy7fcbd372016-06-12 17:53:51 +0700754 if (cmd.out >= 0)
755 close(cmd.out);
Nguyễn Thái Ngọc Duy3f0f6622016-06-12 17:53:52 +0700756 return 1;
757}
Nguyễn Thái Ngọc Duy7fcbd372016-06-12 17:53:51 +0700758
Christian Couderb08c9742020-05-15 12:04:51 +0200759static void check_non_tip(struct upload_pack_data *data)
Nguyễn Thái Ngọc Duy3f0f6622016-06-12 17:53:52 +0700760{
761 int i;
762
763 /*
764 * In the normal in-process case without
765 * uploadpack.allowReachableSHA1InWant,
766 * non-tip requests can never happen.
767 */
Christian Couder629060d2020-06-11 14:05:12 +0200768 if (!data->stateless_rpc && !(data->allow_uor & ALLOW_REACHABLE_SHA1))
Nguyễn Thái Ngọc Duy3f0f6622016-06-12 17:53:52 +0700769 goto error;
Christian Couder629060d2020-06-11 14:05:12 +0200770 if (!has_unreachable(&data->want_obj, data->allow_uor))
Nguyễn Thái Ngọc Duy3f0f6622016-06-12 17:53:52 +0700771 /* All the non-tip ones are ancestors of what we advertised */
772 return;
Junio C Hamano051e4002011-08-05 13:54:06 -0700773
774error:
775 /* Pick one of them (we know there at least is one) */
Christian Couderb08c9742020-05-15 12:04:51 +0200776 for (i = 0; i < data->want_obj.nr; i++) {
777 struct object *o = data->want_obj.objects[i].item;
Christian Couder629060d2020-06-11 14:05:12 +0200778 if (!is_our_ref(o, data->allow_uor)) {
Christian Couderb08c9742020-05-15 12:04:51 +0200779 packet_writer_error(&data->writer,
Jeff King014ade72019-04-13 01:53:34 -0400780 "upload-pack: not our ref %s",
781 oid_to_hex(&o->oid));
Junio C Hamano051e4002011-08-05 13:54:06 -0700782 die("git upload-pack: not our ref %s",
brian m. carlsonf2fd0762015-11-10 02:22:28 +0000783 oid_to_hex(&o->oid));
Jeff King014ade72019-04-13 01:53:34 -0400784 }
Junio C Hamano051e4002011-08-05 13:54:06 -0700785 }
786}
787
Christian Couder35b43a12020-06-11 14:05:09 +0200788static void send_shallow(struct upload_pack_data *data,
Jonathan Tanbc2e7952019-01-15 11:40:27 -0800789 struct commit_list *result)
Nguyễn Thái Ngọc Duy5c24cde2016-06-12 17:53:46 +0700790{
791 while (result) {
792 struct object *object = &result->item->object;
793 if (!(object->flags & (CLIENT_SHALLOW|NOT_SHALLOW))) {
Christian Couder35b43a12020-06-11 14:05:09 +0200794 packet_writer_write(&data->writer, "shallow %s",
Jonathan Tanbc2e7952019-01-15 11:40:27 -0800795 oid_to_hex(&object->oid));
Stefan Beller19143f12018-05-17 15:51:44 -0700796 register_shallow(the_repository, &object->oid);
Christian Couder35b43a12020-06-11 14:05:09 +0200797 data->shallow_nr++;
Nguyễn Thái Ngọc Duy5c24cde2016-06-12 17:53:46 +0700798 }
799 result = result->next;
800 }
801}
802
Christian Couder329f9962020-06-11 14:05:08 +0200803static void send_unshallow(struct upload_pack_data *data)
Nguyễn Thái Ngọc Duye8e44de2016-06-12 17:53:45 +0700804{
Nguyễn Thái Ngọc Duye8e44de2016-06-12 17:53:45 +0700805 int i;
Nguyễn Thái Ngọc Duy873700c2016-06-12 17:53:48 +0700806
Christian Couder329f9962020-06-11 14:05:08 +0200807 for (i = 0; i < data->shallows.nr; i++) {
808 struct object *object = data->shallows.objects[i].item;
Nguyễn Thái Ngọc Duye8e44de2016-06-12 17:53:45 +0700809 if (object->flags & NOT_SHALLOW) {
810 struct commit_list *parents;
Christian Couder329f9962020-06-11 14:05:08 +0200811 packet_writer_write(&data->writer, "unshallow %s",
Jonathan Tanbc2e7952019-01-15 11:40:27 -0800812 oid_to_hex(&object->oid));
Nguyễn Thái Ngọc Duye8e44de2016-06-12 17:53:45 +0700813 object->flags &= ~CLIENT_SHALLOW;
Nguyễn Thái Ngọc Duy873700c2016-06-12 17:53:48 +0700814 /*
815 * We want to _register_ "object" as shallow, but we
816 * also need to traverse object's parents to deepen a
817 * shallow clone. Unregister it for now so we can
818 * parse and add the parents to the want list, then
819 * re-register it.
820 */
brian m. carlsone92b8482017-05-06 22:10:06 +0000821 unregister_shallow(&object->oid);
Nguyễn Thái Ngọc Duye8e44de2016-06-12 17:53:45 +0700822 object->parsed = 0;
823 parse_commit_or_die((struct commit *)object);
824 parents = ((struct commit *)object)->parents;
825 while (parents) {
826 add_object_array(&parents->item->object,
Christian Couder329f9962020-06-11 14:05:08 +0200827 NULL, &data->want_obj);
Nguyễn Thái Ngọc Duye8e44de2016-06-12 17:53:45 +0700828 parents = parents->next;
829 }
Christian Couderde0e9f72020-06-11 14:05:10 +0200830 add_object_array(object, NULL, &data->extra_edge_obj);
Nguyễn Thái Ngọc Duye8e44de2016-06-12 17:53:45 +0700831 }
832 /* make sure commit traversal conforms to client */
Stefan Beller19143f12018-05-17 15:51:44 -0700833 register_shallow(the_repository, &object->oid);
Nguyễn Thái Ngọc Duye8e44de2016-06-12 17:53:45 +0700834 }
Nguyễn Thái Ngọc Duy873700c2016-06-12 17:53:48 +0700835}
836
Jonathan Tan5056cf42018-12-18 13:24:35 -0800837static int check_ref(const char *refname_full, const struct object_id *oid,
838 int flag, void *cb_data);
Christian Couderb1492f22020-06-11 14:05:06 +0200839static void deepen(struct upload_pack_data *data, int depth)
Nguyễn Thái Ngọc Duy873700c2016-06-12 17:53:48 +0700840{
Stefan Bellerc8813482018-05-17 15:51:46 -0700841 if (depth == INFINITE_DEPTH && !is_repository_shallow(the_repository)) {
Nguyễn Thái Ngọc Duy873700c2016-06-12 17:53:48 +0700842 int i;
843
Christian Couderb1492f22020-06-11 14:05:06 +0200844 for (i = 0; i < data->shallows.nr; i++) {
845 struct object *object = data->shallows.objects[i].item;
Nguyễn Thái Ngọc Duy873700c2016-06-12 17:53:48 +0700846 object->flags |= NOT_SHALLOW;
847 }
Christian Couderb1492f22020-06-11 14:05:06 +0200848 } else if (data->deepen_relative) {
Nguyễn Thái Ngọc Duycccf74e2016-06-12 17:54:09 +0700849 struct object_array reachable_shallows = OBJECT_ARRAY_INIT;
850 struct commit_list *result;
851
Jonathan Tan5056cf42018-12-18 13:24:35 -0800852 /*
853 * Checking for reachable shallows requires that our refs be
854 * marked with OUR_REF.
855 */
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +0100856 head_ref_namespaced(check_ref, data);
857 for_each_namespaced_ref(check_ref, data);
Jonathan Tan5056cf42018-12-18 13:24:35 -0800858
Christian Couderf1514c62020-06-11 14:05:11 +0200859 get_reachable_list(data, &reachable_shallows);
Nguyễn Thái Ngọc Duycccf74e2016-06-12 17:54:09 +0700860 result = get_shallow_commits(&reachable_shallows,
861 depth + 1,
862 SHALLOW, NOT_SHALLOW);
Christian Couder35b43a12020-06-11 14:05:09 +0200863 send_shallow(data, result);
Nguyễn Thái Ngọc Duycccf74e2016-06-12 17:54:09 +0700864 free_commit_list(result);
865 object_array_clear(&reachable_shallows);
Nguyễn Thái Ngọc Duy873700c2016-06-12 17:53:48 +0700866 } else {
867 struct commit_list *result;
868
Christian Couderb1492f22020-06-11 14:05:06 +0200869 result = get_shallow_commits(&data->want_obj, depth,
Nguyễn Thái Ngọc Duy873700c2016-06-12 17:53:48 +0700870 SHALLOW, NOT_SHALLOW);
Christian Couder35b43a12020-06-11 14:05:09 +0200871 send_shallow(data, result);
Nguyễn Thái Ngọc Duy873700c2016-06-12 17:53:48 +0700872 free_commit_list(result);
873 }
874
Christian Couder329f9962020-06-11 14:05:08 +0200875 send_unshallow(data);
Nguyễn Thái Ngọc Duye8e44de2016-06-12 17:53:45 +0700876}
877
Christian Couder446e42c2020-06-11 14:05:07 +0200878static void deepen_by_rev_list(struct upload_pack_data *data,
879 int ac,
880 const char **av)
Nguyễn Thái Ngọc Duy569e5542016-06-12 17:53:58 +0700881{
882 struct commit_list *result;
883
Jeff King6abada12019-09-12 10:44:45 -0400884 disable_commit_graph(the_repository);
Nguyễn Thái Ngọc Duy569e5542016-06-12 17:53:58 +0700885 result = get_shallow_commits_by_rev_list(ac, av, SHALLOW, NOT_SHALLOW);
Christian Couder35b43a12020-06-11 14:05:09 +0200886 send_shallow(data, result);
Nguyễn Thái Ngọc Duy569e5542016-06-12 17:53:58 +0700887 free_commit_list(result);
Christian Couder329f9962020-06-11 14:05:08 +0200888 send_unshallow(data);
Brandon Williams685fbd32018-03-15 10:31:28 -0700889}
890
891/* Returns 1 if a shallow list is sent or 0 otherwise */
Christian Couderee703c82020-06-11 14:05:05 +0200892static int send_shallow_list(struct upload_pack_data *data)
Brandon Williams685fbd32018-03-15 10:31:28 -0700893{
894 int ret = 0;
895
Christian Couderee703c82020-06-11 14:05:05 +0200896 if (data->depth > 0 && data->deepen_rev_list)
Brandon Williams685fbd32018-03-15 10:31:28 -0700897 die("git upload-pack: deepen and deepen-since (or deepen-not) cannot be used together");
Christian Couderee703c82020-06-11 14:05:05 +0200898 if (data->depth > 0) {
Christian Couderb1492f22020-06-11 14:05:06 +0200899 deepen(data, data->depth);
Brandon Williams685fbd32018-03-15 10:31:28 -0700900 ret = 1;
Christian Couderee703c82020-06-11 14:05:05 +0200901 } else if (data->deepen_rev_list) {
Jeff Kingc972bf42020-07-28 16:25:12 -0400902 struct strvec av = STRVEC_INIT;
Brandon Williams685fbd32018-03-15 10:31:28 -0700903 int i;
904
Jeff Kingc972bf42020-07-28 16:25:12 -0400905 strvec_push(&av, "rev-list");
Christian Couderee703c82020-06-11 14:05:05 +0200906 if (data->deepen_since)
Jeff Kingc972bf42020-07-28 16:25:12 -0400907 strvec_pushf(&av, "--max-age=%"PRItime, data->deepen_since);
Christian Couderee703c82020-06-11 14:05:05 +0200908 if (data->deepen_not.nr) {
Jeff Kingc972bf42020-07-28 16:25:12 -0400909 strvec_push(&av, "--not");
Christian Couderee703c82020-06-11 14:05:05 +0200910 for (i = 0; i < data->deepen_not.nr; i++) {
911 struct string_list_item *s = data->deepen_not.items + i;
Jeff Kingc972bf42020-07-28 16:25:12 -0400912 strvec_push(&av, s->string);
Brandon Williams685fbd32018-03-15 10:31:28 -0700913 }
Jeff Kingc972bf42020-07-28 16:25:12 -0400914 strvec_push(&av, "--not");
Brandon Williams685fbd32018-03-15 10:31:28 -0700915 }
Christian Couderee703c82020-06-11 14:05:05 +0200916 for (i = 0; i < data->want_obj.nr; i++) {
917 struct object *o = data->want_obj.objects[i].item;
Jeff Kingc972bf42020-07-28 16:25:12 -0400918 strvec_push(&av, oid_to_hex(&o->oid));
Brandon Williams685fbd32018-03-15 10:31:28 -0700919 }
Jeff Kingd70a9eb2020-07-28 20:37:20 -0400920 deepen_by_rev_list(data, av.nr, av.v);
Jeff Kingc972bf42020-07-28 16:25:12 -0400921 strvec_clear(&av);
Brandon Williams685fbd32018-03-15 10:31:28 -0700922 ret = 1;
923 } else {
Christian Couderee703c82020-06-11 14:05:05 +0200924 if (data->shallows.nr > 0) {
Brandon Williams685fbd32018-03-15 10:31:28 -0700925 int i;
Christian Couderee703c82020-06-11 14:05:05 +0200926 for (i = 0; i < data->shallows.nr; i++)
Junio C Hamano00624d62018-07-18 12:20:27 -0700927 register_shallow(the_repository,
Christian Couderee703c82020-06-11 14:05:05 +0200928 &data->shallows.objects[i].item->oid);
Brandon Williams685fbd32018-03-15 10:31:28 -0700929 }
930 }
931
Christian Couder35b43a12020-06-11 14:05:09 +0200932 data->shallow_nr += data->shallows.nr;
Brandon Williams685fbd32018-03-15 10:31:28 -0700933 return ret;
Nguyễn Thái Ngọc Duy569e5542016-06-12 17:53:58 +0700934}
935
Brandon Williamsae2948f2018-03-14 11:31:42 -0700936static int process_shallow(const char *line, struct object_array *shallows)
937{
938 const char *arg;
939 if (skip_prefix(line, "shallow ", &arg)) {
940 struct object_id oid;
941 struct object *object;
942 if (get_oid_hex(arg, &oid))
943 die("invalid shallow line: %s", line);
Stefan Beller109cd762018-06-28 18:21:51 -0700944 object = parse_object(the_repository, &oid);
Brandon Williamsae2948f2018-03-14 11:31:42 -0700945 if (!object)
946 return 1;
947 if (object->type != OBJ_COMMIT)
948 die("invalid shallow object %s", oid_to_hex(&oid));
949 if (!(object->flags & CLIENT_SHALLOW)) {
950 object->flags |= CLIENT_SHALLOW;
951 add_object_array(object, NULL, shallows);
952 }
953 return 1;
954 }
955
956 return 0;
957}
958
959static int process_deepen(const char *line, int *depth)
960{
961 const char *arg;
962 if (skip_prefix(line, "deepen ", &arg)) {
963 char *end = NULL;
964 *depth = (int)strtol(arg, &end, 0);
965 if (!end || *end || *depth <= 0)
966 die("Invalid deepen: %s", line);
967 return 1;
968 }
969
970 return 0;
971}
972
973static int process_deepen_since(const char *line, timestamp_t *deepen_since, int *deepen_rev_list)
974{
975 const char *arg;
976 if (skip_prefix(line, "deepen-since ", &arg)) {
977 char *end = NULL;
978 *deepen_since = parse_timestamp(arg, &end, 0);
979 if (!end || *end || !deepen_since ||
980 /* revisions.c's max_age -1 is special */
981 *deepen_since == -1)
982 die("Invalid deepen-since: %s", line);
983 *deepen_rev_list = 1;
984 return 1;
985 }
986 return 0;
987}
988
989static int process_deepen_not(const char *line, struct string_list *deepen_not, int *deepen_rev_list)
990{
991 const char *arg;
992 if (skip_prefix(line, "deepen-not ", &arg)) {
993 char *ref = NULL;
994 struct object_id oid;
Nguyễn Thái Ngọc Duy0b1dbf52019-04-06 18:34:27 +0700995 if (expand_ref(the_repository, arg, strlen(arg), &oid, &ref) != 1)
Brandon Williamsae2948f2018-03-14 11:31:42 -0700996 die("git upload-pack: ambiguous deepen-not: %s", line);
997 string_list_append(deepen_not, ref);
998 free(ref);
999 *deepen_rev_list = 1;
1000 return 1;
1001 }
1002 return 0;
Linus Torvaldsdef88e92005-07-04 13:26:53 -07001003}
1004
Taylor Blau6dd34562020-08-03 14:00:10 -04001005NORETURN __attribute__((format(printf,2,3)))
1006static void send_err_and_die(struct upload_pack_data *data,
1007 const char *fmt, ...)
1008{
1009 struct strbuf buf = STRBUF_INIT;
1010 va_list ap;
1011
1012 va_start(ap, fmt);
1013 strbuf_vaddf(&buf, fmt, ap);
1014 va_end(ap);
1015
1016 packet_writer_error(&data->writer, "%s", buf.buf);
1017 die("%s", buf.buf);
1018}
1019
1020static void check_one_filter(struct upload_pack_data *data,
1021 struct list_objects_filter_options *opts)
1022{
1023 const char *key = list_object_filter_config_name(opts->choice);
1024 struct string_list_item *item = string_list_lookup(&data->allowed_filters,
1025 key);
1026 int allowed;
1027
1028 if (item)
1029 allowed = (intptr_t)item->util;
1030 else
1031 allowed = data->allow_filter_fallback;
1032
1033 if (!allowed)
1034 send_err_and_die(data, "filter '%s' not supported", key);
Taylor Blau5b01a4e2020-08-03 14:00:17 -04001035
1036 if (opts->choice == LOFC_TREE_DEPTH &&
1037 opts->tree_exclude_depth > data->tree_filter_max_depth)
1038 send_err_and_die(data,
1039 "tree filter allows max depth %lu, but got %lu",
1040 data->tree_filter_max_depth,
1041 opts->tree_exclude_depth);
Taylor Blau6dd34562020-08-03 14:00:10 -04001042}
1043
1044static void check_filter_recurse(struct upload_pack_data *data,
1045 struct list_objects_filter_options *opts)
1046{
1047 size_t i;
1048
1049 check_one_filter(data, opts);
1050 if (opts->choice != LOFC_COMBINE)
1051 return;
1052
1053 for (i = 0; i < opts->sub_nr; i++)
1054 check_filter_recurse(data, &opts->sub[i]);
1055}
1056
1057static void die_if_using_banned_filter(struct upload_pack_data *data)
1058{
1059 check_filter_recurse(data, &data->filter_options);
1060}
1061
Christian Couderd92ae2c2020-05-15 12:04:47 +02001062static void receive_needs(struct upload_pack_data *data,
1063 struct packet_reader *reader)
Linus Torvaldsfb9040c2005-07-04 15:29:17 -07001064{
Junio C Hamano051e4002011-08-05 13:54:06 -07001065 int has_non_tip = 0;
Linus Torvaldsfb9040c2005-07-04 15:29:17 -07001066
Christian Couder35b43a12020-06-11 14:05:09 +02001067 data->shallow_nr = 0;
Linus Torvaldsfb9040c2005-07-04 15:29:17 -07001068 for (;;) {
Junio C Hamano565ebbf2005-10-24 18:59:18 -07001069 struct object *o;
Junio C Hamanof47182c2012-01-08 22:06:19 +01001070 const char *features;
brian m. carlsoncf939822017-05-06 22:10:28 +00001071 struct object_id oid_buf;
Nguyễn Thái Ngọc Duy8bf3b752016-06-12 17:53:49 +07001072 const char *arg;
Josh Steadmon82959462020-11-11 15:29:32 -08001073 int feature_len;
Nguyễn Thái Ngọc Duy8bf3b752016-06-12 17:53:49 +07001074
Christian Couderd40f04e2020-06-04 19:54:40 +02001075 reset_timeout(data->timeout);
Masaya Suzuki01f9ec62018-12-29 13:19:14 -08001076 if (packet_reader_read(reader) != PACKET_READ_NORMAL)
Johannes Schindelined09aef2006-10-30 20:09:06 +01001077 break;
Linus Torvaldsfb9040c2005-07-04 15:29:17 -07001078
Christian Couder7a516762020-05-15 12:04:54 +02001079 if (process_shallow(reader->line, &data->shallows))
Johannes Schindelined09aef2006-10-30 20:09:06 +01001080 continue;
Christian Couder7a516762020-05-15 12:04:54 +02001081 if (process_deepen(reader->line, &data->depth))
Johannes Schindelin016e6cc2006-10-30 20:09:29 +01001082 continue;
Christian Couder7a516762020-05-15 12:04:54 +02001083 if (process_deepen_since(reader->line, &data->deepen_since, &data->deepen_rev_list))
Nguyễn Thái Ngọc Duy569e5542016-06-12 17:53:58 +07001084 continue;
Christian Couder7a516762020-05-15 12:04:54 +02001085 if (process_deepen_not(reader->line, &data->deepen_not, &data->deepen_rev_list))
Nguyễn Thái Ngọc Duy269a7a82016-06-12 17:54:03 +07001086 continue;
Brandon Williamsae2948f2018-03-14 11:31:42 -07001087
Masaya Suzuki01f9ec62018-12-29 13:19:14 -08001088 if (skip_prefix(reader->line, "filter ", &arg)) {
Christian Couder59a90262020-06-04 19:54:42 +02001089 if (!data->filter_capability_requested)
Jeff Hostetler10ac85c2017-12-08 15:58:39 +00001090 die("git upload-pack: filtering capability not negotiated");
Christian Couderd92ae2c2020-05-15 12:04:47 +02001091 list_objects_filter_die_if_populated(&data->filter_options);
1092 parse_list_objects_filter(&data->filter_options, arg);
Taylor Blau6dd34562020-08-03 14:00:10 -04001093 die_if_using_banned_filter(data);
Jeff Hostetler10ac85c2017-12-08 15:58:39 +00001094 continue;
1095 }
Junio C Hamano9bfa0f92018-05-08 15:59:15 +09001096
Masaya Suzuki01f9ec62018-12-29 13:19:14 -08001097 if (!skip_prefix(reader->line, "want ", &arg) ||
brian m. carlson55dc2272018-05-02 00:25:51 +00001098 parse_oid_hex(arg, &oid_buf, &features))
Junio C Hamano7e44c932008-08-31 09:39:19 -07001099 die("git upload-pack: protocol error, "
Masaya Suzuki01f9ec62018-12-29 13:19:14 -08001100 "expected to get object ID, not '%s'", reader->line);
Junio C Hamanof47182c2012-01-08 22:06:19 +01001101
Nguyễn Thái Ngọc Duycccf74e2016-06-12 17:54:09 +07001102 if (parse_feature_request(features, "deepen-relative"))
Christian Couder7a516762020-05-15 12:04:54 +02001103 data->deepen_relative = 1;
Junio C Hamanof47182c2012-01-08 22:06:19 +01001104 if (parse_feature_request(features, "multi_ack_detailed"))
Christian Coudere9d882b2020-06-04 19:54:44 +02001105 data->multi_ack = MULTI_ACK_DETAILED;
Junio C Hamanof47182c2012-01-08 22:06:19 +01001106 else if (parse_feature_request(features, "multi_ack"))
Christian Coudere9d882b2020-06-04 19:54:44 +02001107 data->multi_ack = MULTI_ACK;
Junio C Hamanof47182c2012-01-08 22:06:19 +01001108 if (parse_feature_request(features, "no-done"))
Christian Couderd40f04e2020-06-04 19:54:40 +02001109 data->no_done = 1;
Junio C Hamanof47182c2012-01-08 22:06:19 +01001110 if (parse_feature_request(features, "thin-pack"))
Jeff Kingb5a20682020-06-04 19:54:38 +02001111 data->use_thin_pack = 1;
Junio C Hamanof47182c2012-01-08 22:06:19 +01001112 if (parse_feature_request(features, "ofs-delta"))
Jeff Kingb5a20682020-06-04 19:54:38 +02001113 data->use_ofs_delta = 1;
Junio C Hamanof47182c2012-01-08 22:06:19 +01001114 if (parse_feature_request(features, "side-band-64k"))
Christian Couderf8edd1c2020-06-04 19:54:41 +02001115 data->use_sideband = LARGE_PACKET_MAX;
Junio C Hamanof47182c2012-01-08 22:06:19 +01001116 else if (parse_feature_request(features, "side-band"))
Christian Couderf8edd1c2020-06-04 19:54:41 +02001117 data->use_sideband = DEFAULT_PACKET_MAX;
Junio C Hamanof47182c2012-01-08 22:06:19 +01001118 if (parse_feature_request(features, "no-progress"))
Jeff Kingb5a20682020-06-04 19:54:38 +02001119 data->no_progress = 1;
Junio C Hamanof47182c2012-01-08 22:06:19 +01001120 if (parse_feature_request(features, "include-tag"))
Jeff Kingb5a20682020-06-04 19:54:38 +02001121 data->use_include_tag = 1;
Christian Couder59abe192020-06-04 19:54:47 +02001122 if (data->allow_filter &&
1123 parse_feature_request(features, "filter"))
Christian Couder59a90262020-06-04 19:54:42 +02001124 data->filter_capability_requested = 1;
Junio C Hamano565ebbf2005-10-24 18:59:18 -07001125
Josh Steadmon82959462020-11-11 15:29:32 -08001126 arg = parse_feature_value(features, "session-id", &feature_len, NULL);
1127 if (arg) {
1128 char *client_sid = xstrndup(arg, feature_len);
1129 trace2_data_string("transfer", NULL, "client-sid", client_sid);
1130 free(client_sid);
1131 }
1132
Stefan Beller109cd762018-06-28 18:21:51 -07001133 o = parse_object(the_repository, &oid_buf);
Jonathan Tanbdb31ea2017-02-23 10:43:03 -08001134 if (!o) {
Christian Couder4ace0282020-05-15 12:04:48 +02001135 packet_writer_error(&data->writer,
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001136 "upload-pack: not our ref %s",
1137 oid_to_hex(&oid_buf));
Elijah Newren9f9aa762010-07-31 14:11:46 -06001138 die("git upload-pack: not our ref %s",
brian m. carlsoncf939822017-05-06 22:10:28 +00001139 oid_to_hex(&oid_buf));
Jonathan Tanbdb31ea2017-02-23 10:43:03 -08001140 }
Junio C Hamano565ebbf2005-10-24 18:59:18 -07001141 if (!(o->flags & WANTED)) {
1142 o->flags |= WANTED;
Christian Couder629060d2020-06-11 14:05:12 +02001143 if (!((data->allow_uor & ALLOW_ANY_SHA1) == ALLOW_ANY_SHA1
1144 || is_our_ref(o, data->allow_uor)))
Junio C Hamano051e4002011-08-05 13:54:06 -07001145 has_non_tip = 1;
Christian Couderd92ae2c2020-05-15 12:04:47 +02001146 add_object_array(o, NULL, &data->want_obj);
Junio C Hamano565ebbf2005-10-24 18:59:18 -07001147 }
Linus Torvaldsfb9040c2005-07-04 15:29:17 -07001148 }
Johannes Sixt9462e3f2009-06-16 20:41:16 +02001149
Junio C Hamano051e4002011-08-05 13:54:06 -07001150 /*
1151 * We have sent all our refs already, and the other end
1152 * should have chosen out of them. When we are operating
1153 * in the stateless RPC mode, however, their choice may
1154 * have been based on the set of older refs advertised
1155 * by another process that handled the initial request.
1156 */
1157 if (has_non_tip)
Christian Couderb08c9742020-05-15 12:04:51 +02001158 check_non_tip(data);
Junio C Hamano051e4002011-08-05 13:54:06 -07001159
Christian Couderf8edd1c2020-06-04 19:54:41 +02001160 if (!data->use_sideband && data->daemon_mode)
Jeff Kingb5a20682020-06-04 19:54:38 +02001161 data->no_progress = 1;
Johannes Sixt9462e3f2009-06-16 20:41:16 +02001162
Christian Couder7a516762020-05-15 12:04:54 +02001163 if (data->depth == 0 && !data->deepen_rev_list && data->shallows.nr == 0)
Johannes Schindelinf53514b2006-10-30 20:09:53 +01001164 return;
Nguyễn Thái Ngọc Duy569e5542016-06-12 17:53:58 +07001165
Christian Couderee703c82020-06-11 14:05:05 +02001166 if (send_shallow_list(data))
Brandon Williams685fbd32018-03-15 10:31:28 -07001167 packet_flush(1);
Linus Torvaldsfb9040c2005-07-04 15:29:17 -07001168}
1169
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001170/* return non-zero if the ref is hidden, otherwise 0 */
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001171static int mark_our_ref(const char *refname, const char *refname_full,
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001172 const struct object_id *oid, const struct string_list *hidden_refs)
Junio C Hamanocbbe50d2013-01-18 15:48:49 -08001173{
Jeff King45a187c2021-04-13 03:16:36 -04001174 struct object *o = lookup_unknown_object(the_repository, oid);
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001175
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001176 if (ref_is_hidden(refname, refname_full, hidden_refs)) {
Junio C Hamano390eb362013-01-28 21:49:57 -08001177 o->flags |= HIDDEN_REF;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001178 return 1;
Junio C Hamano390eb362013-01-28 21:49:57 -08001179 }
Junio C Hamano3f1da572013-01-28 20:45:43 -08001180 o->flags |= OUR_REF;
Junio C Hamanocbbe50d2013-01-18 15:48:49 -08001181 return 0;
1182}
1183
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001184static int check_ref(const char *refname_full, const struct object_id *oid,
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001185 int flag UNUSED, void *cb_data)
Jeff Kinge1727552015-03-13 00:42:12 -04001186{
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001187 const char *refname = strip_namespace(refname_full);
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001188 struct upload_pack_data *data = cb_data;
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001189
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001190 mark_our_ref(refname, refname_full, oid, &data->hidden_refs);
Jeff Kinge1727552015-03-13 00:42:12 -04001191 return 0;
1192}
1193
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001194static void format_symref_info(struct strbuf *buf, struct string_list *symref)
1195{
1196 struct string_list_item *item;
1197
1198 if (!symref->nr)
1199 return;
1200 for_each_string_list_item(item, symref)
1201 strbuf_addf(buf, " symref=%s:%s", item->string, (char *)item->util);
1202}
1203
Josh Steadmon791e1ad2020-11-11 15:29:27 -08001204static void format_session_id(struct strbuf *buf, struct upload_pack_data *d) {
1205 if (d->advertise_sid)
1206 strbuf_addf(buf, " session-id=%s", trace2_session_id());
1207}
1208
Michael Haggerty363e98b2015-05-25 18:39:12 +00001209static int send_ref(const char *refname, const struct object_id *oid,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02001210 int flag UNUSED, void *cb_data)
Linus Torvaldsdef88e92005-07-04 13:26:53 -07001211{
Johannes Schindelined09aef2006-10-30 20:09:06 +01001212 static const char *capabilities = "multi_ack thin-pack side-band"
Nguyễn Thái Ngọc Duycccf74e2016-06-12 17:54:09 +07001213 " side-band-64k ofs-delta shallow deepen-since deepen-not"
1214 " deepen-relative no-progress include-tag multi_ack_detailed";
Josh Triplett6b01ecf2011-07-08 16:13:32 -07001215 const char *refname_nons = strip_namespace(refname);
Michael Haggerty21758af2015-05-25 18:39:13 +00001216 struct object_id peeled;
Christian Couder762f9272020-05-15 12:04:50 +02001217 struct upload_pack_data *data = cb_data;
Carl Worthb5b16992006-02-17 16:14:52 -08001218
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001219 if (mark_our_ref(refname_nons, refname, oid, &data->hidden_refs))
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001220 return 0;
Junio C Hamanocbbe50d2013-01-18 15:48:49 -08001221
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001222 if (capabilities) {
1223 struct strbuf symref_info = STRBUF_INIT;
Josh Steadmon791e1ad2020-11-11 15:29:27 -08001224 struct strbuf session_id = STRBUF_INIT;
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001225
Christian Couder762f9272020-05-15 12:04:50 +02001226 format_symref_info(&symref_info, &data->symref);
Josh Steadmon791e1ad2020-11-11 15:29:27 -08001227 format_session_id(&session_id, data);
Jacob Vosmaer70afef52021-09-01 14:54:42 +02001228 packet_fwrite_fmt(stdout, "%s %s%c%s%s%s%s%s%s%s object-format=%s agent=%s\n",
Michael Haggerty363e98b2015-05-25 18:39:12 +00001229 oid_to_hex(oid), refname_nons,
Junio C Hamanocf2ad8e2011-03-29 10:24:59 -07001230 0, capabilities,
Christian Couder629060d2020-06-11 14:05:12 +02001231 (data->allow_uor & ALLOW_TIP_SHA1) ?
Fredrik Medley7199c092015-05-21 22:23:38 +02001232 " allow-tip-sha1-in-want" : "",
Christian Couder629060d2020-06-11 14:05:12 +02001233 (data->allow_uor & ALLOW_REACHABLE_SHA1) ?
Fredrik Medley68ee6282015-05-21 22:23:39 +02001234 " allow-reachable-sha1-in-want" : "",
Ævar Arnfjörð Bjarmasonf234da82021-08-05 03:25:42 +02001235 data->no_done ? " no-done" : "",
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001236 symref_info.buf,
Christian Couder59abe192020-06-04 19:54:47 +02001237 data->allow_filter ? " filter" : "",
Josh Steadmon791e1ad2020-11-11 15:29:27 -08001238 session_id.buf,
brian m. carlsonbf30dbf2020-05-25 19:58:51 +00001239 the_hash_algo->name,
Jeff Kingff5effd2012-08-03 12:19:16 -04001240 git_user_agent_sanitized());
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001241 strbuf_release(&symref_info);
Josh Steadmon791e1ad2020-11-11 15:29:27 -08001242 strbuf_release(&session_id);
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001243 } else {
Jacob Vosmaer70afef52021-09-01 14:54:42 +02001244 packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons);
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001245 }
Johannes Schindelin1f5881b2005-10-28 05:56:41 +02001246 capabilities = NULL;
Jeff King36a31792021-01-20 14:44:43 -05001247 if (!peel_iterated_oid(oid, &peeled))
Jacob Vosmaer70afef52021-09-01 14:54:42 +02001248 packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
Linus Torvaldsdef88e92005-07-04 13:26:53 -07001249 return 0;
1250}
1251
Jeff King63e14ee2022-08-19 06:08:32 -04001252static int find_symref(const char *refname,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02001253 const struct object_id *oid UNUSED,
Michael Haggerty7dabd052015-05-25 18:39:10 +00001254 int flag, void *cb_data)
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001255{
1256 const char *symref_target;
1257 struct string_list_item *item;
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001258
1259 if ((flag & REF_ISSYMREF) == 0)
1260 return 0;
René Scharfe744c0402017-09-23 11:45:04 +02001261 symref_target = resolve_ref_unsafe(refname, 0, NULL, &flag);
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001262 if (!symref_target || (flag & REF_ISSYMREF) == 0)
1263 die("'%s' is a symref but it is not?", refname);
Jeff King533e0882019-05-23 02:11:21 -04001264 item = string_list_append(cb_data, strip_namespace(refname));
1265 item->util = xstrdup(strip_namespace(symref_target));
Junio C Hamano7171d8c2013-09-17 16:17:33 -07001266 return 0;
1267}
1268
Taylor Blau6dd34562020-08-03 14:00:10 -04001269static int parse_object_filter_config(const char *var, const char *value,
1270 struct upload_pack_data *data)
1271{
1272 struct strbuf buf = STRBUF_INIT;
1273 const char *sub, *key;
1274 size_t sub_len;
1275
1276 if (parse_config_key(var, "uploadpackfilter", &sub, &sub_len, &key))
1277 return 0;
1278
1279 if (!sub) {
1280 if (!strcmp(key, "allow"))
1281 data->allow_filter_fallback = git_config_bool(var, value);
1282 return 0;
1283 }
1284
1285 strbuf_add(&buf, sub, sub_len);
1286
1287 if (!strcmp(key, "allow"))
1288 string_list_insert(&data->allowed_filters, buf.buf)->util =
1289 (void *)(intptr_t)git_config_bool(var, value);
Taylor Blau5b01a4e2020-08-03 14:00:17 -04001290 else if (!strcmp(buf.buf, "tree") && !strcmp(key, "maxdepth")) {
1291 if (!value) {
1292 strbuf_release(&buf);
1293 return config_error_nonbool(var);
1294 }
1295 string_list_insert(&data->allowed_filters, buf.buf)->util =
1296 (void *)(intptr_t)1;
1297 data->tree_filter_max_depth = git_config_ulong(var, value);
1298 }
Taylor Blau6dd34562020-08-03 14:00:10 -04001299
1300 strbuf_release(&buf);
1301 return 0;
1302}
1303
Christian Couder8a0e6f12020-06-04 19:54:45 +02001304static int upload_pack_config(const char *var, const char *value, void *cb_data)
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001305{
Christian Couderf203a882020-06-04 19:54:46 +02001306 struct upload_pack_data *data = cb_data;
1307
Fredrik Medley7199c092015-05-21 22:23:38 +02001308 if (!strcmp("uploadpack.allowtipsha1inwant", var)) {
1309 if (git_config_bool(var, value))
Christian Couder629060d2020-06-11 14:05:12 +02001310 data->allow_uor |= ALLOW_TIP_SHA1;
Fredrik Medley7199c092015-05-21 22:23:38 +02001311 else
Christian Couder629060d2020-06-11 14:05:12 +02001312 data->allow_uor &= ~ALLOW_TIP_SHA1;
Fredrik Medley68ee6282015-05-21 22:23:39 +02001313 } else if (!strcmp("uploadpack.allowreachablesha1inwant", var)) {
1314 if (git_config_bool(var, value))
Christian Couder629060d2020-06-11 14:05:12 +02001315 data->allow_uor |= ALLOW_REACHABLE_SHA1;
Fredrik Medley68ee6282015-05-21 22:23:39 +02001316 else
Christian Couder629060d2020-06-11 14:05:12 +02001317 data->allow_uor &= ~ALLOW_REACHABLE_SHA1;
David Turnerf8edeaa2016-11-11 12:23:48 -05001318 } else if (!strcmp("uploadpack.allowanysha1inwant", var)) {
1319 if (git_config_bool(var, value))
Christian Couder629060d2020-06-11 14:05:12 +02001320 data->allow_uor |= ALLOW_ANY_SHA1;
David Turnerf8edeaa2016-11-11 12:23:48 -05001321 else
Christian Couder629060d2020-06-11 14:05:12 +02001322 data->allow_uor &= ~ALLOW_ANY_SHA1;
Fredrik Medley7199c092015-05-21 22:23:38 +02001323 } else if (!strcmp("uploadpack.keepalive", var)) {
Christian Couderf203a882020-06-04 19:54:46 +02001324 data->keepalive = git_config_int(var, value);
1325 if (!data->keepalive)
1326 data->keepalive = -1;
Jeff Hostetler10ac85c2017-12-08 15:58:39 +00001327 } else if (!strcmp("uploadpack.allowfilter", var)) {
Christian Couder59abe192020-06-04 19:54:47 +02001328 data->allow_filter = git_config_bool(var, value);
Brandon Williams516e2b72018-06-27 15:30:17 -07001329 } else if (!strcmp("uploadpack.allowrefinwant", var)) {
Christian Couderd1d7a942020-06-04 19:54:48 +02001330 data->allow_ref_in_want = git_config_bool(var, value);
Jonathan Tan0bbc0bc2019-01-16 11:28:14 -08001331 } else if (!strcmp("uploadpack.allowsidebandall", var)) {
Christian Coudere3835cd2020-06-04 19:54:49 +02001332 data->allow_sideband_all = git_config_bool(var, value);
Elijah Newren8e712ef2019-04-25 07:58:54 -07001333 } else if (!strcmp("core.precomposeunicode", var)) {
1334 precomposed_unicode = git_config_bool(var, value);
Josh Steadmon791e1ad2020-11-11 15:29:27 -08001335 } else if (!strcmp("transfer.advertisesid", var)) {
1336 data->advertise_sid = git_config_bool(var, value);
Jeff King05e95152013-09-08 05:01:31 -04001337 }
Jeff Kingaaaa8812018-10-24 03:27:52 -04001338
Jeff Kingd43a21b2020-12-03 03:09:42 -05001339 if (parse_object_filter_config(var, value, data) < 0)
1340 return -1;
Taylor Blau6dd34562020-08-03 14:00:10 -04001341
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001342 return parse_hide_refs_config(var, value, "uploadpack", &data->hidden_refs);
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001343}
1344
Glen Choo5b3c6502022-07-14 21:27:59 +00001345static int upload_pack_protected_config(const char *var, const char *value, void *cb_data)
1346{
1347 struct upload_pack_data *data = cb_data;
1348
1349 if (!strcmp("uploadpack.packobjectshook", var))
1350 return git_config_string(&data->pack_objects_hook, var, value);
1351 return 0;
1352}
1353
1354static void get_upload_pack_config(struct upload_pack_data *data)
1355{
1356 git_config(upload_pack_config, data);
1357 git_protected_config(upload_pack_protected_config, data);
1358}
1359
Ævar Arnfjörð Bjarmasonf234da82021-08-05 03:25:42 +02001360void upload_pack(const int advertise_refs, const int stateless_rpc,
1361 const int timeout)
Linus Torvaldsdef88e92005-07-04 13:26:53 -07001362{
Masaya Suzuki01f9ec62018-12-29 13:19:14 -08001363 struct packet_reader reader;
Christian Couderebf8ebc2020-05-15 12:04:45 +02001364 struct upload_pack_data data;
H. Peter Anvin960decc2005-10-19 14:27:01 -07001365
Christian Couderebf8ebc2020-05-15 12:04:45 +02001366 upload_pack_data_init(&data);
Glen Choo5b3c6502022-07-14 21:27:59 +00001367 get_upload_pack_config(&data);
Christian Couder8a0e6f12020-06-04 19:54:45 +02001368
Ævar Arnfjörð Bjarmasonf234da82021-08-05 03:25:42 +02001369 data.stateless_rpc = stateless_rpc;
1370 data.timeout = timeout;
1371 if (data.timeout)
1372 data.daemon_mode = 1;
Christian Couderdf654ab2020-05-15 12:04:52 +02001373
Christian Couder438528f2020-05-15 12:04:49 +02001374 head_ref_namespaced(find_symref, &data.symref);
Brandon Williamsaa9bab22017-10-16 10:55:26 -07001375
Ævar Arnfjörð Bjarmasonf234da82021-08-05 03:25:42 +02001376 if (advertise_refs || !data.stateless_rpc) {
Christian Couderd40f04e2020-06-04 19:54:40 +02001377 reset_timeout(data.timeout);
Ævar Arnfjörð Bjarmasonf234da82021-08-05 03:25:42 +02001378 if (advertise_refs)
1379 data.no_done = 1;
Christian Couder762f9272020-05-15 12:04:50 +02001380 head_ref_namespaced(send_ref, &data);
1381 for_each_namespaced_ref(send_ref, &data);
Jacob Vosmaer70afef52021-09-01 14:54:42 +02001382 /*
1383 * fflush stdout before calling advertise_shallow_grafts because send_ref
1384 * uses stdio.
1385 */
1386 fflush_or_die(stdout);
Brandon Williamsa3d6b532018-03-14 11:31:41 -07001387 advertise_shallow_grafts(1);
1388 packet_flush(1);
1389 } else {
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001390 head_ref_namespaced(check_ref, &data);
1391 for_each_namespaced_ref(check_ref, &data);
Brandon Williamsaa9bab22017-10-16 10:55:26 -07001392 }
1393
Ævar Arnfjörð Bjarmasonf234da82021-08-05 03:25:42 +02001394 if (!advertise_refs) {
Christian Couderebf8ebc2020-05-15 12:04:45 +02001395 packet_reader_init(&reader, 0, NULL, 0,
1396 PACKET_READ_CHOMP_NEWLINE |
1397 PACKET_READ_DIE_ON_ERR_PACKET);
Masaya Suzuki01f9ec62018-12-29 13:19:14 -08001398
Christian Couderd92ae2c2020-05-15 12:04:47 +02001399 receive_needs(&data, &reader);
Daniel Duvallfb3d1a02020-10-30 19:39:02 -07001400
1401 /*
1402 * An EOF at this exact point in negotiation should be
1403 * acceptable from stateless clients as they will consume the
1404 * shallow list before doing subsequent rpc with haves/etc.
1405 */
1406 if (data.stateless_rpc)
1407 reader.options |= PACKET_READ_GENTLE_ON_EOF;
1408
1409 if (data.want_obj.nr &&
1410 packet_reader_peek(&reader) != PACKET_READ_EOF) {
1411 reader.options &= ~PACKET_READ_GENTLE_ON_EOF;
Christian Couder07977692020-05-15 12:04:46 +02001412 get_common_commits(&data, &reader);
Ramsay Jonescae2ee12020-06-16 00:00:20 +01001413 create_pack_file(&data, NULL);
Christian Couderebf8ebc2020-05-15 12:04:45 +02001414 }
Brandon Williamsa3d6b532018-03-14 11:31:41 -07001415 }
Christian Couder08450ef2020-05-08 10:01:15 +02001416
Christian Couderebf8ebc2020-05-15 12:04:45 +02001417 upload_pack_data_clear(&data);
Linus Torvaldsdef88e92005-07-04 13:26:53 -07001418}
Brandon Williams3145ea92018-03-15 10:31:27 -07001419
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001420static int parse_want(struct packet_writer *writer, const char *line,
1421 struct object_array *want_obj)
Brandon Williams3145ea92018-03-15 10:31:27 -07001422{
1423 const char *arg;
1424 if (skip_prefix(line, "want ", &arg)) {
1425 struct object_id oid;
1426 struct object *o;
1427
1428 if (get_oid_hex(arg, &oid))
1429 die("git upload-pack: protocol error, "
1430 "expected to get oid, not '%s'", line);
1431
Jeff King9a8c3c42022-09-06 19:06:25 -04001432 o = parse_object_with_flags(the_repository, &oid,
1433 PARSE_OBJECT_SKIP_HASH_CHECK);
Patrick Steinhardt4de65622022-03-01 10:33:37 +01001434
Brandon Williams3145ea92018-03-15 10:31:27 -07001435 if (!o) {
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001436 packet_writer_error(writer,
1437 "upload-pack: not our ref %s",
1438 oid_to_hex(&oid));
Brandon Williams3145ea92018-03-15 10:31:27 -07001439 die("git upload-pack: not our ref %s",
1440 oid_to_hex(&oid));
1441 }
1442
1443 if (!(o->flags & WANTED)) {
1444 o->flags |= WANTED;
Jonathan Tan1d1243f2018-10-18 13:43:28 -07001445 add_object_array(o, NULL, want_obj);
Brandon Williams3145ea92018-03-15 10:31:27 -07001446 }
1447
1448 return 1;
Linus Torvaldsdef88e92005-07-04 13:26:53 -07001449 }
1450
1451 return 0;
1452}
Brandon Williams3145ea92018-03-15 10:31:27 -07001453
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001454static int parse_want_ref(struct packet_writer *writer, const char *line,
1455 struct string_list *wanted_refs,
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001456 struct string_list *hidden_refs,
Jonathan Tan1d1243f2018-10-18 13:43:28 -07001457 struct object_array *want_obj)
Brandon Williams516e2b72018-06-27 15:30:17 -07001458{
Kim Altintop39551402021-08-13 06:23:50 +00001459 const char *refname_nons;
1460 if (skip_prefix(line, "want-ref ", &refname_nons)) {
Brandon Williams516e2b72018-06-27 15:30:17 -07001461 struct object_id oid;
1462 struct string_list_item *item;
Patrick Steinhardt4de65622022-03-01 10:33:37 +01001463 struct object *o = NULL;
Kim Altintop39551402021-08-13 06:23:50 +00001464 struct strbuf refname = STRBUF_INIT;
Brandon Williams516e2b72018-06-27 15:30:17 -07001465
Kim Altintop39551402021-08-13 06:23:50 +00001466 strbuf_addf(&refname, "%s%s", get_git_namespace(), refname_nons);
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001467 if (ref_is_hidden(refname_nons, refname.buf, hidden_refs) ||
Kim Altintop39551402021-08-13 06:23:50 +00001468 read_ref(refname.buf, &oid)) {
1469 packet_writer_error(writer, "unknown ref %s", refname_nons);
1470 die("unknown ref %s", refname_nons);
Brandon Williams516e2b72018-06-27 15:30:17 -07001471 }
Kim Altintop39551402021-08-13 06:23:50 +00001472 strbuf_release(&refname);
Brandon Williams516e2b72018-06-27 15:30:17 -07001473
Kim Altintop39551402021-08-13 06:23:50 +00001474 item = string_list_append(wanted_refs, refname_nons);
Brandon Williams516e2b72018-06-27 15:30:17 -07001475 item->util = oiddup(&oid);
1476
Patrick Steinhardt4de65622022-03-01 10:33:37 +01001477 if (!starts_with(refname_nons, "refs/tags/")) {
1478 struct commit *commit = lookup_commit_in_graph(the_repository, &oid);
1479 if (commit)
1480 o = &commit->object;
1481 }
1482
1483 if (!o)
1484 o = parse_object_or_die(&oid, refname_nons);
1485
Brandon Williams516e2b72018-06-27 15:30:17 -07001486 if (!(o->flags & WANTED)) {
1487 o->flags |= WANTED;
Jonathan Tan1d1243f2018-10-18 13:43:28 -07001488 add_object_array(o, NULL, want_obj);
Brandon Williams516e2b72018-06-27 15:30:17 -07001489 }
1490
1491 return 1;
1492 }
1493
1494 return 0;
1495}
1496
Brandon Williams3145ea92018-03-15 10:31:27 -07001497static int parse_have(const char *line, struct oid_array *haves)
1498{
1499 const char *arg;
1500 if (skip_prefix(line, "have ", &arg)) {
1501 struct object_id oid;
1502
1503 if (get_oid_hex(arg, &oid))
1504 die("git upload-pack: expected SHA1 object, got '%s'", arg);
1505 oid_array_append(haves, &oid);
1506 return 1;
1507 }
1508
1509 return 0;
1510}
1511
1512static void process_args(struct packet_reader *request,
Christian Couder389f1612020-05-15 12:04:43 +02001513 struct upload_pack_data *data)
Brandon Williams3145ea92018-03-15 10:31:27 -07001514{
Jeff King4845b772020-03-27 04:03:38 -04001515 while (packet_reader_read(request) == PACKET_READ_NORMAL) {
Brandon Williams3145ea92018-03-15 10:31:27 -07001516 const char *arg = request->line;
Jonathan Tanba957102018-05-03 16:46:56 -07001517 const char *p;
Brandon Williams3145ea92018-03-15 10:31:27 -07001518
1519 /* process want */
Christian Couder389f1612020-05-15 12:04:43 +02001520 if (parse_want(&data->writer, arg, &data->want_obj))
Brandon Williams3145ea92018-03-15 10:31:27 -07001521 continue;
Christian Couderd1d7a942020-06-04 19:54:48 +02001522 if (data->allow_ref_in_want &&
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001523 parse_want_ref(&data->writer, arg, &data->wanted_refs,
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001524 &data->hidden_refs, &data->want_obj))
Brandon Williams516e2b72018-06-27 15:30:17 -07001525 continue;
Brandon Williams3145ea92018-03-15 10:31:27 -07001526 /* process have line */
1527 if (parse_have(arg, &data->haves))
1528 continue;
1529
1530 /* process args like thin-pack */
1531 if (!strcmp(arg, "thin-pack")) {
Jeff Kingb5a20682020-06-04 19:54:38 +02001532 data->use_thin_pack = 1;
Brandon Williams3145ea92018-03-15 10:31:27 -07001533 continue;
1534 }
1535 if (!strcmp(arg, "ofs-delta")) {
Jeff Kingb5a20682020-06-04 19:54:38 +02001536 data->use_ofs_delta = 1;
Brandon Williams3145ea92018-03-15 10:31:27 -07001537 continue;
1538 }
1539 if (!strcmp(arg, "no-progress")) {
Jeff Kingb5a20682020-06-04 19:54:38 +02001540 data->no_progress = 1;
Brandon Williams3145ea92018-03-15 10:31:27 -07001541 continue;
1542 }
1543 if (!strcmp(arg, "include-tag")) {
Jeff Kingb5a20682020-06-04 19:54:38 +02001544 data->use_include_tag = 1;
Brandon Williams3145ea92018-03-15 10:31:27 -07001545 continue;
1546 }
1547 if (!strcmp(arg, "done")) {
1548 data->done = 1;
1549 continue;
1550 }
Jonathan Tan9c1e6572021-05-04 14:16:01 -07001551 if (!strcmp(arg, "wait-for-done")) {
1552 data->wait_for_done = 1;
1553 continue;
1554 }
Brandon Williams3145ea92018-03-15 10:31:27 -07001555
Brandon Williams685fbd32018-03-15 10:31:28 -07001556 /* Shallow related arguments */
1557 if (process_shallow(arg, &data->shallows))
1558 continue;
1559 if (process_deepen(arg, &data->depth))
1560 continue;
1561 if (process_deepen_since(arg, &data->deepen_since,
1562 &data->deepen_rev_list))
1563 continue;
1564 if (process_deepen_not(arg, &data->deepen_not,
1565 &data->deepen_rev_list))
1566 continue;
1567 if (!strcmp(arg, "deepen-relative")) {
1568 data->deepen_relative = 1;
1569 continue;
1570 }
1571
Christian Couder59abe192020-06-04 19:54:47 +02001572 if (data->allow_filter && skip_prefix(arg, "filter ", &p)) {
Christian Couder08450ef2020-05-08 10:01:15 +02001573 list_objects_filter_die_if_populated(&data->filter_options);
1574 parse_list_objects_filter(&data->filter_options, p);
Taylor Blau6dd34562020-08-03 14:00:10 -04001575 die_if_using_banned_filter(data);
Jonathan Tanba957102018-05-03 16:46:56 -07001576 continue;
1577 }
1578
Jonathan Tan07c3c2a2019-01-16 11:28:15 -08001579 if ((git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) ||
Christian Coudere3835cd2020-06-04 19:54:49 +02001580 data->allow_sideband_all) &&
Jonathan Tan07c3c2a2019-01-16 11:28:15 -08001581 !strcmp(arg, "sideband-all")) {
Jonathan Tan0bbc0bc2019-01-16 11:28:14 -08001582 data->writer.use_sideband = 1;
1583 continue;
1584 }
1585
Jonathan Tandd4b7322020-06-10 13:57:23 -07001586 if (skip_prefix(arg, "packfile-uris ", &p)) {
1587 string_list_split(&data->uri_protocols, p, ',', -1);
1588 continue;
1589 }
1590
Brandon Williams3145ea92018-03-15 10:31:27 -07001591 /* ignore unknown lines maybe? */
Jonathan Tan7cc6ed22018-05-01 17:31:29 -07001592 die("unexpected line: '%s'", arg);
Brandon Williams3145ea92018-03-15 10:31:27 -07001593 }
Jeff King4845b772020-03-27 04:03:38 -04001594
Jonathan Tandd4b7322020-06-10 13:57:23 -07001595 if (data->uri_protocols.nr && !data->writer.use_sideband)
1596 string_list_clear(&data->uri_protocols, 0);
1597
Jeff King4845b772020-03-27 04:03:38 -04001598 if (request->status != PACKET_READ_FLUSH)
1599 die(_("expected flush after fetch arguments"));
Brandon Williams3145ea92018-03-15 10:31:27 -07001600}
1601
Christian Couder8dcf2272020-06-11 14:05:13 +02001602static int process_haves(struct upload_pack_data *data, struct oid_array *common)
Brandon Williams3145ea92018-03-15 10:31:27 -07001603{
1604 int i;
1605
1606 /* Process haves */
Christian Couder8dcf2272020-06-11 14:05:13 +02001607 for (i = 0; i < data->haves.nr; i++) {
1608 const struct object_id *oid = &data->haves.oid[i];
Brandon Williams3145ea92018-03-15 10:31:27 -07001609
Ævar Arnfjörð Bjarmasonbc726bd2023-03-28 15:58:50 +02001610 if (!repo_has_object_file_with_flags(the_repository, oid,
1611 OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT))
Brandon Williams3145ea92018-03-15 10:31:27 -07001612 continue;
1613
1614 oid_array_append(common, oid);
1615
Christian Couderea2c6e62020-06-11 14:05:18 +02001616 do_got_oid(data, oid);
Brandon Williams3145ea92018-03-15 10:31:27 -07001617 }
1618
1619 return 0;
1620}
1621
Christian Couder6fbbc432020-06-11 14:05:14 +02001622static int send_acks(struct upload_pack_data *data, struct oid_array *acks)
Brandon Williams3145ea92018-03-15 10:31:27 -07001623{
1624 int i;
1625
Christian Couder6fbbc432020-06-11 14:05:14 +02001626 packet_writer_write(&data->writer, "acknowledgments\n");
Brandon Williams3145ea92018-03-15 10:31:27 -07001627
1628 /* Send Acks */
1629 if (!acks->nr)
Christian Couder6fbbc432020-06-11 14:05:14 +02001630 packet_writer_write(&data->writer, "NAK\n");
Brandon Williams3145ea92018-03-15 10:31:27 -07001631
1632 for (i = 0; i < acks->nr; i++) {
Christian Couder6fbbc432020-06-11 14:05:14 +02001633 packet_writer_write(&data->writer, "ACK %s\n",
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001634 oid_to_hex(&acks->oid[i]));
Brandon Williams3145ea92018-03-15 10:31:27 -07001635 }
1636
Jonathan Tan9c1e6572021-05-04 14:16:01 -07001637 if (!data->wait_for_done && ok_to_give_up(data)) {
Brandon Williams3145ea92018-03-15 10:31:27 -07001638 /* Send Ready */
Christian Couder6fbbc432020-06-11 14:05:14 +02001639 packet_writer_write(&data->writer, "ready\n");
Brandon Williams3145ea92018-03-15 10:31:27 -07001640 return 1;
1641 }
1642
1643 return 0;
1644}
1645
Christian Couder389f1612020-05-15 12:04:43 +02001646static int process_haves_and_send_acks(struct upload_pack_data *data)
Brandon Williams3145ea92018-03-15 10:31:27 -07001647{
1648 struct oid_array common = OID_ARRAY_INIT;
Brandon Williams3145ea92018-03-15 10:31:27 -07001649 int ret = 0;
1650
Christian Couder8dcf2272020-06-11 14:05:13 +02001651 process_haves(data, &common);
Brandon Williams3145ea92018-03-15 10:31:27 -07001652 if (data->done) {
1653 ret = 1;
Christian Couder6fbbc432020-06-11 14:05:14 +02001654 } else if (send_acks(data, &common)) {
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001655 packet_writer_delim(&data->writer);
Brandon Williams3145ea92018-03-15 10:31:27 -07001656 ret = 1;
1657 } else {
1658 /* Add Flush */
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001659 packet_writer_flush(&data->writer);
Brandon Williams3145ea92018-03-15 10:31:27 -07001660 ret = 0;
1661 }
1662
Brandon Williams3145ea92018-03-15 10:31:27 -07001663 oid_array_clear(&data->haves);
1664 oid_array_clear(&common);
1665 return ret;
1666}
1667
Brandon Williams516e2b72018-06-27 15:30:17 -07001668static void send_wanted_ref_info(struct upload_pack_data *data)
1669{
1670 const struct string_list_item *item;
1671
1672 if (!data->wanted_refs.nr)
1673 return;
1674
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001675 packet_writer_write(&data->writer, "wanted-refs\n");
Brandon Williams516e2b72018-06-27 15:30:17 -07001676
1677 for_each_string_list_item(item, &data->wanted_refs) {
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001678 packet_writer_write(&data->writer, "%s %s\n",
1679 oid_to_hex(item->util),
1680 item->string);
Brandon Williams516e2b72018-06-27 15:30:17 -07001681 }
1682
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001683 packet_writer_delim(&data->writer);
Brandon Williams516e2b72018-06-27 15:30:17 -07001684}
1685
Christian Couder389f1612020-05-15 12:04:43 +02001686static void send_shallow_info(struct upload_pack_data *data)
Brandon Williams685fbd32018-03-15 10:31:28 -07001687{
1688 /* No shallow info needs to be sent */
1689 if (!data->depth && !data->deepen_rev_list && !data->shallows.nr &&
Junio C Hamano00624d62018-07-18 12:20:27 -07001690 !is_repository_shallow(the_repository))
Brandon Williams685fbd32018-03-15 10:31:28 -07001691 return;
1692
Jonathan Tanbc2e7952019-01-15 11:40:27 -08001693 packet_writer_write(&data->writer, "shallow-info\n");
Brandon Williams685fbd32018-03-15 10:31:28 -07001694
Christian Couderee703c82020-06-11 14:05:05 +02001695 if (!send_shallow_list(data) &&
Junio C Hamano00624d62018-07-18 12:20:27 -07001696 is_repository_shallow(the_repository))
Christian Couderb1492f22020-06-11 14:05:06 +02001697 deepen(data, INFINITE_DEPTH);
Brandon Williams685fbd32018-03-15 10:31:28 -07001698
1699 packet_delim(1);
1700}
1701
Brandon Williams3145ea92018-03-15 10:31:27 -07001702enum fetch_state {
1703 FETCH_PROCESS_ARGS = 0,
1704 FETCH_SEND_ACKS,
1705 FETCH_SEND_PACK,
1706 FETCH_DONE,
1707};
1708
Jeff King74595cc2023-02-24 01:38:23 -05001709int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request)
Brandon Williams3145ea92018-03-15 10:31:27 -07001710{
1711 enum fetch_state state = FETCH_PROCESS_ARGS;
1712 struct upload_pack_data data;
Jonathan Tand1035ca2018-10-18 13:43:29 -07001713
1714 clear_object_flags(ALL_FLAGS);
Brandon Williams3145ea92018-03-15 10:31:27 -07001715
1716 upload_pack_data_init(&data);
Christian Couderf8edd1c2020-06-04 19:54:41 +02001717 data.use_sideband = LARGE_PACKET_MAX;
Glen Choo5b3c6502022-07-14 21:27:59 +00001718 get_upload_pack_config(&data);
Christian Couder8a0e6f12020-06-04 19:54:45 +02001719
Brandon Williams3145ea92018-03-15 10:31:27 -07001720 while (state != FETCH_DONE) {
1721 switch (state) {
1722 case FETCH_PROCESS_ARGS:
Christian Couder389f1612020-05-15 12:04:43 +02001723 process_args(request, &data);
Brandon Williams3145ea92018-03-15 10:31:27 -07001724
Jonathan Tan9c1e6572021-05-04 14:16:01 -07001725 if (!data.want_obj.nr && !data.wait_for_done) {
Brandon Williams3145ea92018-03-15 10:31:27 -07001726 /*
Jonathan Tan9c1e6572021-05-04 14:16:01 -07001727 * Request didn't contain any 'want' lines (and
1728 * the request does not contain
1729 * "wait-for-done", in which it is reasonable
1730 * to just send 'have's without 'want's); guess
1731 * they didn't want anything.
Brandon Williams3145ea92018-03-15 10:31:27 -07001732 */
1733 state = FETCH_DONE;
1734 } else if (data.haves.nr) {
1735 /*
1736 * Request had 'have' lines, so lets ACK them.
1737 */
1738 state = FETCH_SEND_ACKS;
1739 } else {
1740 /*
1741 * Request had 'want's but no 'have's so we can
1742 * immedietly go to construct and send a pack.
1743 */
1744 state = FETCH_SEND_PACK;
1745 }
1746 break;
1747 case FETCH_SEND_ACKS:
Christian Couder389f1612020-05-15 12:04:43 +02001748 if (process_haves_and_send_acks(&data))
Brandon Williams3145ea92018-03-15 10:31:27 -07001749 state = FETCH_SEND_PACK;
1750 else
1751 state = FETCH_DONE;
1752 break;
1753 case FETCH_SEND_PACK:
Brandon Williams516e2b72018-06-27 15:30:17 -07001754 send_wanted_ref_info(&data);
Christian Couder389f1612020-05-15 12:04:43 +02001755 send_shallow_info(&data);
Brandon Williams685fbd32018-03-15 10:31:28 -07001756
Jonathan Tandd4b7322020-06-10 13:57:23 -07001757 if (data.uri_protocols.nr) {
1758 create_pack_file(&data, &data.uri_protocols);
1759 } else {
1760 packet_writer_write(&data.writer, "packfile\n");
1761 create_pack_file(&data, NULL);
1762 }
Brandon Williams3145ea92018-03-15 10:31:27 -07001763 state = FETCH_DONE;
1764 break;
1765 case FETCH_DONE:
1766 continue;
1767 }
1768 }
1769
1770 upload_pack_data_clear(&data);
1771 return 0;
1772}
Brandon Williams685fbd32018-03-15 10:31:28 -07001773
1774int upload_pack_advertise(struct repository *r,
1775 struct strbuf *value)
1776{
Jonathan Tanba957102018-05-03 16:46:56 -07001777 if (value) {
1778 int allow_filter_value;
Brandon Williams516e2b72018-06-27 15:30:17 -07001779 int allow_ref_in_want;
Jonathan Tan0bbc0bc2019-01-16 11:28:14 -08001780 int allow_sideband_all_value;
Jonathan Tandd4b7322020-06-10 13:57:23 -07001781 char *str = NULL;
Brandon Williams516e2b72018-06-27 15:30:17 -07001782
Jonathan Tan9c1e6572021-05-04 14:16:01 -07001783 strbuf_addstr(value, "shallow wait-for-done");
Brandon Williams516e2b72018-06-27 15:30:17 -07001784
Jeff King4b4e75d2023-02-24 01:38:10 -05001785 if (!repo_config_get_bool(r,
Jonathan Tanba957102018-05-03 16:46:56 -07001786 "uploadpack.allowfilter",
1787 &allow_filter_value) &&
1788 allow_filter_value)
1789 strbuf_addstr(value, " filter");
Brandon Williams516e2b72018-06-27 15:30:17 -07001790
Jeff King4b4e75d2023-02-24 01:38:10 -05001791 if (!repo_config_get_bool(r,
Brandon Williams516e2b72018-06-27 15:30:17 -07001792 "uploadpack.allowrefinwant",
1793 &allow_ref_in_want) &&
1794 allow_ref_in_want)
1795 strbuf_addstr(value, " ref-in-want");
Jonathan Tan0bbc0bc2019-01-16 11:28:14 -08001796
Jonathan Tan07c3c2a2019-01-16 11:28:15 -08001797 if (git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) ||
Jeff King4b4e75d2023-02-24 01:38:10 -05001798 (!repo_config_get_bool(r,
Jonathan Tan07c3c2a2019-01-16 11:28:15 -08001799 "uploadpack.allowsidebandall",
1800 &allow_sideband_all_value) &&
1801 allow_sideband_all_value))
Jonathan Tan0bbc0bc2019-01-16 11:28:14 -08001802 strbuf_addstr(value, " sideband-all");
Jonathan Tandd4b7322020-06-10 13:57:23 -07001803
Jeff King4b4e75d2023-02-24 01:38:10 -05001804 if (!repo_config_get_string(r,
Jonathan Tandd4b7322020-06-10 13:57:23 -07001805 "uploadpack.blobpackfileuri",
1806 &str) &&
1807 str) {
1808 strbuf_addstr(value, " packfile-uris");
1809 free(str);
1810 }
Jonathan Tanba957102018-05-03 16:46:56 -07001811 }
Brandon Williams516e2b72018-06-27 15:30:17 -07001812
Brandon Williams685fbd32018-03-15 10:31:28 -07001813 return 1;
1814}