64
65
static int filter_capability_requested;
66
static int allow_filter;
67
+static int allow_ref_in_want;
68
static struct list_objects_filter_options filter_options;
69
70
static void reset_timeout(void)
1076
return git_config_string(&pack_objects_hook, var, value);
1077
} else if (!strcmp("uploadpack.allowfilter", var)) {
1078
allow_filter = git_config_bool(var, value);
1079
+ } else if (!strcmp("uploadpack.allowrefinwant", var)) {
1080
+ allow_ref_in_want = git_config_bool(var, value);
1081
}
1082
return parse_hide_refs_config(var, value, "uploadpack");
1083
}
1117
1118
struct upload_pack_data {
1119
struct object_array wants;
1120
+ struct string_list wanted_refs;
1121
struct oid_array haves;
1122
1123
struct object_array shallows;
1139
static void upload_pack_data_init(struct upload_pack_data *data)
1140
{
1141
struct object_array wants = OBJECT_ARRAY_INIT;
1142
+ struct string_list wanted_refs = STRING_LIST_INIT_DUP;
1143
struct oid_array haves = OID_ARRAY_INIT;
1144
struct object_array shallows = OBJECT_ARRAY_INIT;
1145
struct string_list deepen_not = STRING_LIST_INIT_DUP;
1146
1147
memset(data, 0, sizeof(*data));
1148
data->wants = wants;
1149
+ data->wanted_refs = wanted_refs;
1150
data->haves = haves;
1151
data->shallows = shallows;
1152
data->deepen_not = deepen_not;
1155
static void upload_pack_data_clear(struct upload_pack_data *data)
1156
{
1157
object_array_clear(&data->wants);
1158
+ string_list_clear(&data->wanted_refs, 1);
1159
oid_array_clear(&data->haves);
1160
object_array_clear(&data->shallows);
1161
string_list_clear(&data->deepen_not, 0);
1192
return 0;
1193
}
1194
1195
+static int parse_want_ref(const char *line, struct string_list *wanted_refs)
1196
+{
1197
+ const char *arg;
1198
+ if (skip_prefix(line, "want-ref ", &arg)) {
1199
+ struct object_id oid;
1200
+ struct string_list_item *item;
1201
+ struct object *o;
1202
+
1203
+ if (read_ref(arg, &oid)) {
1204
+ packet_write_fmt(1, "ERR unknown ref %s", arg);
1205
+ die("unknown ref %s", arg);
1206
+ }
1207
+
1208
+ item = string_list_append(wanted_refs, arg);
1209
+ item->util = oiddup(&oid);
1210
+
1211
+ o = parse_object_or_die(&oid, arg);
1212
+ if (!(o->flags & WANTED)) {
1213
+ o->flags |= WANTED;
1214
+ add_object_array(o, NULL, &want_obj);
1215
+ }
1216
+
1217
+ return 1;
1218
+ }
1219
+
1220
+ return 0;
1221
+}
1222
+
1223
static int parse_have(const char *line, struct oid_array *haves)
1224
{
1225
const char *arg;
1245
/* process want */
1246
if (parse_want(arg))
1247
continue;
1248
+ if (allow_ref_in_want && parse_want_ref(arg, &data->wanted_refs))
1249
+ continue;
1250
/* process have line */
1251
if (parse_have(arg, &data->haves))
1252
continue;
1389
return ret;
1390
}
1391
1392
+static void send_wanted_ref_info(struct upload_pack_data *data)
1393
+{
1394
+ const struct string_list_item *item;
1395
+
1396
+ if (!data->wanted_refs.nr)
1397
+ return;
1398
+
1399
+ packet_write_fmt(1, "wanted-refs\n");
1400
+
1401
+ for_each_string_list_item(item, &data->wanted_refs) {
1402
+ packet_write_fmt(1, "%s %s\n",
1403
+ oid_to_hex(item->util),
1404
+ item->string);
1405
+ }
1406
+
1407
+ packet_delim(1);
1408
+}
1409
+
1410
static void send_shallow_info(struct upload_pack_data *data)
1411
{
1412
/* No shallow info needs to be sent */
1473
state = FETCH_DONE;
1474
break;
1475
case FETCH_SEND_PACK:
1476
+ send_wanted_ref_info(&data);
1477
send_shallow_info(&data);
1478
1479
packet_write_fmt(1, "packfile\n");
1494
{
1495
if (value) {
1496
int allow_filter_value;
1497
+ int allow_ref_in_want;
1498
+
1499
strbuf_addstr(value, "shallow");
1500
+
1501
if (!repo_config_get_bool(the_repository,
1502
"uploadpack.allowfilter",
1503
&allow_filter_value) &&
1504
allow_filter_value)
1505
strbuf_addstr(value, " filter");
1506
+
1507
+ if (!repo_config_get_bool(the_repository,
1508
+ "uploadpack.allowrefinwant",
1509
+ &allow_ref_in_want) &&
1510
+ allow_ref_in_want)
1511
+ strbuf_addstr(value, " ref-in-want");
1512
}
1513
+
1514
return 1;
1515
}