All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] receive-pack: Two small code cleanups
  2010-02-24 16:41 [RFC][PATCH 0/3] Different views on a repository Andreas Gruenbacher
@ 2010-02-24 15:33 ` Andreas Gruenbacher
  2010-02-24 15:57   ` [PATCH 2/3] Different views on a repository Andreas Gruenbacher
  2010-02-24 17:29   ` [PATCH 1/3] receive-pack: Two small code cleanups Shawn O. Pearce
  2010-02-25 20:13 ` [RFC][PATCH 0/3] Different views on a repository James Pickens
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2010-02-24 15:33 UTC (permalink / raw)
  To: git

Rename show_ref()'s path parameter to refname.

In read_head_info(), lines may have trailing capability strings.  Throw
away such strings after evaluation; they are not needed in the command
structs.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
 builtin-receive-pack.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index 0559fcc..77cbc2a 100644
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
@@ -105,13 +105,13 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
 	return git_default_config(var, value, cb);
 }
 
-static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
+static int show_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 {
 	if (sent_capabilities)
-		packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
+		packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname);
 	else
 		packet_write(1, "%s %s%c%s%s\n",
-			     sha1_to_hex(sha1), path, 0,
+			     sha1_to_hex(sha1), refname, 0,
 			     " report-status delete-refs side-band-64k",
 			     prefer_ofs_delta ? " ofs-delta" : "");
 	sent_capabilities = 1;
@@ -524,7 +524,7 @@ static void read_head_info(void)
 		static char line[1000];
 		unsigned char old_sha1[20], new_sha1[20];
 		struct command *cmd;
-		char *refname;
+		const char *refname;
 		int len, reflen;
 
 		len = packet_read_line(0, line, sizeof(line));
@@ -548,10 +548,10 @@ static void read_head_info(void)
 			if (strstr(refname + reflen + 1, "side-band-64k"))
 				use_sideband = LARGE_PACKET_MAX;
 		}
-		cmd = xmalloc(sizeof(struct command) + len - 80);
+		cmd = xmalloc(sizeof(struct command) + reflen + 1);
 		hashcpy(cmd->old_sha1, old_sha1);
 		hashcpy(cmd->new_sha1, new_sha1);
-		memcpy(cmd->ref_name, line + 82, len - 81);
+		memcpy(cmd->ref_name, refname, reflen + 1);
 		cmd->error_string = NULL;
 		cmd->next = NULL;
 		*p = cmd;
-- 
1.6.6.243.gff6d2

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/3] Different views on a repository
  2010-02-24 15:33 ` [PATCH 1/3] receive-pack: Two small code cleanups Andreas Gruenbacher
@ 2010-02-24 15:57   ` Andreas Gruenbacher
  2010-02-24 16:14     ` [PATCH 3/3] Different views on a repository: HEAD mapping Andreas Gruenbacher
                       ` (2 more replies)
  2010-02-24 17:29   ` [PATCH 1/3] receive-pack: Two small code cleanups Shawn O. Pearce
  1 sibling, 3 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2010-02-24 15:57 UTC (permalink / raw)
  To: git

Add --view options in upload-pack and receive-pack so that a repository
on the server side can be made to look like several independent
repositories on the client side.

This is implemented by transforming ref names: for example, with
--view=one/, refs/heads/one/master on the server will look like
refs/heads/master to the client, refs/tags/one/v1 will look like
refs/tags/v1, etc.

This allows to transparently share repositories on the server which
have a lot of objects in common without complicating things for the
client, and without breaking garbage collection.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
 Documentation/git-receive-pack.txt |    8 +++++-
 Documentation/git-upload-pack.txt  |    9 ++++++-
 builtin-receive-pack.c             |   20 ++++++++++++++++
 refs.c                             |   44 ++++++++++++++++++++++++++++++++++++
 refs.h                             |    3 ++
 upload-pack.c                      |   11 +++++++++
 6 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
index 2790eeb..09d7d0c 100644
--- a/Documentation/git-receive-pack.txt
+++ b/Documentation/git-receive-pack.txt
@@ -8,7 +8,7 @@ git-receive-pack - Receive what is pushed into the repository
 
 SYNOPSIS
 --------
-'git-receive-pack' <directory>
+'git-receive-pack' [--view=<prefix>] <directory>
 
 DESCRIPTION
 -----------
@@ -34,6 +34,12 @@ are not fast-forwards.
 
 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.
+
 <directory>::
 	The repository to sync into.
 
diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt
index 71ca4ef..0eee0ba 100644
--- a/Documentation/git-upload-pack.txt
+++ b/Documentation/git-upload-pack.txt
@@ -8,7 +8,7 @@ git-upload-pack - Send objects packed back to git-fetch-pack
 
 SYNOPSIS
 --------
-'git-upload-pack' [--strict] [--timeout=<n>] <directory>
+'git-upload-pack' [--strict] [--timeout=<n>] [--view=<prefix>] <directory>
 
 DESCRIPTION
 -----------
@@ -30,6 +30,13 @@ OPTIONS
 --timeout=<n>::
 	Interrupt transfer after <n> seconds of inactivity.
 
+--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.
+
 <directory>::
 	The repository to sync from.
 
diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index 77cbc2a..44d7055 100644
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
@@ -32,6 +32,7 @@ static int use_sideband;
 static int prefer_ofs_delta = 1;
 static int auto_update_server_info;
 static int auto_gc = 1;
+static const char *view;
 static const char *head_name;
 static int sent_capabilities;
 
@@ -107,6 +108,12 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
 
 static int show_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 {
+	if (view) {
+		refname = ref_to_view(refname, view);
+		if (!refname)
+			return 0;
+	}
+
 	if (sent_capabilities)
 		packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname);
 	else
@@ -548,6 +555,15 @@ static void read_head_info(void)
 			if (strstr(refname + reflen + 1, "side-band-64k"))
 				use_sideband = LARGE_PACKET_MAX;
 		}
+		if (view) {
+			const char *r;
+
+			r = view_to_ref(refname, view);
+			if (r) {
+				refname = r;
+				reflen = strlen(refname);
+			}
+		}
 		cmd = xmalloc(sizeof(struct command) + reflen + 1);
 		hashcpy(cmd->old_sha1, old_sha1);
 		hashcpy(cmd->new_sha1, new_sha1);
@@ -736,6 +752,10 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 				stateless_rpc = 1;
 				continue;
 			}
+			if (!prefixcmp(arg, "--view=")) {
+				view = arg + 7;
+				continue;
+			}
 
 			usage(receive_pack_usage);
 		}
diff --git a/refs.c b/refs.c
index f3fcbe0..b1f3951 100644
--- a/refs.c
+++ b/refs.c
@@ -1829,3 +1829,47 @@ char *shorten_unambiguous_ref(const char *ref, int strict)
 	free(short_name);
 	return xstrdup(ref);
 }
+
+const char *ref_to_view(const char *refname, const char *view)
+{
+	static char *buffer;
+	int prefix_len, view_len, suffix_len;
+	const char *r, *suffix;
+
+	if (prefixcmp(refname, "refs/"))
+		return NULL;
+	r = strchr(refname + 5, '/');
+	if (!r)
+		return NULL;
+	r++;
+	view_len = strlen(view);
+	if (strncmp(r, view, view_len))
+		return NULL;
+	suffix = r + view_len;
+	prefix_len = r - refname;
+	suffix_len = strlen(suffix);
+	buffer = xrealloc(buffer, prefix_len + suffix_len + 1);
+	sprintf(buffer, "%.*s%s", prefix_len, refname, suffix);
+	return buffer;
+}
+
+const char *view_to_ref(const char *refname, const char *view)
+{
+	static char *buffer;
+	int prefix_len, view_len, suffix_len;
+	const char *r, *suffix;
+
+	view_len = strlen(view);
+	if (prefixcmp(refname, "refs/"))
+		return NULL;
+	r = strchr(refname + 5, '/');
+	if (!r)
+		return NULL;
+	r++;
+	prefix_len = r - refname;
+	suffix = r + view_len;
+	suffix_len = strlen(suffix);
+	buffer = xrealloc(buffer, prefix_len + view_len + suffix_len + 1);
+	sprintf(buffer, "%.*s%s%s", prefix_len, refname, view, suffix);
+	return buffer;
+}
diff --git a/refs.h b/refs.h
index f7648b9..390e812 100644
--- a/refs.h
+++ b/refs.h
@@ -98,4 +98,7 @@ int update_ref(const char *action, const char *refname,
 		const unsigned char *sha1, const unsigned char *oldval,
 		int flags, enum action_on_err onerr);
 
+extern const char *ref_to_view(const char *refname, const char *view);
+extern const char *view_to_ref(const char *refname, const char *view);
+
 #endif /* REFS_H */
diff --git a/upload-pack.c b/upload-pack.c
index dc464d7..bc72471 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -34,6 +34,7 @@ static struct object_array have_obj;
 static struct object_array want_obj;
 static struct object_array extra_edge_obj;
 static unsigned int timeout;
+static const char *view;
 /* 0 for no sideband,
  * otherwise maximum packet size (up to 65520 bytes).
  */
@@ -629,6 +630,12 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 	if (!o)
 		die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
 
+	if (view) {
+		refname = ref_to_view(refname, view);
+		if (!refname)
+			return 0;
+	}
+
 	if (capabilities)
 		packet_write(1, "%s %s%c%s\n", sha1_to_hex(sha1), refname,
 			0, capabilities);
@@ -711,6 +718,10 @@ int main(int argc, char **argv)
 			daemon_mode = 1;
 			continue;
 		}
+		if (!prefixcmp(arg, "--view=")) {
+			view = arg + 7;
+			continue;
+		}
 		if (!strcmp(arg, "--")) {
 			i++;
 			break;
-- 
1.6.6.243.gff6d2

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/3] Different views on a repository: HEAD mapping
  2010-02-24 15:57   ` [PATCH 2/3] Different views on a repository Andreas Gruenbacher
@ 2010-02-24 16:14     ` Andreas Gruenbacher
  2010-02-24 17:42     ` [PATCH 2/3] Different views on a repository Shawn O. Pearce
  2010-02-25  9:01     ` Michael J Gruber
  2 siblings, 0 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2010-02-24 16:14 UTC (permalink / raw)
  To: git

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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC][PATCH 0/3] Different views on a repository
@ 2010-02-24 16:41 Andreas Gruenbacher
  2010-02-24 15:33 ` [PATCH 1/3] receive-pack: Two small code cleanups Andreas Gruenbacher
                   ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2010-02-24 16:41 UTC (permalink / raw)
  To: git

Hello,

we have a use case with groups of repositories which share lots of
objects, but which are logically independent.  There is no strict
hierarchy between the repositories, the development modl is arbitrary.
The alternates mechanism for sharig objects between repositories won't
work.

The best idea I came up with so far to solve this was to keep everything
in the same repository on the server.  Then, to keep the logically
independent repositories separate, directories are used below refs/heads
and refs/tags.  Receive-pack and upload-pack are modified to hide this
directory structure from clients so that repositories will continue to
look "normal" to users.  For example, the following structure on the
server:

	refs/heads/one/master
	refs/tags/one/tag1
	refs/heads/two/master
	refs/heads/two/branch2

would appear as two independent repositories to different clients:

	refs/heads/master
	refs/tags/tag1

and:

	refs/heads/master
	refs/heads/branch2

The following three patches implement this.  What do you guys think --
does the basic idea and implementation look sensible, or am I
overlooking a way to solve this kind of problem with other means?

Thanks!


  receive-pack: Two small code cleanups
  Different views on a repository
  Different views on a repository: HEAD mapping

 Documentation/git-receive-pack.txt |    9 ++++-
 Documentation/git-upload-pack.txt  |   10 +++++-
 builtin-receive-pack.c             |   32 ++++++++++++++---
 refs.c                             |   65 ++++++++++++++++++++++++++++++++++--
 refs.h                             |    4 ++
 upload-pack.c                      |   20 ++++++++++-
 6 files changed, 127 insertions(+), 13 deletions(-)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/3] receive-pack: Two small code cleanups
  2010-02-24 15:33 ` [PATCH 1/3] receive-pack: Two small code cleanups Andreas Gruenbacher
  2010-02-24 15:57   ` [PATCH 2/3] Different views on a repository Andreas Gruenbacher
@ 2010-02-24 17:29   ` Shawn O. Pearce
  1 sibling, 0 replies; 16+ messages in thread
From: Shawn O. Pearce @ 2010-02-24 17:29 UTC (permalink / raw)
  To: Andreas Gruenbacher; +Cc: git

Andreas Gruenbacher <agruen@suse.de> wrote:
> Rename show_ref()'s path parameter to refname.
> 
> In read_head_info(), lines may have trailing capability strings.  Throw
> away such strings after evaluation; they are not needed in the command
> structs.
> 
> Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

Acked-by: Shawn O. Pearce <spearce@spearce.org>

-- 
Shawn.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] Different views on a repository
  2010-02-24 15:57   ` [PATCH 2/3] Different views on a repository Andreas Gruenbacher
  2010-02-24 16:14     ` [PATCH 3/3] Different views on a repository: HEAD mapping Andreas Gruenbacher
@ 2010-02-24 17:42     ` Shawn O. Pearce
  2010-02-25  9:01     ` Michael J Gruber
  2 siblings, 0 replies; 16+ messages in thread
From: Shawn O. Pearce @ 2010-02-24 17:42 UTC (permalink / raw)
  To: Andreas Gruenbacher; +Cc: git

Andreas Gruenbacher <agruen@suse.de> wrote:
> Add --view options in upload-pack and receive-pack so that a repository
> on the server side can be made to look like several independent
> repositories on the client side.

Before saying this is good... I'd like to know how a repository owner
is supposed to set these options on the user started invocations
of other remote side program.

Right now, I don't see how this is too different from just
doing the following on a client:

  git init
  git remote add origin URL
  git config remote.origin.fetch refs/heads/one/*:refs/remotes/origin/*

and therefore shouldn't just be handled on the *client* side of the
connection, as part of the remote setup and push matching refs rules.

(Of course, the push matching ref logic is messy too... adding yet
more into that pile might also be ugly.)

> +const char *view_to_ref(const char *refname, const char *view)
> +{
> +	static char *buffer;
...
> +	buffer = xrealloc(buffer, prefix_len + view_len + suffix_len + 1);
> +	sprintf(buffer, "%.*s%s%s", prefix_len, refname, view, suffix);
> +	return buffer;

I'd rather not use a static buffer like this.  Why not alloc and let
the caller free?  Or have the caller pass in a strbuf you populate
for them?

-- 
Shawn.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] Different views on a repository
  2010-02-24 15:57   ` [PATCH 2/3] Different views on a repository Andreas Gruenbacher
  2010-02-24 16:14     ` [PATCH 3/3] Different views on a repository: HEAD mapping Andreas Gruenbacher
  2010-02-24 17:42     ` [PATCH 2/3] Different views on a repository Shawn O. Pearce
@ 2010-02-25  9:01     ` Michael J Gruber
  2010-02-25  9:25       ` Andreas Gruenbacher
  2 siblings, 1 reply; 16+ messages in thread
From: Michael J Gruber @ 2010-02-25  9:01 UTC (permalink / raw)
  To: Andreas Gruenbacher; +Cc: git

Andreas Gruenbacher venit, vidit, dixit 24.02.2010 16:57:
> Add --view options in upload-pack and receive-pack so that a repository
> on the server side can be made to look like several independent
> repositories on the client side.
> 
> This is implemented by transforming ref names: for example, with
> --view=one/, refs/heads/one/master on the server will look like
> refs/heads/master to the client, refs/tags/one/v1 will look like
> refs/tags/v1, etc.
> 
> This allows to transparently share repositories on the server which
> have a lot of objects in common without complicating things for the
> client, and without breaking garbage collection.

Just from this description, I can't see why the same can't be done with
appropriate refspecs. (A helper for doing that would be more welcome, of
course.)

Maybe a few tests and documentation (i.e. examples, not just the option
description) would clear this up?

Michael

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] Different views on a repository
  2010-02-25  9:01     ` Michael J Gruber
@ 2010-02-25  9:25       ` Andreas Gruenbacher
  2010-02-25 12:30         ` Michael J Gruber
  0 siblings, 1 reply; 16+ messages in thread
From: Andreas Gruenbacher @ 2010-02-25  9:25 UTC (permalink / raw)
  To: Michael J Gruber; +Cc: git

On Thursday 25 February 2010 10:01:43 Michael J Gruber wrote:
> Andreas Gruenbacher venit, vidit, dixit 24.02.2010 16:57:
> > Add --view options in upload-pack and receive-pack so that a repository
> > on the server side can be made to look like several independent
> > repositories on the client side.
> >
> > This is implemented by transforming ref names: for example, with
> > --view=one/, refs/heads/one/master on the server will look like
> > refs/heads/master to the client, refs/tags/one/v1 will look like
> > refs/tags/v1, etc.
> >
> > This allows to transparently share repositories on the server which
> > have a lot of objects in common without complicating things for the
> > client, and without breaking garbage collection.
> 
> Just from this description, I can't see why the same can't be done with
> appropriate refspecs. (A helper for doing that would be more welcome, of
> course.)

You mean on the client side? The problem then is that a simple "git clone" 
would not do the right thing anymore; you would still expose server-side 
implementation details to clients. Clients shouldn't have to bother with this 
added complexity. (They might not even have access to some of the views.) When 
you do the mapping server-side, you can split or merge repositories as needed 
without the clients even noticing.

> Maybe a few tests and documentation (i.e. examples, not just the option
> description) would clear this up?

Indeed, I should add some more background info.

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] Different views on a repository
  2010-02-25  9:25       ` Andreas Gruenbacher
@ 2010-02-25 12:30         ` Michael J Gruber
  2010-02-25 14:35           ` Andreas Gruenbacher
  0 siblings, 1 reply; 16+ messages in thread
From: Michael J Gruber @ 2010-02-25 12:30 UTC (permalink / raw)
  To: Andreas Gruenbacher; +Cc: git

Andreas Gruenbacher venit, vidit, dixit 25.02.2010 10:25:
> On Thursday 25 February 2010 10:01:43 Michael J Gruber wrote:
>> Andreas Gruenbacher venit, vidit, dixit 24.02.2010 16:57:
>>> Add --view options in upload-pack and receive-pack so that a repository
>>> on the server side can be made to look like several independent
>>> repositories on the client side.
>>>
>>> This is implemented by transforming ref names: for example, with
>>> --view=one/, refs/heads/one/master on the server will look like
>>> refs/heads/master to the client, refs/tags/one/v1 will look like
>>> refs/tags/v1, etc.
>>>
>>> This allows to transparently share repositories on the server which
>>> have a lot of objects in common without complicating things for the
>>> client, and without breaking garbage collection.
>>
>> Just from this description, I can't see why the same can't be done with
>> appropriate refspecs. (A helper for doing that would be more welcome, of
>> course.)
> 
> You mean on the client side? The problem then is that a simple "git clone" 
> would not do the right thing anymore; you would still expose server-side 
> implementation details to clients. Clients shouldn't have to bother with this 
> added complexity. (They might not even have access to some of the views.) When 
> you do the mapping server-side, you can split or merge repositories as needed 
> without the clients even noticing.

But the client has to request a specific view, doesn't it? You have to
tell all clients "don't just clone, use...", where the "..." don't seem
to be part of the series yet. [I could see 0/3 on gmane only now, by the
way.]

I just can't help the impression that this is a use case which does not
need a new feature, at least not upload/receive-pack wise. It's more a
matter of ensuring that all clients use a specific configuration (which
you would have to with your patch as well, AFAICT), and this more
general issue is creeping up again and again, with no agreeable solution
so far.

Cheers,
Michael

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] Different views on a repository
  2010-02-25 12:30         ` Michael J Gruber
@ 2010-02-25 14:35           ` Andreas Gruenbacher
  2010-02-25 17:28             ` Junio C Hamano
  0 siblings, 1 reply; 16+ messages in thread
From: Andreas Gruenbacher @ 2010-02-25 14:35 UTC (permalink / raw)
  To: Michael J Gruber; +Cc: git

On Thursday 25 February 2010 13:30:24 Michael J Gruber wrote:
> Andreas Gruenbacher venit, vidit, dixit 25.02.2010 10:25:
> > On Thursday 25 February 2010 10:01:43 Michael J Gruber wrote:
> >> Andreas Gruenbacher venit, vidit, dixit 24.02.2010 16:57:
> >>> Add --view options in upload-pack and receive-pack so that a repository
> >>> on the server side can be made to look like several independent
> >>> repositories on the client side.
> >>>
> >>> This is implemented by transforming ref names: for example, with
> >>> --view=one/, refs/heads/one/master on the server will look like
> >>> refs/heads/master to the client, refs/tags/one/v1 will look like
> >>> refs/tags/v1, etc.
> >>>
> >>> This allows to transparently share repositories on the server which
> >>> have a lot of objects in common without complicating things for the
> >>> client, and without breaking garbage collection.
> >>
> >> Just from this description, I can't see why the same can't be done with
> >> appropriate refspecs. (A helper for doing that would be more welcome, of
> >> course.)
> >
> > You mean on the client side? The problem then is that a simple "git
> > clone" would not do the right thing anymore; you would still expose
> > server-side implementation details to clients. Clients shouldn't have to
> > bother with this added complexity. (They might not even have access to
> > some of the views.) When you do the mapping server-side, you can split or
> > merge repositories as needed without the clients even noticing.
> 
> But the client has to request a specific view, doesn't it?

No, it's a server side thing. The git commands affected are upload-pack and 
receice-pack, and those run on the remote end of a fetch. For example, the 
client would ask the server for repository /foo/one or /foo/two, and the 
server would map that to different views of /bar/shared: when the client asks 
the server to run "git-upload-pack /foo/one", the server runs "git-upload-pack 
--view=one/ /bar/shared" instead.

This is relatively easy to set up over ssh using a simple script; for direct 
git access, a small wrapper daemon would be needed. I'm not sure how this 
could be hacked into http access, but it doesn't seem all that hard, either.

> I just can't help the impression that this is a use case which does not
> need a new feature, at least not upload/receive-pack wise.

Still, even with the additional explanation above?

> It's more a matter of ensuring that all clients use a specific configuration
> (which you would have to with your patch as well, AFAICT), and this more
> general issue is creeping up again and again, with no agreeable solution
> so far.

Well that's another problem which we indeed also have for enabling things like 
local consistency checks and merge drivers. I don't have a good answer here :)

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] Different views on a repository
  2010-02-25 14:35           ` Andreas Gruenbacher
@ 2010-02-25 17:28             ` Junio C Hamano
  2010-02-26  0:45               ` Andreas Gruenbacher
  0 siblings, 1 reply; 16+ messages in thread
From: Junio C Hamano @ 2010-02-25 17:28 UTC (permalink / raw)
  To: Andreas Gruenbacher; +Cc: Michael J Gruber, git

Andreas Gruenbacher <agruen@suse.de> writes:

> No, it's a server side thing.

If it were a server side thing, then I would expect no change to
send/receive pack.  Instead your clients will access distinct URL as if
they are different repositories.

    git clone git://example.com/pub/scm/git/A
    git push example.com:/pub/scm/git/B master
    git pull http://example.com/pub/scm/git/C

They should not have to care that the server is cheating to save disk
space, and they should be able to access your server with Git v1.6.0.

Instead, the server side would:

 - have separate repositories, A, B and C, as normal repositories;

 - these repositories share their object stores by having their
   .git/objects pointing at a shared location via a symlink;

 - on the server side, gc/prune/fsck will have to be updated so that when
   the object store of a repository (say A) is shared with something else,
   they will consider refs in other repositories (B and C) also as the
   root of traversal.

So if this were a server side solution, I would expect the series would
add:

 - a way to set up a shared object store;

 - a way to maintain a list of backlinks to repositories that share an
   object store;

 - a way to create a new repository that shares the object store
   (e.g. create a symlink to the shared store instead of having its own
   .git/objects/, and add itself to the list of backlinks for the shared
   object store);

 - a way to retire an existing such repository (rm -rf and remove itself
   from the list of backlinks);

 - update gc/prune/fsck to honor such a list of backlinks.

This would help a "forks" setup commonly seen at places like repo.or.cz
and github.com among others.

One thing that is missing from the above handwaving outline that your
"different views" offers is a "consolidated view", a pseudo-repository
that allows you to see refs from individual real (from the client's and
project participant's point of view) repositories as if they are in
individual subhierarchies of the ref namespace.

I however suspect that you didn't want such a view in the first place if
there weren't issues around reachability.  In other words, I suspect that
you invented it merely as one possible solution to the reachability issue,
and it was not your goal to have such a consolidated view by itself.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC][PATCH 0/3] Different views on a repository
  2010-02-24 16:41 [RFC][PATCH 0/3] Different views on a repository Andreas Gruenbacher
  2010-02-24 15:33 ` [PATCH 1/3] receive-pack: Two small code cleanups Andreas Gruenbacher
@ 2010-02-25 20:13 ` James Pickens
  2010-02-26  4:30 ` Adam Brewster
       [not found] ` <c376da901002252012s507a6921q922e606bdce4b4fa@mail.gmail.com>
  3 siblings, 0 replies; 16+ messages in thread
From: James Pickens @ 2010-02-25 20:13 UTC (permalink / raw)
  To: Andreas Gruenbacher; +Cc: git

On Wed, Feb 24, 2010, Andreas Gruenbacher <agruen@suse.de> wrote:
> we have a use case with groups of repositories which share lots of
> objects, but which are logically independent.  There is no strict
> hierarchy between the repositories, the development modl is arbitrary.
> The alternates mechanism for sharig objects between repositories won't
> work.

Can you elaborate on why alternates won't work?

> The best idea I came up with so far to solve this

Solve what?  You didn't mention any specific problem.  Are you just trying
to save disk space by not storing multiple copies of the same objects?

James

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] Different views on a repository
  2010-02-25 17:28             ` Junio C Hamano
@ 2010-02-26  0:45               ` Andreas Gruenbacher
  2010-02-26 21:35                 ` Andreas Gruenbacher
  0 siblings, 1 reply; 16+ messages in thread
From: Andreas Gruenbacher @ 2010-02-26  0:45 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Michael J Gruber, git

On Thursday 25 February 2010 18:28:46 Junio C Hamano wrote:
> Andreas Gruenbacher <agruen@suse.de> writes:
> > No, it's a server side thing.
> 
> If it were a server side thing, then I would expect no change to
> send/receive pack.
>
> Instead your clients will access distinct URL as if they are different
> repositories.
> 
>     git clone git://example.com/pub/scm/git/A
>     git push example.com:/pub/scm/git/B master
>     git pull http://example.com/pub/scm/git/C
>
> They should not have to care that the server is cheating to save disk
> space, and they should be able to access your server with Git v1.6.0.
> 
> Instead, the server side would:
> 
>  - have separate repositories, A, B and C, as normal repositories;
> 
>  - these repositories share their object stores by having their
>    .git/objects pointing at a shared location via a symlink;
> 
>  - on the server side, gc/prune/fsck will have to be updated so that when
>    the object store of a repository (say A) is shared with something else,
>    they will consider refs in other repositories (B and C) also as the
>    root of traversal.

I was proposing to change receive-pack and upload-pack, both of which are 
running on the server; there was no mention of send-pack.  What I've proposed 
is not a complete solution, but it should suffice to show the idea.

Your alternative proposal would also solve my problem, in a different way.  
With either approach, what looks like separate repositories A, B, and C to 
clients looks like one repository to gc/prune/fsck.

> So if this were a server side solution, I would expect the series would
> add:
> 
>  - a way to set up a shared object store;
> 
>  - a way to maintain a list of backlinks to repositories that share an
>    object store;
> 
>  - a way to create a new repository that shares the object store
>    (e.g. create a symlink to the shared store instead of having its own
>    .git/objects/, and add itself to the list of backlinks for the shared
>    object store);
> 
>  - a way to retire an existing such repository (rm -rf and remove itself
>    from the list of backlinks);
> 
>  - update gc/prune/fsck to honor such a list of backlinks.
> 
> This would help a "forks" setup commonly seen at places like repo.or.cz
> and github.com among others.

Yes. I'm don't know how big a problem this is for those kinds of hosters; in 
our case, it is a big problem.

> One thing that is missing from the above handwaving outline that your
> "different views" offers is a "consolidated view", a pseudo-repository
> that allows you to see refs from individual real (from the client's and
> project participant's point of view) repositories as if they are in
> individual subhierarchies of the ref namespace.

I have been talking about a repository and different subsets or views of that 
repository; you call the former a consolidated view and the latter a 
repository.  Those are really just two sides of the same coin.

> I however suspect that you didn't want such a view in the first place if
> there weren't issues around reachability.  In other words, I suspect that
> you invented it merely as one possible solution to the reachability issue,
> and it was not your goal to have such a consolidated view by itself.

I'm actually not sure.  The "consolidated view" as you put it may be useful 
all by itself; it would be a proper, self sufficient git repository -- a 
really nice property.  it may be too painful to maintain this view though.

When sharing objects across repositories, the worst-case scenario is that 
something goes wrong with the backlinks.  You will eventually lose objects, 
but it may take a while until it happens and until you notice, with a lot of 
damage.  That's nasty.

A combination of the two approaches would be to "link forward" instead of 
"linking back", so that the consolidated view would maintain itself, with a 
server repo setup like this:

	/repos/ABC:
		objects
		refs/tags/A/
		refs/tags/B/
		refs/heads/A/
		refs/heads/B/

	/repos/A:
		refs/tags -> /repos/ABC/refs/tags/A/
		refs/heads -> /repos/ABC/refs/heads/A/
		objects -> /repos/ABC/objects/

	/repos/B:
		refs/tags -> /repos/ABC/refs/tags/B/
		refs/heads -> /repos/ABC/refs/heads/B/
		objects -> /repos/ABC/objects/

This could be made safe by not doing garbage collection if objects is a 
symlink instead of a directory.  (The ABC repo could be garbage collected as 
usual.)  Am I overlooking anything why this can't work?


Thanks,
Andreas

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC][PATCH 0/3] Different views on a repository
  2010-02-24 16:41 [RFC][PATCH 0/3] Different views on a repository Andreas Gruenbacher
  2010-02-24 15:33 ` [PATCH 1/3] receive-pack: Two small code cleanups Andreas Gruenbacher
  2010-02-25 20:13 ` [RFC][PATCH 0/3] Different views on a repository James Pickens
@ 2010-02-26  4:30 ` Adam Brewster
       [not found] ` <c376da901002252012s507a6921q922e606bdce4b4fa@mail.gmail.com>
  3 siblings, 0 replies; 16+ messages in thread
From: Adam Brewster @ 2010-02-26  4:30 UTC (permalink / raw)
  To: Andreas Gruenbacher; +Cc: git

On Wed, Feb 24, 2010 at 11:41 AM, Andreas Gruenbacher <agruen@suse.de>wrote:

> Hello,
>
> we have a use case with groups of repositories which share lots of
> objects, but which are logically independent.  There is no strict
> hierarchy between the repositories, the development modl is arbitrary.
> The alternates mechanism for sharig objects between repositories won't
> work.
>

I don't know what you're trying to accomplish, but for what it's
worth, I do something similar with a couple of shell scripts.

My goal was to make bundles (basically thin packs) smaller by taking
advantage of files I knew were available on the far side of the
air-gap even if they weren't in a the repository I was bundling that
particular day.

The idea was to push from all of my repositories into a super
repository with a fancy (and auto-generated) refspec.  The actual code
is impenetrable, but reconstructing it in everybody's favorite IDE,
gmail, I came up with

#!/bin/bash
PROJECTS=$HOME/projects
SUPER=$HOME/projects/.git-super-repo

[[ -d "$SUPER" ]] || \
 (mkdir "$SUPER"; git --git-dir="$SUPER" init)

for i in $PROJECTS/*/.git; do
 name=$(basename "$(dirname "$0")")
 echo "$SUPER/objects" > $i/.git/objects/info/alternates
 git --git-dir="$i" push -f "$SUPER" "*:refs/$name/*"
done

git --git-dir="$SUPER" gc --aggressive

for i in $PROJECTS/*/.git; do
 git --git-dir="$i" repack -Ad #unnecessary?
 git --git-dir="$i" gc --aggressive
done

Clearly I can lose data if I try to rebase $SUPER or something, but I
think it's pretty safe for normal use.

In your case, the "projects" are called "views".

Adam

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC][PATCH 0/3] Different views on a repository
       [not found] ` <c376da901002252012s507a6921q922e606bdce4b4fa@mail.gmail.com>
@ 2010-02-26 12:01   ` Andreas Gruenbacher
  0 siblings, 0 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2010-02-26 12:01 UTC (permalink / raw)
  To: Adam Brewster; +Cc: git

On Friday 26 February 2010 05:12:45 Adam Brewster wrote:
> The idea was to push from all of my repositories into a super repository
> with a fancy (and auto-generated) refspec.  The actual code is
> impenetrable, but reconstructing it in everybody's favorite IDE, gmail, I
> came up with
> 
> #!/bin/bash
> PROJECTS=$HOME/projects
> SUPER=$HOME/projects/.git-super-repo
> 
> [[ -d "$SUPER" ]] || \
>   (mkdir "$SUPER"; git --git-dir="$SUPER" init)
> 
> for i in $PROJECTS/*/.git; do
>   name=$(basename "$(dirname "$0")")
>   echo "$SUPER/objects" > $i/.git/objects/info/alternates
>   git --git-dir="$i" push -f "$SUPER" "*:refs/$name/*"
> done
> 
> git --git-dir="$SUPER" gc --aggressive
> 
> for i in $PROJECTS/*/.git; do
>   git --git-dir="$i" repack -Ad #unnecessary?
>   git --git-dir="$i" gc --aggressive
> done

I see, when multiple projects share the same objects, you push them into those 
projects independently first, and the script will later move them to $SUPER.

> Clearly I can lose data if I try to rebase $SUPER or something, but I think
> it's pretty safe for normal use.

It looks safe unless somebody messes with $SUPER.  A lot of repacking will 
still occur as part of moving stuff to $SUPER, though.

I was trying to set things up so that this extra work won't be necessary in 
the first place.

Thanks!

Andreas

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] Different views on a repository
  2010-02-26  0:45               ` Andreas Gruenbacher
@ 2010-02-26 21:35                 ` Andreas Gruenbacher
  0 siblings, 0 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2010-02-26 21:35 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Michael J Gruber, git

On Friday 26 February 2010 01:45:33 Andreas Gruenbacher wrote:
> A combination of the two approaches would be to "link forward" instead of
> "linking back", so that the consolidated view would maintain itself, with a
> server repo setup like this:
> 
> 	/repos/ABC:
> 		objects
> 		refs/tags/A/
> 		refs/tags/B/
> 		refs/heads/A/
> 		refs/heads/B/
> 
> 	/repos/A:
> 		refs/tags -> /repos/ABC/refs/tags/A/
> 		refs/heads -> /repos/ABC/refs/heads/A/
> 		objects -> /repos/ABC/objects/
> 
> 	/repos/B:
> 		refs/tags -> /repos/ABC/refs/tags/B/
> 		refs/heads -> /repos/ABC/refs/heads/B/
> 		objects -> /repos/ABC/objects/
> 
> This could be made safe by not doing garbage collection if objects is a
> symlink instead of a directory.  (The ABC repo could be garbage collected
>  as usual.)  Am I overlooking anything why this can't work?

Self reply: reference packing breaks this kind of setup.  Crap.

Andreas

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2010-02-26 21:35 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-24 16:41 [RFC][PATCH 0/3] Different views on a repository Andreas Gruenbacher
2010-02-24 15:33 ` [PATCH 1/3] receive-pack: Two small code cleanups Andreas Gruenbacher
2010-02-24 15:57   ` [PATCH 2/3] Different views on a repository Andreas Gruenbacher
2010-02-24 16:14     ` [PATCH 3/3] Different views on a repository: HEAD mapping Andreas Gruenbacher
2010-02-24 17:42     ` [PATCH 2/3] Different views on a repository Shawn O. Pearce
2010-02-25  9:01     ` Michael J Gruber
2010-02-25  9:25       ` Andreas Gruenbacher
2010-02-25 12:30         ` Michael J Gruber
2010-02-25 14:35           ` Andreas Gruenbacher
2010-02-25 17:28             ` Junio C Hamano
2010-02-26  0:45               ` Andreas Gruenbacher
2010-02-26 21:35                 ` Andreas Gruenbacher
2010-02-24 17:29   ` [PATCH 1/3] receive-pack: Two small code cleanups Shawn O. Pearce
2010-02-25 20:13 ` [RFC][PATCH 0/3] Different views on a repository James Pickens
2010-02-26  4:30 ` Adam Brewster
     [not found] ` <c376da901002252012s507a6921q922e606bdce4b4fa@mail.gmail.com>
2010-02-26 12:01   ` Andreas Gruenbacher

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.