git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/3] Different views on a repository: HEAD mapping

From
AGAndreas Gruenbacher <agruen@suse.de>
Date
Feb 24, 2010, 16:14 UTC
Message-ID
<d4ad6b45786def21cbe484c97723aa573b069175.1267029680.git.agruen@suse.de>
In-Reply-To
<92fea2335b73265b04d64fcc217055e1170f5e16.1267029680.git.agruen@suse.de>

The HEAD ref is not located under .git/refs/heads/, so the trivial view mapping doesn't work. Fix this by making refs/heads/<view>HEAD appear as HEAD on the client when --view=<view> is used in upload-pack and receive-pack.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
 Documentation/git-receive-pack.txt |    7 ++++---
 Documentation/git-upload-pack.txt  |    9 +++++----
 refs.c                             |   21 ++++++++++++++++++---
 refs.h                             |    1 +
 upload-pack.c                      |    9 +++++++--
 5 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
index 09d7d0c..07e0159 100644
--- a/Documentation/git-receive-pack.txt
+++ b/Documentation/git-receive-pack.txt
@@ -36,9 +36,10 @@ OPTIONS
 -------
 --view=<prefix>::
 	Prepend <prefix> to all ref names.  For example, --view=one/ will
-	turn refs/tags/v1 into refs/tags/one/v1 on the receiving end.  Together
-	with the --view option of linkgit:git-upload-pack[1], this allows to
-	make one respository look like multiple independent repositories.
+	turn refs/tags/v1 into refs/tags/one/v1 and HEAD into refs/heads/one/HEAD
+	on the receiving end.  Together with the --view option of
+	linkgit:git-upload-pack[1], this allows to make one respository look like
+	multiple independent repositories.
 
 <directory>::
 	The repository to sync into.
diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt
index 0eee0ba..1e8b76b 100644
--- a/Documentation/git-upload-pack.txt
+++ b/Documentation/git-upload-pack.txt
@@ -32,10 +32,11 @@ OPTIONS
 
 --view=<prefix>::
 	Only upload refs which start with <prefix>, and hide <prefix> from the
-	remote side.  For example, --view=one/ will skip refs/heads/master
-	and turn refs/tags/one/v1 into refs/tags/v1.  Together with the --view
-	option of linkgit:git-receive-pack, this allows to make one respository
-	look like multiple independent repositories.
+	remote side.  For example, --view=one/ will skip refs/heads/master,
+	turn refs/tags/one/v1 into refs/tags/v1, and refs/heads/one/HEAD into
+	HEAD.  Together with the --view option of linkgit:git-receive-pack,
+	this allows to make one respository look like multiple independent
+	repositories.
 
 <directory>::
 	The repository to sync from.
diff --git a/refs.c b/refs.c
index b1f3951..77a6267 100644
--- a/refs.c
+++ b/refs.c
@@ -650,16 +650,21 @@ end_each:
 	return retval;
 }
 
-int head_ref(each_ref_fn fn, void *cb_data)
+int one_ref(each_ref_fn fn, void *cb_data, const char *refname)
 {
 	unsigned char sha1[20];
 	int flag;
 
-	if (resolve_ref("HEAD", sha1, 1, &flag))
-		return fn("HEAD", sha1, flag, cb_data);
+	if (resolve_ref(refname, sha1, 1, &flag))
+		return fn(refname, sha1, flag, cb_data);
 	return 0;
 }
 
+int head_ref(each_ref_fn fn, void *cb_data)
+{
+	return one_ref(fn, cb_data, "HEAD");
+}
+
 int for_each_ref(each_ref_fn fn, void *cb_data)
 {
 	return do_for_each_ref("refs/", fn, 0, 0, cb_data);
@@ -1846,6 +1851,10 @@ const char *ref_to_view(const char *refname, const char *view)
 	if (strncmp(r, view, view_len))
 		return NULL;
 	suffix = r + view_len;
+	if (!strncmp(refname + 5, "heads/", 6) &&
+	    !strcmp(suffix, "HEAD"))
+		return "HEAD";
+
 	prefix_len = r - refname;
 	suffix_len = strlen(suffix);
 	buffer = xrealloc(buffer, prefix_len + suffix_len + 1);
@@ -1860,6 +1869,12 @@ const char *view_to_ref(const char *refname, const char *view)
 	const char *r, *suffix;
 
 	view_len = strlen(view);
+	if (!strcmp(refname, "HEAD")) {
+		buffer = xrealloc(buffer, view_len + 16);
+		sprintf(buffer, "refs/heads/%sHEAD", view);
+		return buffer;
+	}
+
 	if (prefixcmp(refname, "refs/"))
 		return NULL;
 	r = strchr(refname + 5, '/');
diff --git a/refs.h b/refs.h
index 390e812..addcc2d 100644
--- a/refs.h
+++ b/refs.h
@@ -18,6 +18,7 @@ struct ref_lock {
  * and returns the value
  */
 typedef int each_ref_fn(const char *refname, const unsigned char *sha1, int flags, void *cb_data);
+extern int one_ref(each_ref_fn, void *, const char *);
 extern int head_ref(each_ref_fn, void *);
 extern int for_each_ref(each_ref_fn, void *);
 extern int for_each_ref_in(const char *, each_ref_fn, void *);
diff --git a/upload-pack.c b/upload-pack.c
index bc72471..b3bf20f 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -668,13 +668,18 @@ static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag
 
 static void upload_pack(void)
 {
+	const char *head = "HEAD";
+
+	if (view)
+		head = view_to_ref(head, view);
+
 	if (advertise_refs || !stateless_rpc) {
 		reset_timeout();
-		head_ref(send_ref, NULL);
+		one_ref(send_ref, NULL, head);
 		for_each_ref(send_ref, NULL);
 		packet_flush(1);
 	} else {
-		head_ref(mark_our_ref, NULL);
+		one_ref(mark_our_ref, NULL, head);
 		for_each_ref(mark_our_ref, NULL);
 	}
 	if (advertise_refs)
-- 
1.6.6.243.gff6d2
Previous: Andreas GruenbacherNext: Shawn O. Pearce
Message 4 of 16 in “Different views on a repository”
  1. Andreas GruenbacherFeb 24, 2010
  2. 1/3 receive-pack: Two small code cleanupsAndreas Gruenbacher, Feb 24, 2010
  3. 2/3 Different views on a repositoryAndreas Gruenbacher, Feb 24, 2010
  4. 3/3 Different views on a repository: HEAD mappingAndreas Gruenbacher, Feb 24, 2010
  5. Shawn O. PearceFeb 24, 2010
  6. Michael J GruberFeb 25, 2010
  7. Andreas GruenbacherFeb 25, 2010
  8. Michael J GruberFeb 25, 2010
  9. Andreas GruenbacherFeb 25, 2010
  10. Junio C HamanoFeb 25, 2010
  11. Andreas GruenbacherFeb 26, 2010
  12. Andreas GruenbacherFeb 26, 2010
  13. Shawn O. PearceFeb 24, 2010
  14. James PickensFeb 25, 2010
  15. Adam BrewsterFeb 26, 2010
  16. Andreas GruenbacherFeb 26, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.