All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv8 0/4] Support ref namespaces
@ 2011-06-07 23:04 Jamey Sharp
  2011-06-07 23:04 ` [PATCHv8 1/4] Fix prefix handling in ref iteration functions Jamey Sharp
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Jamey Sharp @ 2011-06-07 23:04 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Shawn O. Pearce, Johannes Schindelin, Jeff King, Jakub Narebski,
	Bert Wesarg, git

This series adds support for dividing the refs of a single repository
into multiple namespaces, each of which can have its own branches, tags,
and HEAD. Git can expose each namespace as an independent repository to
pull from and push to, while sharing the object store, and exposing all
the refs to operations such as git-gc.

Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source.  The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.

The first patch improves the prefix handling in the ref iteration
functions, making it possible for us to implement
for_each_namespaced_ref later. The next two patches implement and then
use infrastructure for tracking the current namespace and iterating over
the refs in that namespace. The last patch adds general documentation
for namespaces, and specific references from the documentation on
receive-pack, upload-pack, http-backend, and git.

v8: Fix error message in parsing of the --namespace option; noticed by
Bert Wesarg.

v7 (unintentionally sent without a version number): Back out the change
to actually use "refs/" as a filter, which caused t5501 to fail.  Patch
1/4 now preserves the existing behavior, to avoid breaking assumptions
like this; that seems preferable to tracking down all the places that
would break due to this new ref filtering.  Adding that filtering and
fixing all the resulting breakage seems like an entirely separate
change.

Josh Triplett and Jamey Sharp (4):
  Fix prefix handling in ref iteration functions
  Add infrastructure for ref namespaces
  Support ref namespaces for remote repositories via upload-pack and
    receive-pack
  Add documentation for ref namespaces

 Documentation/Makefile                 |    2 +-
 Documentation/git-http-backend.txt     |    8 +++
 Documentation/git-receive-pack.txt     |    2 +-
 Documentation/git-upload-pack.txt      |    4 ++
 Documentation/git.txt                  |   13 +++++-
 Documentation/gitnamespaces.txt        |   75 ++++++++++++++++++++++++++++++++
 builtin/receive-pack.c                 |   34 ++++++++++++---
 cache.h                                |    3 +
 contrib/completion/git-completion.bash |    3 +-
 environment.c                          |   41 +++++++++++++++++
 git.c                                  |   18 +++++++-
 refs.c                                 |   33 ++++++++++++--
 refs.h                                 |    3 +
 upload-pack.c                          |   15 +++---
 14 files changed, 230 insertions(+), 24 deletions(-)
 create mode 100644 Documentation/gitnamespaces.txt

-- 
1.7.5.3

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

* [PATCHv8 1/4] Fix prefix handling in ref iteration functions
  2011-06-07 23:04 [PATCHv8 0/4] Support ref namespaces Jamey Sharp
@ 2011-06-07 23:04 ` Jamey Sharp
  2011-06-08  0:17   ` Junio C Hamano
  2011-06-07 23:04 ` [PATCHv8 2/4] Add infrastructure for ref namespaces Jamey Sharp
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Jamey Sharp @ 2011-06-07 23:04 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Shawn O. Pearce, Johannes Schindelin, Jeff King, Jakub Narebski,
	Bert Wesarg, git, Josh Triplett

From: Josh Triplett <josh@joshtriplett.org>

The do_for_each_ref iteration function accepts a prefix and a trim, and
checks for the prefix on each ref before passing in that ref; it also
supports trimming off part of the ref before passing it.  However,
do_for_each_ref used trim as the length of the prefix to check, ignoring
the actual length of the prefix.  Switch to using prefixcmp, checking
the entire length of the prefix string, to properly support a trim value
different than the length of the prefix.

Several callers passed a prefix of "refs/" to filter out everything
outside of refs/, but a trim of 0 to avoid trimming off the "refs/"; the
trim of 0 meant that the filter of "refs/" no longer applied.  Change
these callers to pass an empty prefix instead, to avoid changing the
existing behavior.  Various callers count on this lack of filtering,
such as receive-pack which uses add_extra_ref to add alternates as refs
named ".have"; adding filtering would break that, causing
t5501-fetch-push-alternates.sh to fail.  That lack of filtering doesn't
currently have any other effect, since the loose ref functions can never
supply refs outside of "refs/", and packed-refs will not normally
include such refs unless manually edited.

Commit by Josh Triplett and Jamey Sharp.

Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
---
 refs.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index e3c0511..858cf92 100644
--- a/refs.c
+++ b/refs.c
@@ -584,7 +584,7 @@ int read_ref(const char *ref, unsigned char *sha1)
 static int do_one_ref(const char *base, each_ref_fn fn, int trim,
 		      int flags, void *cb_data, struct ref_list *entry)
 {
-	if (strncmp(base, entry->name, trim))
+	if (prefixcmp(entry->name, base))
 		return 0;
 
 	if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
@@ -728,12 +728,12 @@ int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
 
 int for_each_ref(each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref(NULL, "refs/", fn, 0, 0, cb_data);
+	return do_for_each_ref(NULL, "", fn, 0, 0, cb_data);
 }
 
 int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref(submodule, "refs/", fn, 0, 0, cb_data);
+	return do_for_each_ref(submodule, "", fn, 0, 0, cb_data);
 }
 
 int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
@@ -819,7 +819,7 @@ int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
 
 int for_each_rawref(each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref(NULL, "refs/", fn, 0,
+	return do_for_each_ref(NULL, "", fn, 0,
 			       DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
 }
 
-- 
1.7.5.3

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

* [PATCHv8 2/4] Add infrastructure for ref namespaces
  2011-06-07 23:04 [PATCHv8 0/4] Support ref namespaces Jamey Sharp
  2011-06-07 23:04 ` [PATCHv8 1/4] Fix prefix handling in ref iteration functions Jamey Sharp
@ 2011-06-07 23:04 ` Jamey Sharp
  2011-06-07 23:04 ` [PATCHv8 3/4] Support ref namespaces for remote repositories via upload-pack and receive-pack Jamey Sharp
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Jamey Sharp @ 2011-06-07 23:04 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Shawn O. Pearce, Johannes Schindelin, Jeff King, Jakub Narebski,
	Bert Wesarg, git, Josh Triplett

From: Josh Triplett <josh@joshtriplett.org>

Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.

Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source.  The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.

To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace.  For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/.  For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/.  You can
also specify namespaces via the --namespace option to git.

Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/.  This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar.  It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.

This adds the infrastructure for ref namespaces: handling the
GIT_NAMESPACE environment variable and --namespace option, and iterating
over refs in a namespace.  Subsequent commits use this infrastructure to
implement the user-visible support for ref namespaces.

Commit by Josh Triplett and Jamey Sharp.

Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
---
 cache.h                                |    3 ++
 contrib/completion/git-completion.bash |    1 +
 environment.c                          |   41 ++++++++++++++++++++++++++++++++
 git.c                                  |   18 ++++++++++++-
 refs.c                                 |   25 +++++++++++++++++++
 refs.h                                 |    3 ++
 6 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/cache.h b/cache.h
index e11cf6a..b256a94 100644
--- a/cache.h
+++ b/cache.h
@@ -379,6 +379,7 @@ static inline enum object_type object_type(unsigned int mode)
 }
 
 #define GIT_DIR_ENVIRONMENT "GIT_DIR"
+#define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
 #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
 #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
 #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
@@ -419,6 +420,8 @@ extern char *get_object_directory(void);
 extern char *get_index_file(void);
 extern char *get_graft_file(void);
 extern int set_git_dir(const char *path);
+extern const char *get_git_namespace(void);
+extern const char *strip_namespace(const char *namespaced_ref);
 extern const char *get_git_work_tree(void);
 extern const char *read_gitfile_gently(const char *path);
 extern void set_git_work_tree(const char *tree);
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index b36290f..b10a1ec 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2640,6 +2640,7 @@ _git ()
 			--exec-path
 			--html-path
 			--work-tree=
+			--namespace=
 			--help
 			"
 			;;
diff --git a/environment.c b/environment.c
index 94d58fd..aad274b 100644
--- a/environment.c
+++ b/environment.c
@@ -8,6 +8,7 @@
  * are.
  */
 #include "cache.h"
+#include "refs.h"
 
 char git_default_email[MAX_GITNAME];
 char git_default_name[MAX_GITNAME];
@@ -65,6 +66,9 @@ int core_preload_index = 0;
 char *git_work_tree_cfg;
 static char *work_tree;
 
+static const char *namespace;
+static size_t namespace_len;
+
 static const char *git_dir;
 static char *git_object_dir, *git_index_file, *git_graft_file;
 
@@ -86,6 +90,27 @@ const char * const local_repo_env[LOCAL_REPO_ENV_SIZE + 1] = {
 	NULL
 };
 
+static char *expand_namespace(const char *raw_namespace)
+{
+	struct strbuf buf = STRBUF_INIT;
+	struct strbuf **components, **c;
+
+	if (!raw_namespace || !*raw_namespace)
+		return xstrdup("");
+
+	strbuf_addstr(&buf, raw_namespace);
+	components = strbuf_split(&buf, '/');
+	strbuf_reset(&buf);
+	for (c = components; *c; c++)
+		if (strcmp((*c)->buf, "/") != 0)
+			strbuf_addf(&buf, "refs/namespaces/%s", (*c)->buf);
+	strbuf_list_free(components);
+	if (check_ref_format(buf.buf) != CHECK_REF_FORMAT_OK)
+		die("bad git namespace path \"%s\"", raw_namespace);
+	strbuf_addch(&buf, '/');
+	return strbuf_detach(&buf, NULL);
+}
+
 static void setup_git_env(void)
 {
 	git_dir = getenv(GIT_DIR_ENVIRONMENT);
@@ -111,6 +136,8 @@ static void setup_git_env(void)
 		git_graft_file = git_pathdup("info/grafts");
 	if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
 		read_replace_refs = 0;
+	namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
+	namespace_len = strlen(namespace);
 }
 
 int is_bare_repository(void)
@@ -131,6 +158,20 @@ const char *get_git_dir(void)
 	return git_dir;
 }
 
+const char *get_git_namespace(void)
+{
+	if (!namespace)
+		setup_git_env();
+	return namespace;
+}
+
+const char *strip_namespace(const char *namespaced_ref)
+{
+	if (prefixcmp(namespaced_ref, get_git_namespace()) != 0)
+		return NULL;
+	return namespaced_ref + namespace_len;
+}
+
 static int git_work_tree_initialized;
 
 /*
diff --git a/git.c b/git.c
index 89721d4..47d2884 100644
--- a/git.c
+++ b/git.c
@@ -7,8 +7,8 @@
 
 const char git_usage_string[] =
 	"git [--version] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
-	"           [-p|--paginate|--no-pager] [--no-replace-objects]\n"
-	"           [--bare] [--git-dir=<path>] [--work-tree=<path>]\n"
+	"           [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]\n"
+	"           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
 	"           [-c name=value] [--help]\n"
 	"           <command> [<args>]";
 
@@ -126,6 +126,20 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 			setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
 			if (envchanged)
 				*envchanged = 1;
+		} else if (!strcmp(cmd, "--namespace")) {
+			if (*argc < 2) {
+				fprintf(stderr, "No namespace given for --namespace.\n" );
+				usage(git_usage_string);
+			}
+			setenv(GIT_NAMESPACE_ENVIRONMENT, (*argv)[1], 1);
+			if (envchanged)
+				*envchanged = 1;
+			(*argv)++;
+			(*argc)--;
+		} else if (!prefixcmp(cmd, "--namespace=")) {
+			setenv(GIT_NAMESPACE_ENVIRONMENT, cmd + 12, 1);
+			if (envchanged)
+				*envchanged = 1;
 		} else if (!strcmp(cmd, "--work-tree")) {
 			if (*argc < 2) {
 				fprintf(stderr, "No directory given for --work-tree.\n" );
diff --git a/refs.c b/refs.c
index 858cf92..e83bbf8 100644
--- a/refs.c
+++ b/refs.c
@@ -782,6 +782,31 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data)
 	return do_for_each_ref(NULL, "refs/replace/", fn, 13, 0, cb_data);
 }
 
+int head_ref_namespaced(each_ref_fn fn, void *cb_data)
+{
+	struct strbuf buf = STRBUF_INIT;
+	int ret = 0;
+	unsigned char sha1[20];
+	int flag;
+
+	strbuf_addf(&buf, "%sHEAD", get_git_namespace());
+	if (resolve_ref(buf.buf, sha1, 1, &flag))
+		ret = fn(buf.buf, sha1, flag, cb_data);
+	strbuf_release(&buf);
+
+	return ret;
+}
+
+int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
+{
+	struct strbuf buf = STRBUF_INIT;
+	int ret;
+	strbuf_addf(&buf, "%srefs/", get_git_namespace());
+	ret = do_for_each_ref(NULL, buf.buf, fn, 0, 0, cb_data);
+	strbuf_release(&buf);
+	return ret;
+}
+
 int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
 	const char *prefix, void *cb_data)
 {
diff --git a/refs.h b/refs.h
index 5e7a9a5..9a5c9e0 100644
--- a/refs.h
+++ b/refs.h
@@ -36,6 +36,9 @@ extern int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, voi
 extern int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data);
 extern int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data);
 
+extern int head_ref_namespaced(each_ref_fn fn, void *cb_data);
+extern int for_each_namespaced_ref(each_ref_fn fn, void *cb_data);
+
 static inline const char *has_glob_specials(const char *pattern)
 {
 	return strpbrk(pattern, "?*[");
-- 
1.7.5.3

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

* [PATCHv8 3/4] Support ref namespaces for remote repositories via upload-pack and receive-pack
  2011-06-07 23:04 [PATCHv8 0/4] Support ref namespaces Jamey Sharp
  2011-06-07 23:04 ` [PATCHv8 1/4] Fix prefix handling in ref iteration functions Jamey Sharp
  2011-06-07 23:04 ` [PATCHv8 2/4] Add infrastructure for ref namespaces Jamey Sharp
@ 2011-06-07 23:04 ` Jamey Sharp
  2011-06-07 23:04 ` [PATCHv8 4/4] Add documentation for ref namespaces Jamey Sharp
  2011-06-15 11:18 ` Painless namespaces design Jiang Xin
  4 siblings, 0 replies; 10+ messages in thread
From: Jamey Sharp @ 2011-06-07 23:04 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Shawn O. Pearce, Johannes Schindelin, Jeff King, Jakub Narebski,
	Bert Wesarg, git, Josh Triplett

From: Josh Triplett <josh@joshtriplett.org>

Change upload-pack and receive-pack to use the namespace-prefixed refs
when working with the repository, and use the unprefixed refs when
talking to the client, maintaining the masquerade.  This allows
clone, pull, fetch, and push to work with a suitably configured
GIT_NAMESPACE.

With appropriate configuration, this also allows http-backend to expose
namespaces as multiple repositories with different paths.  This only
requires setting GIT_NAMESPACE, which http-backend passes through to
upload-pack and receive-pack.

Commit by Josh Triplett and Jamey Sharp.

Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
---
 builtin/receive-pack.c |   34 ++++++++++++++++++++++++++++------
 upload-pack.c          |   15 ++++++++-------
 2 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index e1a687a..54dd5d4 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -120,9 +120,14 @@ static int show_ref(const char *path, const unsigned char *sha1, int flag, void
 	return 0;
 }
 
+static int show_ref_cb(const char *path, const unsigned char *sha1, int flag, void *cb_data)
+{
+	return show_ref(strip_namespace(path), sha1, flag, cb_data);
+}
+
 static void write_head_info(void)
 {
-	for_each_ref(show_ref, NULL);
+	for_each_namespaced_ref(show_ref_cb, NULL);
 	if (!sent_capabilities)
 		show_ref("capabilities^{}", null_sha1, 0, NULL);
 
@@ -333,6 +338,8 @@ static void refuse_unconfigured_deny_delete_current(void)
 static const char *update(struct command *cmd)
 {
 	const char *name = cmd->ref_name;
+	struct strbuf namespaced_name_buf = STRBUF_INIT;
+	const char *namespaced_name;
 	unsigned char *old_sha1 = cmd->old_sha1;
 	unsigned char *new_sha1 = cmd->new_sha1;
 	struct ref_lock *lock;
@@ -343,7 +350,10 @@ static const char *update(struct command *cmd)
 		return "funny refname";
 	}
 
-	if (is_ref_checked_out(name)) {
+	strbuf_addf(&namespaced_name_buf, "%s%s", get_git_namespace(), name);
+	namespaced_name = strbuf_detach(&namespaced_name_buf, NULL);
+
+	if (is_ref_checked_out(namespaced_name)) {
 		switch (deny_current_branch) {
 		case DENY_IGNORE:
 			break;
@@ -371,7 +381,7 @@ static const char *update(struct command *cmd)
 			return "deletion prohibited";
 		}
 
-		if (!strcmp(name, head_name)) {
+		if (!strcmp(namespaced_name, head_name)) {
 			switch (deny_delete_current) {
 			case DENY_IGNORE:
 				break;
@@ -427,14 +437,14 @@ static const char *update(struct command *cmd)
 			rp_warning("Allowing deletion of corrupt ref.");
 			old_sha1 = NULL;
 		}
-		if (delete_ref(name, old_sha1, 0)) {
+		if (delete_ref(namespaced_name, old_sha1, 0)) {
 			rp_error("failed to delete %s", name);
 			return "failed to delete";
 		}
 		return NULL; /* good */
 	}
 	else {
-		lock = lock_any_ref_for_update(name, old_sha1, 0);
+		lock = lock_any_ref_for_update(namespaced_name, old_sha1, 0);
 		if (!lock) {
 			rp_error("failed to lock %s", name);
 			return "failed to lock";
@@ -491,17 +501,29 @@ static void run_update_post_hook(struct command *commands)
 
 static void check_aliased_update(struct command *cmd, struct string_list *list)
 {
+	struct strbuf buf = STRBUF_INIT;
+	const char *dst_name;
 	struct string_list_item *item;
 	struct command *dst_cmd;
 	unsigned char sha1[20];
 	char cmd_oldh[41], cmd_newh[41], dst_oldh[41], dst_newh[41];
 	int flag;
 
-	const char *dst_name = resolve_ref(cmd->ref_name, sha1, 0, &flag);
+	strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
+	dst_name = resolve_ref(buf.buf, sha1, 0, &flag);
+	strbuf_release(&buf);
 
 	if (!(flag & REF_ISSYMREF))
 		return;
 
+	dst_name = strip_namespace(dst_name);
+	if (!dst_name) {
+		rp_error("refusing update to broken symref '%s'", cmd->ref_name);
+		cmd->skip_update = 1;
+		cmd->error_string = "broken symref";
+		return;
+	}
+
 	if ((item = string_list_lookup(list, dst_name)) == NULL)
 		return;
 
diff --git a/upload-pack.c b/upload-pack.c
index ce5cbbe..267e5b1 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -641,16 +641,17 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 		" side-band-64k ofs-delta shallow no-progress"
 		" include-tag multi_ack_detailed";
 	struct object *o = parse_object(sha1);
+	const char *refname_nons = strip_namespace(refname);
 
 	if (!o)
 		die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
 
 	if (capabilities)
-		packet_write(1, "%s %s%c%s%s\n", sha1_to_hex(sha1), refname,
+		packet_write(1, "%s %s%c%s%s\n", sha1_to_hex(sha1), refname_nons,
 			     0, capabilities,
 			     stateless_rpc ? " no-done" : "");
 	else
-		packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname);
+		packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname_nons);
 	capabilities = NULL;
 	if (!(o->flags & OUR_REF)) {
 		o->flags |= OUR_REF;
@@ -659,7 +660,7 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 	if (o->type == OBJ_TAG) {
 		o = deref_tag(o, refname, 0);
 		if (o)
-			packet_write(1, "%s %s^{}\n", sha1_to_hex(o->sha1), refname);
+			packet_write(1, "%s %s^{}\n", sha1_to_hex(o->sha1), refname_nons);
 	}
 	return 0;
 }
@@ -680,12 +681,12 @@ static void upload_pack(void)
 {
 	if (advertise_refs || !stateless_rpc) {
 		reset_timeout();
-		head_ref(send_ref, NULL);
-		for_each_ref(send_ref, NULL);
+		head_ref_namespaced(send_ref, NULL);
+		for_each_namespaced_ref(send_ref, NULL);
 		packet_flush(1);
 	} else {
-		head_ref(mark_our_ref, NULL);
-		for_each_ref(mark_our_ref, NULL);
+		head_ref_namespaced(mark_our_ref, NULL);
+		for_each_namespaced_ref(mark_our_ref, NULL);
 	}
 	if (advertise_refs)
 		return;
-- 
1.7.5.3

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

* [PATCHv8 4/4] Add documentation for ref namespaces
  2011-06-07 23:04 [PATCHv8 0/4] Support ref namespaces Jamey Sharp
                   ` (2 preceding siblings ...)
  2011-06-07 23:04 ` [PATCHv8 3/4] Support ref namespaces for remote repositories via upload-pack and receive-pack Jamey Sharp
@ 2011-06-07 23:04 ` Jamey Sharp
  2011-06-08 15:19   ` Marc Branchaud
  2011-06-15 11:18 ` Painless namespaces design Jiang Xin
  4 siblings, 1 reply; 10+ messages in thread
From: Jamey Sharp @ 2011-06-07 23:04 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Shawn O. Pearce, Johannes Schindelin, Jeff King, Jakub Narebski,
	Bert Wesarg, git, Josh Triplett

From: Josh Triplett <josh@joshtriplett.org>

Document the namespace mechanism in a new gitnamespaces(7) page.
Reference it from receive-pack and upload-pack.

Document the new --namespace option and GIT_NAMESPACE environment
variable in git(1), and reference gitnamespaces(7).

Add a sample Apache configuration to http-backend(1) to support
namespaced repositories, and reference gitnamespaces(7).

Commit by Josh Triplett and Jamey Sharp.

Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
---
 Documentation/Makefile                 |    2 +-
 Documentation/git-http-backend.txt     |    8 +++
 Documentation/git-receive-pack.txt     |    2 +-
 Documentation/git-upload-pack.txt      |    4 ++
 Documentation/git.txt                  |   13 +++++-
 Documentation/gitnamespaces.txt        |   75 ++++++++++++++++++++++++++++++++
 contrib/completion/git-completion.bash |    2 +-
 7 files changed, 101 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/gitnamespaces.txt

diff --git a/Documentation/Makefile b/Documentation/Makefile
index 36989b7..2004fbe 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -6,7 +6,7 @@ MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \
 	gitrepository-layout.txt
 MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \
 	gitcvs-migration.txt gitcore-tutorial.txt gitglossary.txt \
-	gitdiffcore.txt gitrevisions.txt gitworkflows.txt
+	gitdiffcore.txt gitnamespaces.txt gitrevisions.txt gitworkflows.txt
 
 MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)
 MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT))
diff --git a/Documentation/git-http-backend.txt b/Documentation/git-http-backend.txt
index 277d9e1..f4e0741 100644
--- a/Documentation/git-http-backend.txt
+++ b/Documentation/git-http-backend.txt
@@ -119,6 +119,14 @@ ScriptAliasMatch \
 
 ScriptAlias /git/ /var/www/cgi-bin/gitweb.cgi/
 ----------------------------------------------------------------
++
+To serve multiple repositories from different linkgit:gitnamespaces[7] in a
+single repository:
++
+----------------------------------------------------------------
+SetEnvIf Request_URI "^/git/([^/]*)" GIT_NAMESPACE=$1
+ScriptAliasMatch ^/git/[^/]*(.*) /usr/libexec/git-core/git-http-backend/storage.git$1
+----------------------------------------------------------------
 
 Accelerated static Apache 2.x::
 	Similar to the above, but Apache can be used to return static
diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
index f34e0ae..3534ba0 100644
--- a/Documentation/git-receive-pack.txt
+++ b/Documentation/git-receive-pack.txt
@@ -149,7 +149,7 @@ if the repository is packed and is served via a dumb transport.
 
 SEE ALSO
 --------
-linkgit:git-send-pack[1]
+linkgit:git-send-pack[1], linkgit:gitnamespaces[7]
 
 GIT
 ---
diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt
index 4c0ca9d..61a9a04 100644
--- a/Documentation/git-upload-pack.txt
+++ b/Documentation/git-upload-pack.txt
@@ -33,6 +33,10 @@ OPTIONS
 <directory>::
 	The repository to sync from.
 
+SEE ALSO
+--------
+linkgit:gitnamespaces[7]
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 5c45446..4cbf741 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -10,8 +10,8 @@ SYNOPSIS
 --------
 [verse]
 'git' [--version] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
-    [-p|--paginate|--no-pager] [--no-replace-objects]
-    [--bare] [--git-dir=<path>] [--work-tree=<path>]
+    [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
+    [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
     [-c <name>=<value>]
     [--help] <command> [<args>]
 
@@ -325,6 +325,11 @@ help ...`.
 	variable (see core.worktree in linkgit:git-config[1] for a
 	more detailed discussion).
 
+--namespace=<path>::
+	Set the git namespace.  See linkgit:gitnamespaces[7] for more
+	details.  Equivalent to setting the `GIT_NAMESPACE` environment
+	variable.
+
 --bare::
 	Treat the repository as a bare repository.  If GIT_DIR
 	environment is not set, it is set to the current working
@@ -589,6 +594,10 @@ git so take care if using Cogito etc.
 	This can also be controlled by the '--work-tree' command line
 	option and the core.worktree configuration variable.
 
+'GIT_NAMESPACE'::
+	Set the git namespace; see linkgit:gitnamespaces[7] for details.
+	The '--namespace' command-line option also sets this value.
+
 'GIT_CEILING_DIRECTORIES'::
 	This should be a colon-separated list of absolute paths.
 	If set, it is a list of directories that git should not chdir
diff --git a/Documentation/gitnamespaces.txt b/Documentation/gitnamespaces.txt
new file mode 100644
index 0000000..ed8924e
--- /dev/null
+++ b/Documentation/gitnamespaces.txt
@@ -0,0 +1,75 @@
+gitnamespaces(7)
+================
+
+NAME
+----
+gitnamespaces - Git namespaces
+
+DESCRIPTION
+-----------
+
+Git supports dividing the refs of a single repository into multiple
+namespaces, each of which has its own branches, tags, and HEAD.  Git can
+expose each namespace as an independent repository to pull from and push
+to, while sharing the object store, and exposing all the refs to
+operations such as linkgit:git-gc[1].
+
+Storing multiple repositories as namespaces of a single repository
+avoids storing duplicate copies of the same objects, such as when
+storing multiple branches of the same source.  The alternates mechanism
+provides similar support for avoiding duplicates, but alternates do not
+prevent duplication between new objects added to the repositories
+without ongoing maintenance, while namespaces do.
+
+To specify a namespace, set the `GIT_NAMESPACE` environment variable to
+the namespace.  For each ref namespace, git stores the corresponding
+refs in a directory under `refs/namespaces/`.  For example,
+`GIT_NAMESPACE=foo` will store refs under `refs/namespaces/foo/`.  You
+can also specify namespaces via the `--namespace` option to
+linkgit:git[1].
+
+Note that namespaces which include a `/` will expand to a hierarchy of
+namespaces; for example, `GIT_NAMESPACE=foo/bar` will store refs under
+`refs/namespaces/foo/refs/namespaces/bar/`.  This makes paths in
+`GIT_NAMESPACE` behave hierarchically, so that cloning with
+`GIT_NAMESPACE=foo/bar` produces the same result as cloning with
+`GIT_NAMESPACE=foo` and cloning from that repo with `GIT_NAMESPACE=bar`.  It
+also avoids ambiguity with strange namespace paths such as `foo/refs/heads/`,
+which could otherwise generate directory/file conflicts within the `refs`
+directory.
+
+linkgit:git-upload-pack[1] and linkgit:git-receive-pack[1] rewrite the
+names of refs as specified by `GIT_NAMESPACE`.  git-upload-pack and
+git-receive-pack will ignore all references outside the specified
+namespace.
+
+The smart HTTP server, linkgit:git-http-backend[1], will pass
+GIT_NAMESPACE through to the backend programs; see
+linkgit:git-http-backend[1] for sample configuration to expose
+repository namespaces as repositories.
+
+For a simple local test, you can use linkgit:git-remote-ext[1]:
+
+----------
+git clone ext::'git --namespace=foo %s /tmp/prefixed.git'
+----------
+
+SECURITY
+--------
+
+Anyone with access to any namespace within a repository can potentially
+access objects from any other namespace stored in the same repository.
+You can't directly say "give me object ABCD" if you don't have a ref to
+it, but you can do some other sneaky things like:
+
+. Claiming to push ABCD, at which point the server will optimize out the
+  need for you to actually send it. Now you have a ref to ABCD and can
+  fetch it (claiming not to have it, of course).
+
+. Requesting other refs, claiming that you have ABCD, at which point the
+  server may generate deltas against ABCD.
+
+None of this causes a problem if you only host public repositories, or
+if everyone who may read one namespace may also read everything in every
+other namespace (for instance, if everyone in an organization has read
+permission to every repository).
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index b10a1ec..ec1c986 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1469,7 +1469,7 @@ _git_help ()
 	__gitcomp "$__git_all_commands $(__git_aliases)
 		attributes cli core-tutorial cvs-migration
 		diffcore gitk glossary hooks ignore modules
-		repository-layout tutorial tutorial-2
+		namespaces repository-layout tutorial tutorial-2
 		workflows
 		"
 }
-- 
1.7.5.3

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

* Re: [PATCHv8 1/4] Fix prefix handling in ref iteration functions
  2011-06-07 23:04 ` [PATCHv8 1/4] Fix prefix handling in ref iteration functions Jamey Sharp
@ 2011-06-08  0:17   ` Junio C Hamano
  2011-06-08  1:40     ` Josh Triplett
  0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2011-06-08  0:17 UTC (permalink / raw)
  To: Jamey Sharp
  Cc: Shawn O. Pearce, Johannes Schindelin, Jeff King, Jakub Narebski,
	Bert Wesarg, git, Josh Triplett

This round does fix the ".have" issues, but with the --namespace patch
later in the series, it seems to break the same test, by filtering .have
entries with "refs/" prefix.

> Commit by Josh Triplett and Jamey Sharp.

Didn't I ask you to remove this?

Please pick which one of you would be the primary contact for each patch.
I know you said you two did these commits sitting side-by-side, but the
thing is, we simply don't care, and "git shortlog" and the author list you
can see at http://www.git-scm.com/about don't, either.

It is somewhat irritating having to re-edit the log message (not just this
part, but what have been queued were retitled, reflowed and reworded to
match the style of other commits in the project better) over and over
again.

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

* Re: [PATCHv8 1/4] Fix prefix handling in ref iteration functions
  2011-06-08  0:17   ` Junio C Hamano
@ 2011-06-08  1:40     ` Josh Triplett
  0 siblings, 0 replies; 10+ messages in thread
From: Josh Triplett @ 2011-06-08  1:40 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Jamey Sharp, Shawn O. Pearce, Johannes Schindelin, Jeff King,
	Jakub Narebski, Bert Wesarg, git

On Tue, Jun 07, 2011 at 05:17:56PM -0700, Junio C Hamano wrote:
> This round does fix the ".have" issues, but with the --namespace patch
> later in the series, it seems to break the same test, by filtering .have
> entries with "refs/" prefix.

Ouch, missed that; good catch.  We'll fix that in the next round of the
patch series.

> > Commit by Josh Triplett and Jamey Sharp.
> 
> Didn't I ask you to remove this?

You did ask, we responded (with a citation to a specific recommendation
from the Git list saying to include such a note), and you hadn't said
anything further about it until now.  If you insist that we remove it,
fine, we'll remove it.

> It is somewhat irritating having to re-edit the log message (not just this
> part, but what have been queued were retitled, reflowed and reworded to
> match the style of other commits in the project better) over and over
> again.

We attempted to follow the usual commit message conventions, and none of
the feedback we received mentioned anything about any other desired
changes.  What changes would you like us to make?

- Josh Triplett

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

* Re: [PATCHv8 4/4] Add documentation for ref namespaces
  2011-06-07 23:04 ` [PATCHv8 4/4] Add documentation for ref namespaces Jamey Sharp
@ 2011-06-08 15:19   ` Marc Branchaud
  0 siblings, 0 replies; 10+ messages in thread
From: Marc Branchaud @ 2011-06-08 15:19 UTC (permalink / raw)
  To: Jamey Sharp
  Cc: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Jeff King,
	Jakub Narebski, Bert Wesarg, git, Josh Triplett

On 11-06-07 07:04 PM, Jamey Sharp wrote:
> From: Josh Triplett<josh@joshtriplett.org>
>
> Document the namespace mechanism in a new gitnamespaces(7) page.
> Reference it from receive-pack and upload-pack.
>
> Document the new --namespace option and GIT_NAMESPACE environment
> variable in git(1), and reference gitnamespaces(7).
>
> Add a sample Apache configuration to http-backend(1) to support
> namespaced repositories, and reference gitnamespaces(7).
>
> Commit by Josh Triplett and Jamey Sharp.
>
> Signed-off-by: Josh Triplett<josh@joshtriplett.org>
> Signed-off-by: Jamey Sharp<jamey@minilop.net>
> ---
>   Documentation/Makefile                 |    2 +-
>   Documentation/git-http-backend.txt     |    8 +++
>   Documentation/git-receive-pack.txt     |    2 +-
>   Documentation/git-upload-pack.txt      |    4 ++
>   Documentation/git.txt                  |   13 +++++-
>   Documentation/gitnamespaces.txt        |   75 ++++++++++++++++++++++++++++++++
>   contrib/completion/git-completion.bash |    2 +-
>   7 files changed, 101 insertions(+), 5 deletions(-)
>   create mode 100644 Documentation/gitnamespaces.txt
>
> diff --git a/Documentation/Makefile b/Documentation/Makefile
> index 36989b7..2004fbe 100644
> --- a/Documentation/Makefile
> +++ b/Documentation/Makefile
> @@ -6,7 +6,7 @@ MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \
>   	gitrepository-layout.txt
>   MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \
>   	gitcvs-migration.txt gitcore-tutorial.txt gitglossary.txt \
> -	gitdiffcore.txt gitrevisions.txt gitworkflows.txt
> +	gitdiffcore.txt gitnamespaces.txt gitrevisions.txt gitworkflows.txt
>
>   MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)
>   MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT))
> diff --git a/Documentation/git-http-backend.txt b/Documentation/git-http-backend.txt
> index 277d9e1..f4e0741 100644
> --- a/Documentation/git-http-backend.txt
> +++ b/Documentation/git-http-backend.txt
> @@ -119,6 +119,14 @@ ScriptAliasMatch \
>
>   ScriptAlias /git/ /var/www/cgi-bin/gitweb.cgi/
>   ----------------------------------------------------------------
> ++
> +To serve multiple repositories from different linkgit:gitnamespaces[7] in a
> +single repository:
> ++
> +----------------------------------------------------------------
> +SetEnvIf Request_URI "^/git/([^/]*)" GIT_NAMESPACE=$1
> +ScriptAliasMatch ^/git/[^/]*(.*) /usr/libexec/git-core/git-http-backend/storage.git$1
> +----------------------------------------------------------------
>
>   Accelerated static Apache 2.x::
>   	Similar to the above, but Apache can be used to return static
> diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
> index f34e0ae..3534ba0 100644
> --- a/Documentation/git-receive-pack.txt
> +++ b/Documentation/git-receive-pack.txt
> @@ -149,7 +149,7 @@ if the repository is packed and is served via a dumb transport.
>
>   SEE ALSO
>   --------
> -linkgit:git-send-pack[1]
> +linkgit:git-send-pack[1], linkgit:gitnamespaces[7]
>
>   GIT
>   ---
> diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt
> index 4c0ca9d..61a9a04 100644
> --- a/Documentation/git-upload-pack.txt
> +++ b/Documentation/git-upload-pack.txt
> @@ -33,6 +33,10 @@ OPTIONS
>   <directory>::
>   	The repository to sync from.
>
> +SEE ALSO
> +--------
> +linkgit:gitnamespaces[7]
> +
>   GIT
>   ---
>   Part of the linkgit:git[1] suite
> diff --git a/Documentation/git.txt b/Documentation/git.txt
> index 5c45446..4cbf741 100644
> --- a/Documentation/git.txt
> +++ b/Documentation/git.txt
> @@ -10,8 +10,8 @@ SYNOPSIS
>   --------
>   [verse]
>   'git' [--version] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
> -    [-p|--paginate|--no-pager] [--no-replace-objects]
> -    [--bare] [--git-dir=<path>] [--work-tree=<path>]
> +    [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
> +    [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
>       [-c<name>=<value>]
>       [--help]<command>  [<args>]
>
> @@ -325,6 +325,11 @@ help ...`.
>   	variable (see core.worktree in linkgit:git-config[1] for a
>   	more detailed discussion).
>
> +--namespace=<path>::
> +	Set the git namespace.  See linkgit:gitnamespaces[7] for more
> +	details.  Equivalent to setting the `GIT_NAMESPACE` environment
> +	variable.
> +
>   --bare::
>   	Treat the repository as a bare repository.  If GIT_DIR
>   	environment is not set, it is set to the current working
> @@ -589,6 +594,10 @@ git so take care if using Cogito etc.
>   	This can also be controlled by the '--work-tree' command line
>   	option and the core.worktree configuration variable.
>
> +'GIT_NAMESPACE'::
> +	Set the git namespace; see linkgit:gitnamespaces[7] for details.
> +	The '--namespace' command-line option also sets this value.
> +

Thanks for this work!

Does --namespace override GIT_NAMESPACE or extend it in some way?

I also have a question about how to use this feature.  We currently have 
a central "Main.git" repo where people put their finished work. 
Developers clone this repo with, say, "git clone 
ssh://host/git/Main.git".  Each developer also has a "personal" repo 
where they can publish work-in-progress branches to share without 
creating churn in Main.git.  Folks add personal repos as remotes in 
their Main.git clone, e.g. "git remote add Marc 
git://host/git/personal/marcnarc/Main.git".

This is a fairly clean model:  The personal repos on the central host 
are just local clones of the Main.git repo, and fetching from a personal 
repo only transmits unique refs.  But setting it up was a bit involved, 
and it looks like namespaces would make things even cleaner on the 
central host.

But I think our users will get tripped up by the remote-ext syntax.  The 
above "remote add" command is reasonably straightforward, but with 
namespaces it would be

	git remote add Marc ext::"git --namespace=personal/marcnarc %s 
git://host/git/Main.git"

I can see a lot of opportunity for confusion as users try to type that in.

So my question is, is there any way we could adopt namespaces without 
teaching our users about remote-ext?  Ideally they would just use the 
same URLs they already use, or maybe a slight variation thereof (e.g. 
git://host/git/Main.git/personal/marcnarc).

		M.

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

* Painless namespaces design
  2011-06-07 23:04 [PATCHv8 0/4] Support ref namespaces Jamey Sharp
                   ` (3 preceding siblings ...)
  2011-06-07 23:04 ` [PATCHv8 4/4] Add documentation for ref namespaces Jamey Sharp
@ 2011-06-15 11:18 ` Jiang Xin
  2011-06-15 14:00   ` Shawn Pearce
  4 siblings, 1 reply; 10+ messages in thread
From: Jiang Xin @ 2011-06-15 11:18 UTC (permalink / raw)
  To: Jamey Sharp
  Cc: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Jeff King,
	Jakub Narebski, Bert Wesarg, git

I like the idea of new namespaces feature from Josh Triplett, Jamey Sharp and others.
I think it is better to pass namespace through remote.remote-name.namespace variables,
not through GIT_NAMESPACE environment.

Host1 has a bare repository with multiple namespaces: foo, bar, and foo/baz.

* master branch of default namespace : refs/heads/master
* master branch of namespace foo is : refs/namespaces/foo/refs/heads/master
* master branch of namesapce bar is : refs/namespaces/bar/refs/heads/master
* master branch of namesapce foo/baz is : refs/namespaces/foo/refs/namespaces/baz/refs/heads/master

UserA clone namespace foo from Host1:

    $ git clone --namespace foo ssh://Host1/path/to/project.git

the default remote.origin section in  .git/config in userA's working directory:

    [remote "origin"]
        namespace = foo
        fetch = +refs/heads/*:refs/remotes/origin/*
        url = ssh://Host1/path/to/project.git

When UserA runs `git fetch`, it's just like

    git fetch origin refs/namespaces/foo/refs/heads/*:refs/remotes/origin/*

When UserA runs `git push`, it's just like

    git push origin refs/heads/master:refs/namespaces/foo/refs/heads/master

These can be done on the client side, so I think there is no necessary to hack
git-receive-pack and git-upload-pack.

Refs of namespace foo/baz not cloned by UserA by default, so name space baz
does not exists in UserA's new cloned repository.

If UserA wants to watch some commits on other namespace in project.git in Host1,
UserA can do this:

    $ git remote add --namespace bar  host1bar  ssh://Host1/path/to/project.git

Then there is a new remote section in .git/config file in UserA's working directory.

    [remote "host1bar"]
        namespace = bar
        fetch = +refs/heads/*:refs/remotes/host1bar/*
        url = ssh://Host1/path/to/project.git

When UserA runs git fetch host1bar, then:

    refs/namespaces/bar/refs/heads/master [remote] => refs/remotes/host1bar/master [local]

When UserA execute `git ls-remote host1bar`, only show references under  refs/namespaces/bar/refs/
of remote Host1.

To mirror all namespaces of project.git in Host1, run this command:

    git clone --mirror ssh://Host1/path/to/project.git


I believe this design is painless for both git server and client side tools.

Topgit is one of my daily use tools. Without namespaces feature, I have to create new repositories
to track develop status. It is because the develop status of a topgit controlled repository
is not through one certain branch, but through all the topic branches (refs/heads/t/*) and their
base branches (refs/top-bases/t/*).

I'd like to see namespaces feature becomes one part of git.


于 11-6-8 上午7:04, Jamey Sharp 写道:
> This series adds support for dividing the refs of a single repository
> into multiple namespaces, each of which can have its own branches, tags,
> and HEAD. Git can expose each namespace as an independent repository to
> pull from and push to, while sharing the object store, and exposing all
> the refs to operations such as git-gc.
> 

-- 
Jiang Xin

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

* Re: Painless namespaces design
  2011-06-15 11:18 ` Painless namespaces design Jiang Xin
@ 2011-06-15 14:00   ` Shawn Pearce
  0 siblings, 0 replies; 10+ messages in thread
From: Shawn Pearce @ 2011-06-15 14:00 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Jamey Sharp, Junio C Hamano, Johannes Schindelin, Jeff King,
	Jakub Narebski, Bert Wesarg, git

2011/6/15 Jiang Xin <worldhello.net@gmail.com>:
> I like the idea of new namespaces feature from Josh Triplett, Jamey Sharp and others.
> I think it is better to pass namespace through remote.remote-name.namespace variables,
> not through GIT_NAMESPACE environment.
...
>    [remote "origin"]
>        namespace = foo
>        fetch = +refs/heads/*:refs/remotes/origin/*
>        url = ssh://Host1/path/to/project.git
>
> When UserA runs `git fetch`, it's just like
>
>    git fetch origin refs/namespaces/foo/refs/heads/*:refs/remotes/origin/*

This is less than ideal. Part of the rationale for the GIT_NAMESPACE
environment variable is to allow the server to restrict the namespace
and only show that specific slice of the repository's refs to the
client. It allows a server administrator to put several logical
repositories into a single repository, and have clients be oblivious
to this fact.

-- 
Shawn.

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

end of thread, other threads:[~2011-06-15 14:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-07 23:04 [PATCHv8 0/4] Support ref namespaces Jamey Sharp
2011-06-07 23:04 ` [PATCHv8 1/4] Fix prefix handling in ref iteration functions Jamey Sharp
2011-06-08  0:17   ` Junio C Hamano
2011-06-08  1:40     ` Josh Triplett
2011-06-07 23:04 ` [PATCHv8 2/4] Add infrastructure for ref namespaces Jamey Sharp
2011-06-07 23:04 ` [PATCHv8 3/4] Support ref namespaces for remote repositories via upload-pack and receive-pack Jamey Sharp
2011-06-07 23:04 ` [PATCHv8 4/4] Add documentation for ref namespaces Jamey Sharp
2011-06-08 15:19   ` Marc Branchaud
2011-06-15 11:18 ` Painless namespaces design Jiang Xin
2011-06-15 14:00   ` Shawn Pearce

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.