提交 78a766ab 编写于 作者: L Lukas Fleischer 提交者: Junio C Hamano

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: NLukas Fleischer <lfleischer@lfos.de>
Signed-off-by: NJunio C Hamano <gitster@pobox.com>
上级 00b293e5
...@@ -2680,7 +2680,8 @@ For example, if `refs/heads/master` is specified in `transfer.hideRefs` and ...@@ -2680,7 +2680,8 @@ For example, if `refs/heads/master` is specified in `transfer.hideRefs` and
the current namespace is `foo`, then `refs/namespaces/foo/refs/heads/master` the current namespace is `foo`, then `refs/namespaces/foo/refs/heads/master`
is omitted from the advertisements but `refs/heads/master` and is omitted from the advertisements but `refs/heads/master` and
`refs/namespaces/bar/refs/heads/master` are still advertised as so-called `refs/namespaces/bar/refs/heads/master` are still advertised as so-called
"have" lines. "have" lines. In order to match refs before stripping, add a `^` in front of
the ref name. If you combine `!` and `^`, `!` must be specified first.
transfer.unpackLimit:: transfer.unpackLimit::
When `fetch.unpackLimit` or `receive.unpackLimit` are When `fetch.unpackLimit` or `receive.unpackLimit` are
......
...@@ -195,9 +195,6 @@ static int receive_pack_config(const char *var, const char *value, void *cb) ...@@ -195,9 +195,6 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
static void show_ref(const char *path, const unsigned char *sha1) static void show_ref(const char *path, const unsigned char *sha1)
{ {
if (ref_is_hidden(path))
return;
if (sent_capabilities) { if (sent_capabilities) {
packet_write(1, "%s %s\n", sha1_to_hex(sha1), path); packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
} else { } else {
...@@ -219,9 +216,14 @@ static void show_ref(const char *path, const unsigned char *sha1) ...@@ -219,9 +216,14 @@ static void show_ref(const char *path, const unsigned char *sha1)
} }
} }
static int show_ref_cb(const char *path, const struct object_id *oid, int flag, void *unused) static int show_ref_cb(const char *path_full, const struct object_id *oid,
int flag, void *unused)
{ {
path = strip_namespace(path); const char *path = strip_namespace(path_full);
if (ref_is_hidden(path, path_full))
return 0;
/* /*
* Advertise refs outside our current namespace as ".have" * Advertise refs outside our current namespace as ".have"
* refs, so that the client can use them to minimize data * 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]) ...@@ -1195,16 +1197,29 @@ static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20])
static void reject_updates_to_hidden(struct command *commands) static void reject_updates_to_hidden(struct command *commands)
{ {
struct strbuf refname_full = STRBUF_INIT;
size_t prefix_len;
struct command *cmd; struct command *cmd;
strbuf_addstr(&refname_full, get_git_namespace());
prefix_len = refname_full.len;
for (cmd = commands; cmd; cmd = cmd->next) { for (cmd = commands; cmd; cmd = cmd->next) {
if (cmd->error_string || !ref_is_hidden(cmd->ref_name)) if (cmd->error_string)
continue;
strbuf_setlen(&refname_full, prefix_len);
strbuf_addstr(&refname_full, cmd->ref_name);
if (!ref_is_hidden(cmd->ref_name, refname_full.buf))
continue; continue;
if (is_null_sha1(cmd->new_sha1)) if (is_null_sha1(cmd->new_sha1))
cmd->error_string = "deny deleting a hidden ref"; cmd->error_string = "deny deleting a hidden ref";
else else
cmd->error_string = "deny updating a hidden ref"; cmd->error_string = "deny updating a hidden ref";
} }
strbuf_release(&refname_full);
} }
static int should_process_cmd(struct command *cmd) static int should_process_cmd(struct command *cmd)
......
...@@ -4534,7 +4534,7 @@ int parse_hide_refs_config(const char *var, const char *value, const char *secti ...@@ -4534,7 +4534,7 @@ int parse_hide_refs_config(const char *var, const char *value, const char *secti
return 0; return 0;
} }
int ref_is_hidden(const char *refname) int ref_is_hidden(const char *refname, const char *refname_full)
{ {
int i; int i;
...@@ -4542,6 +4542,7 @@ int ref_is_hidden(const char *refname) ...@@ -4542,6 +4542,7 @@ int ref_is_hidden(const char *refname)
return 0; return 0;
for (i = hide_refs->nr - 1; i >= 0; i--) { for (i = hide_refs->nr - 1; i >= 0; i--) {
const char *match = hide_refs->items[i].string; const char *match = hide_refs->items[i].string;
const char *subject;
int neg = 0; int neg = 0;
int len; int len;
...@@ -4550,10 +4551,18 @@ int ref_is_hidden(const char *refname) ...@@ -4550,10 +4551,18 @@ int ref_is_hidden(const char *refname)
match++; match++;
} }
if (!starts_with(refname, match)) if (*match == '^') {
subject = refname_full;
match++;
} else {
subject = refname;
}
/* refname can be NULL when namespaces are used. */
if (!subject || !starts_with(subject, match))
continue; continue;
len = strlen(match); len = strlen(match);
if (!refname[len] || refname[len] == '/') if (!subject[len] || subject[len] == '/')
return !neg; return !neg;
} }
return 0; return 0;
......
...@@ -444,7 +444,15 @@ int update_ref(const char *msg, const char *refname, ...@@ -444,7 +444,15 @@ int update_ref(const char *msg, const char *refname,
extern int parse_hide_refs_config(const char *var, const char *value, const char *); extern int parse_hide_refs_config(const char *var, const char *value, const char *);
extern int ref_is_hidden(const char *); /*
* Check whether a ref is hidden. If no namespace is set, both the first and
* the second parameter point to the full ref name. If a namespace is set and
* the ref is inside that namespace, the first parameter is a pointer to the
* name of the ref with the namespace prefix removed. If a namespace is set and
* the ref is outside that namespace, the first parameter is NULL. The second
* parameter always points to the full ref name.
*/
extern int ref_is_hidden(const char *, const char *);
enum ref_type { enum ref_type {
REF_TYPE_PER_WORKTREE, REF_TYPE_PER_WORKTREE,
......
...@@ -688,11 +688,12 @@ static void receive_needs(void) ...@@ -688,11 +688,12 @@ static void receive_needs(void)
} }
/* return non-zero if the ref is hidden, otherwise 0 */ /* return non-zero if the ref is hidden, otherwise 0 */
static int mark_our_ref(const char *refname, const struct object_id *oid) static int mark_our_ref(const char *refname, const char *refname_full,
const struct object_id *oid)
{ {
struct object *o = lookup_unknown_object(oid->hash); struct object *o = lookup_unknown_object(oid->hash);
if (refname && ref_is_hidden(refname)) { if (ref_is_hidden(refname, refname_full)) {
o->flags |= HIDDEN_REF; o->flags |= HIDDEN_REF;
return 1; return 1;
} }
...@@ -700,10 +701,12 @@ static int mark_our_ref(const char *refname, const struct object_id *oid) ...@@ -700,10 +701,12 @@ static int mark_our_ref(const char *refname, const struct object_id *oid)
return 0; return 0;
} }
static int check_ref(const char *refname, const struct object_id *oid, static int check_ref(const char *refname_full, const struct object_id *oid,
int flag, void *cb_data) int flag, void *cb_data)
{ {
mark_our_ref(strip_namespace(refname), oid); const char *refname = strip_namespace(refname_full);
mark_our_ref(refname, refname_full, oid);
return 0; return 0;
} }
...@@ -726,7 +729,7 @@ static int send_ref(const char *refname, const struct object_id *oid, ...@@ -726,7 +729,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
const char *refname_nons = strip_namespace(refname); const char *refname_nons = strip_namespace(refname);
struct object_id peeled; struct object_id peeled;
if (mark_our_ref(refname_nons, oid)) if (mark_our_ref(refname_nons, refname, oid))
return 0; return 0;
if (capabilities) { if (capabilities) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册