diff mbox series

[v6,2/5] hiderefs: use a new flag to mark force hidden refs

Message ID f309e9534f2397fc575634108279aa7dd038feae.1663662167.git.gitgitgadget@gmail.com (mailing list archive)
State New, archived
Headers show
Series hiderefs: add hide-refs hook to hide refs dynamically | expand

Commit Message

Sun Chao Sept. 20, 2022, 8:22 a.m. UTC
From: Sun Chao <sunchao9@huawei.com>

If uploadpack.allowTipSHA1InWant or uploadpack.allowReachableSHA1InWant
is set to true, the private commits of hiding refs can be fetched by
the client. The new hide-refs hook is used to hide our refs and we wish
to hide the private commits either.

A new flag `HIDDEN_REF_FORCE` is used to mark a ref if hide-refs hook
decides to hide it, and we make sure the wire protocol V1 will reject
to send the private commits of this kind of refs even if
uploadpack.allowTipSHA1InWant or uploadpack.allowReachableSHA1InWant
is set to true.

Signed-off-by: Sun Chao <sunchao9@huawei.com>
---
 refs.c        | 39 +++++++++++++++++++++++++++++++++++++++
 refs.h        |  3 +++
 upload-pack.c | 14 --------------
 3 files changed, 42 insertions(+), 14 deletions(-)
diff mbox series

Patch

diff --git a/refs.c b/refs.c
index 68368055946..5a9079fd4c4 100644
--- a/refs.c
+++ b/refs.c
@@ -1648,6 +1648,45 @@  int ref_is_hidden(const char *refname, const char *refname_full)
 	return 0;
 }
 
+#define OUR_REF		(1u << 12)
+#define HIDDEN_REF	(1u << 19)
+/*
+ * Use this flag to mark a ref that is hidden by the hide-refs hook, its private
+ * commits (tip or non-tip commits, not reachable by the refs not hidden by the
+ * hide-refs hook) will be forced hidden to the client, which means a client can
+ * not fetch such kind of commits even uploadpack.allowTipSHA1InWant or
+ * uploadpack.allowReachableSHA1InWant are set to true
+ */
+#define HIDDEN_REF_FORCE	(1u << 20)
+
+static unsigned int ref_hidden_flag(const char *refname, const char *refname_full)
+{
+	if (ref_hidden_check(refname, refname_full, 1))
+		return HIDDEN_REF_FORCE;
+	else if (ref_hidden_check(refname, refname_full, 0))
+		return HIDDEN_REF;
+	return OUR_REF;
+}
+
+int mark_our_ref(const char *refname, const char *refname_full,
+		 const struct object_id *oid)
+{
+	struct object *o;
+	unsigned int flag;
+
+	if (!oid || is_null_oid(oid)) {
+		return 0;
+	}
+
+	o = lookup_unknown_object(the_repository, oid);
+	flag = ref_hidden_flag(refname, refname_full);
+	o->flags |= flag;
+
+	if (flag & OUR_REF)
+		return 0;
+	return 1;
+}
+
 const char *find_descendant_ref(const char *dirname,
 				const struct string_list *extras,
 				const struct string_list *skip)
diff --git a/refs.h b/refs.h
index d6575b8c2bd..2feabfe35c4 100644
--- a/refs.h
+++ b/refs.h
@@ -819,6 +819,9 @@  int parse_hide_refs_config(const char *var, const char *value, const char *);
  * parameter always points to the full ref name.
  */
 int ref_is_hidden(const char *, const char *);
+/* return non-zero if the ref is hidden, otherwise 0 */
+int mark_our_ref(const char *refname, const char *refname_full,
+		 const struct object_id *oid);
 
 enum ref_type {
 	REF_TYPE_PER_WORKTREE,	  /* refs inside refs/ but not shared       */
diff --git a/upload-pack.c b/upload-pack.c
index b217a1f469e..a8ca5d1c26e 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1155,20 +1155,6 @@  static void receive_needs(struct upload_pack_data *data,
 		packet_flush(1);
 }
 
-/* return non-zero if the ref is hidden, otherwise 0 */
-static int mark_our_ref(const char *refname, const char *refname_full,
-			const struct object_id *oid)
-{
-	struct object *o = lookup_unknown_object(the_repository, oid);
-
-	if (ref_is_hidden(refname, refname_full)) {
-		o->flags |= HIDDEN_REF;
-		return 1;
-	}
-	o->flags |= OUR_REF;
-	return 0;
-}
-
 static int check_ref(const char *refname_full, const struct object_id *oid,
 		     int flag, void *cb_data)
 {