hideRefs: add support for matching full refs
In addition to matching stripped refs, one can now add hideRefs patterns that the full (unstripped) ref is matched against. To distinguish between stripped and full matches, those new patterns must be prefixed with a circumflex (^). This commit also removes support for the undocumented and unintended hideRefs settings ".have" (suppressing all "have" lines) and "capabilities^{}" (suppressing the capabilities line). Signed-off-by: Lukas Fleischer <lfleischer@lfos.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Lukas Fleischer committed
Nov 3, 2015 at 08:58 UTC
78a766ab6eaaa91c2638158bd4fda06a93291da0
5 files changed
+52
-16
Documentation/config.txt
+2
-1
@@ -2680,7 +2680,8 @@ For example, if `refs/heads/master` is specified in `transfer.hideRefs` and
2680
the current namespace is `foo`, then `refs/namespaces/foo/refs/heads/master`
2681
is omitted from the advertisements but `refs/heads/master` and
2682
`refs/namespaces/bar/refs/heads/master` are still advertised as so-called
2683
-"have" lines.
2683
+"have" lines. In order to match refs before stripping, add a `^` in front of
2684
+the ref name. If you combine `!` and `^`, `!` must be specified first.
2685
2686
transfer.unpackLimit::
2687
When `fetch.unpackLimit` or `receive.unpackLimit` are
builtin/receive-pack.c
+21
-6
@@ -195,9 +195,6 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
195
196
static void show_ref(const char *path, const unsigned char *sha1)
197
{
198
- if (ref_is_hidden(path))
199
- return;
200
-
198
if (sent_capabilities) {
199
packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
200
} else {
@@ -219,9 +216,14 @@ static void show_ref(const char *path, const unsigned char *sha1)
216
}
217
}
218
222
-static int show_ref_cb(const char *path, const struct object_id *oid, int flag, void *unused)
219
+static int show_ref_cb(const char *path_full, const struct object_id *oid,
220
+ int flag, void *unused)
221
{
224
- path = strip_namespace(path);
222
+ const char *path = strip_namespace(path_full);
223
+
224
+ if (ref_is_hidden(path, path_full))
225
+ return 0;
226
+
227
/*
228
* Advertise refs outside our current namespace as ".have"
229
* refs, so that the client can use them to minimize data
@@ -1195,16 +1197,29 @@ static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20])
1197
1198
static void reject_updates_to_hidden(struct command *commands)
1199
{
1200
+ struct strbuf refname_full = STRBUF_INIT;
1201
+ size_t prefix_len;
1202
struct command *cmd;
1203
1204
+ strbuf_addstr(&refname_full, get_git_namespace());
1205
+ prefix_len = refname_full.len;
1206
+
1207
for (cmd = commands; cmd; cmd = cmd->next) {
1201
- if (cmd->error_string || !ref_is_hidden(cmd->ref_name))
1208
+ if (cmd->error_string)
1209
+ continue;
1210
+
1211
+ strbuf_setlen(&refname_full, prefix_len);
1212
+ strbuf_addstr(&refname_full, cmd->ref_name);
1213
+
1214
+ if (!ref_is_hidden(cmd->ref_name, refname_full.buf))
1215
continue;
1216
if (is_null_sha1(cmd->new_sha1))
1217
cmd->error_string = "deny deleting a hidden ref";
1218
else
1219
cmd->error_string = "deny updating a hidden ref";
1220
}
1221
+
1222
+ strbuf_release(&refname_full);
1223
}
1224
1225
static int should_process_cmd(struct command *cmd)
refs.c
+12
-3
@@ -4534,7 +4534,7 @@ int parse_hide_refs_config(const char *var, const char *value, const char *secti
4534
return 0;
4535
}
4536
4537
-int ref_is_hidden(const char *refname)
4537
+int ref_is_hidden(const char *refname, const char *refname_full)
4538
{
4539
int i;
4540
@@ -4542,6 +4542,7 @@ int ref_is_hidden(const char *refname)
4542
return 0;
4543
for (i = hide_refs->nr - 1; i >= 0; i--) {
4544
const char *match = hide_refs->items[i].string;
4545
+ const char *subject;
4546
int neg = 0;
4547
int len;
4548
@@ -4550,10 +4551,18 @@ int ref_is_hidden(const char *refname)
4551
match++;
4552
}
4553
4553
- if (!starts_with(refname, match))
4554
+ if (*match == '^') {
4555
+ subject = refname_full;
4556
+ match++;
4557
+ } else {
4558
+ subject = refname;
4559
+ }
4560
+
4561
+ /* refname can be NULL when namespaces are used. */
4562
+ if (!subject || !starts_with(subject, match))
4563
continue;
4564
len = strlen(match);
4556
- if (!refname[len] || refname[len] == '/')
4565
+ if (!subject[len] || subject[len] == '/')
4566
return !neg;
4567
}
4568
return 0;
refs.h
+9
-1
@@ -444,7 +444,15 @@ int update_ref(const char *msg, const char *refname,
444
445
extern int parse_hide_refs_config(const char *var, const char *value, const char *);
446
447
-extern int ref_is_hidden(const char *);
447
+/*
448
+ * Check whether a ref is hidden. If no namespace is set, both the first and
449
+ * the second parameter point to the full ref name. If a namespace is set and
450
+ * the ref is inside that namespace, the first parameter is a pointer to the
451
+ * name of the ref with the namespace prefix removed. If a namespace is set and
452
+ * the ref is outside that namespace, the first parameter is NULL. The second
453
+ * parameter always points to the full ref name.
454
+ */
455
+extern int ref_is_hidden(const char *, const char *);
456
457
enum ref_type {
458
REF_TYPE_PER_WORKTREE,
upload-pack.c
+8
-5
@@ -688,11 +688,12 @@ static void receive_needs(void)
688
}
689
690
/* return non-zero if the ref is hidden, otherwise 0 */
691
-static int mark_our_ref(const char *refname, const struct object_id *oid)
691
+static int mark_our_ref(const char *refname, const char *refname_full,
692
+ const struct object_id *oid)
693
{
694
struct object *o = lookup_unknown_object(oid->hash);
695
695
- if (refname && ref_is_hidden(refname)) {
696
+ if (ref_is_hidden(refname, refname_full)) {
697
o->flags |= HIDDEN_REF;
698
return 1;
699
}
@@ -700,10 +701,12 @@ static int mark_our_ref(const char *refname, const struct object_id *oid)
701
return 0;
702
}
703
703
-static int check_ref(const char *refname, const struct object_id *oid,
704
+static int check_ref(const char *refname_full, const struct object_id *oid,
705
int flag, void *cb_data)
706
{
706
- mark_our_ref(strip_namespace(refname), oid);
707
+ const char *refname = strip_namespace(refname_full);
708
+
709
+ mark_our_ref(refname, refname_full, oid);
710
return 0;
711
}
712
@@ -726,7 +729,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
729
const char *refname_nons = strip_namespace(refname);
730
struct object_id peeled;
731
729
- if (mark_our_ref(refname_nons, oid))
732
+ if (mark_our_ref(refname_nons, refname, oid))
733
return 0;
734
735
if (capabilities) {