diff mbox series

[v6,3/5] hiderefs: hornor hide flags in wire protocol V2

Message ID 0013476266e05aebd41e455b3d6305e8ec347a9e.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>

Previously hiderefs configurations can not protect the private data
of hiding refs in wire protocol V2, for example, an `ALL_FLAGS` flag
will be used to clear all the objects before handling the fetch requests.

Hornor the hide flags by removing the `HIDDEN_REFS` flag from the
`ALL_FLAGS` and make sure all the refs will check its hidden flags
before sending the pack to client, especially during stateless RPC.
And if there are refs with `HIDDEN_REF_FORCE` flag, use `check_non_tip`
to protect the private data of force-hidden refs.

Signed-off-by: Sun Chao <sunchao9@huawei.com>
---
 ls-refs.c     |  2 +-
 refs.c        | 20 ++++++++++++++++++++
 refs.h        |  4 ++++
 upload-pack.c | 11 +++++++++--
 4 files changed, 34 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/ls-refs.c b/ls-refs.c
index 98e69373c84..b5cb1316d38 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -84,7 +84,7 @@  static int send_ref(const char *refname, const struct object_id *oid,
 
 	strbuf_reset(&data->buf);
 
-	if (ref_is_hidden(refname_nons, refname))
+	if (mark_our_ref(refname_nons, refname, oid))
 		return 0;
 
 	if (!ref_match(&data->prefixes, refname_nons))
diff --git a/refs.c b/refs.c
index 5a9079fd4c4..847f7c003e6 100644
--- a/refs.c
+++ b/refs.c
@@ -1659,6 +1659,25 @@  int ref_is_hidden(const char *refname, const char *refname_full)
  */
 #define HIDDEN_REF_FORCE	(1u << 20)
 
+/* Use this variable to record existing object hidden flags */
+static unsigned int objects_hidden_flags;
+
+/* Return non-zero if need to batch check hidden refs, otherwise 0 */
+int need_check_hidden_refs(void)
+{
+	if (!objects_hidden_flags)
+		return 1;
+	return 0;
+}
+
+/* Return non-zero if some ref is force hidden, otherwise 0 */
+int has_force_hidden_refs(void)
+{
+	if (objects_hidden_flags & HIDDEN_REF_FORCE)
+		return 1;
+	return 0;
+}
+
 static unsigned int ref_hidden_flag(const char *refname, const char *refname_full)
 {
 	if (ref_hidden_check(refname, refname_full, 1))
@@ -1681,6 +1700,7 @@  int mark_our_ref(const char *refname, const char *refname_full,
 	o = lookup_unknown_object(the_repository, oid);
 	flag = ref_hidden_flag(refname, refname_full);
 	o->flags |= flag;
+	objects_hidden_flags |= flag;
 
 	if (flag & OUR_REF)
 		return 0;
diff --git a/refs.h b/refs.h
index 2feabfe35c4..8deb36a95cc 100644
--- a/refs.h
+++ b/refs.h
@@ -822,6 +822,10 @@  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);
+/* return non-zero if need to batch check hidden refs, otherwise 0 */
+int need_check_hidden_refs(void);
+/* return non-zero if some ref is force hidden, otherwise 0 */
+int has_force_hidden_refs(void);
 
 enum ref_type {
 	REF_TYPE_PER_WORKTREE,	  /* refs inside refs/ but not shared       */
diff --git a/upload-pack.c b/upload-pack.c
index a8ca5d1c26e..a9a24399d8e 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -39,8 +39,8 @@ 
 #define CLIENT_SHALLOW	(1u << 18)
 #define HIDDEN_REF	(1u << 19)
 
-#define ALL_FLAGS (THEY_HAVE | OUR_REF | WANTED | COMMON_KNOWN | SHALLOW | \
-		NOT_SHALLOW | CLIENT_SHALLOW | HIDDEN_REF)
+#define ALL_FLAGS (THEY_HAVE |WANTED | COMMON_KNOWN | SHALLOW | \
+		NOT_SHALLOW | CLIENT_SHALLOW)
 
 /* Enum for allowed unadvertised object request (UOR) */
 enum allow_uor {
@@ -1726,6 +1726,13 @@  int upload_pack_v2(struct repository *r, struct packet_reader *request)
 				state = FETCH_DONE;
 			break;
 		case FETCH_SEND_PACK:
+			if (need_check_hidden_refs()) {
+				head_ref_namespaced(check_ref, NULL);
+				for_each_namespaced_ref(check_ref, NULL);
+			}
+			if (has_force_hidden_refs())
+				check_non_tip(&data);
+
 			send_wanted_ref_info(&data);
 			send_shallow_info(&data);