From c578f51d52fe75e71d75566c2c216af989b65e6e Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Wed, 18 Nov 2009 02:42:25 +0100 Subject: Add a config option for remotes to specify a foreign vcs If this is set, the url is not required, and the transport always uses a helper named "git-remote-". It is a separate configuration option in order to allow a sensible configuration for foreign systems which either have no meaningful urls for repositories or which require urls that do not specify the system used by the repository at that location. However, this only affects how the name of the helper is determined, not anything about the interaction with the helper, and the contruction is such that, if the foreign scm does happen to use a co-named url method, a url with that method may be used directly. Signed-off-by: Daniel Barkalow Signed-off-by: Sverre Rabbelier Signed-off-by: Junio C Hamano --- remote.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'remote.h') diff --git a/remote.h b/remote.h index 5db842087d..ac0ce2ff9c 100644 --- a/remote.h +++ b/remote.h @@ -11,6 +11,8 @@ struct remote { const char *name; int origin; + const char *foreign_vcs; + const char **url; int url_nr; int url_alloc; -- cgit v1.3-5-g9baa From 72ff894308d4f6eb9f081167377857f7a3268bca Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Wed, 18 Nov 2009 02:42:28 +0100 Subject: Allow helper to map private ref names into normal names This allows a helper to say that, when it handles "import refs/heads/topic", the script it outputs will actually write to refs/svn/origin/branches/topic; therefore, transport-helper should read it from the latter location after git-fast-import completes. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- Documentation/git-remote-helpers.txt | 16 +++++++++++++++- remote.c | 27 +++++++++++++++++++++++++++ remote.h | 5 +++++ transport-helper.c | 34 +++++++++++++++++++++++++++++++++- 4 files changed, 80 insertions(+), 2 deletions(-) (limited to 'remote.h') diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt index e9aa67e757..d6c5268d38 100644 --- a/Documentation/git-remote-helpers.txt +++ b/Documentation/git-remote-helpers.txt @@ -46,7 +46,11 @@ Supported if the helper has the "fetch" capability. 'import' :: Produces a fast-import stream which imports the current value of the named ref. It may additionally import other refs as - needed to construct the history efficiently. + needed to construct the history efficiently. The script writes + to a helper-specific private namespace. The value of the named + ref should be written to a location in this namespace derived + by applying the refspecs from the "refspec" capability to the + name of the ref. + Supported if the helper has the "import" capability. @@ -67,6 +71,16 @@ CAPABILITIES 'import':: This helper supports the 'import' command. +'refspec' 'spec':: + When using the import command, expect the source ref to have + been written to the destination ref. The earliest applicable + refspec takes precedence. For example + "refs/heads/*:refs/svn/origin/branches/*" means that, after an + "import refs/heads/name", the script has written to + refs/svn/origin/branches/name. If this capability is used at + all, it must cover all refs reported by the list command; if + it is not used, it is effectively "*:*" + REF LIST ATTRIBUTES ------------------- diff --git a/remote.c b/remote.c index 09bb79c22c..1f7870d107 100644 --- a/remote.c +++ b/remote.c @@ -673,6 +673,16 @@ static struct refspec *parse_push_refspec(int nr_refspec, const char **refspec) return parse_refspec_internal(nr_refspec, refspec, 0, 0); } +void free_refspec(int nr_refspec, struct refspec *refspec) +{ + int i; + for (i = 0; i < nr_refspec; i++) { + free(refspec[i].src); + free(refspec[i].dst); + } + free(refspec); +} + static int valid_remote_nick(const char *name) { if (!name[0] || is_dot_or_dotdot(name)) @@ -811,6 +821,23 @@ static int match_name_with_pattern(const char *key, const char *name, return ret; } +char *apply_refspecs(struct refspec *refspecs, int nr_refspec, + const char *name) +{ + int i; + char *ret = NULL; + for (i = 0; i < nr_refspec; i++) { + struct refspec *refspec = refspecs + i; + if (refspec->pattern) { + if (match_name_with_pattern(refspec->src, name, + refspec->dst, &ret)) + return ret; + } else if (!strcmp(refspec->src, name)) + return strdup(refspec->dst); + } + return NULL; +} + int remote_find_tracking(struct remote *remote, struct refspec *refspec) { int find_src = refspec->src == NULL; diff --git a/remote.h b/remote.h index ac0ce2ff9c..cdc3b5b159 100644 --- a/remote.h +++ b/remote.h @@ -91,6 +91,11 @@ void ref_remove_duplicates(struct ref *ref_map); int valid_fetch_refspec(const char *refspec); struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec); +void free_refspec(int nr_refspec, struct refspec *refspec); + +char *apply_refspecs(struct refspec *refspecs, int nr_refspec, + const char *name); + int match_refs(struct ref *src, struct ref **dst, int nr_refspec, const char **refspec, int all); diff --git a/transport-helper.c b/transport-helper.c index 82caaaead6..da8185a981 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -5,6 +5,7 @@ #include "commit.h" #include "diff.h" #include "revision.h" +#include "remote.h" struct helper_data { @@ -12,6 +13,9 @@ struct helper_data struct child_process *helper; unsigned fetch : 1; unsigned import : 1; + /* These go from remote name (as in "list") to private name */ + struct refspec *refspecs; + int refspec_nr; }; static struct child_process *get_helper(struct transport *transport) @@ -20,6 +24,9 @@ static struct child_process *get_helper(struct transport *transport) struct strbuf buf = STRBUF_INIT; struct child_process *helper; FILE *file; + const char **refspecs = NULL; + int refspec_nr = 0; + int refspec_alloc = 0; if (data->helper) return data->helper; @@ -51,6 +58,21 @@ static struct child_process *get_helper(struct transport *transport) data->fetch = 1; if (!strcmp(buf.buf, "import")) data->import = 1; + if (!data->refspecs && !prefixcmp(buf.buf, "refspec ")) { + ALLOC_GROW(refspecs, + refspec_nr + 1, + refspec_alloc); + refspecs[refspec_nr++] = strdup(buf.buf + strlen("refspec ")); + } + } + if (refspecs) { + int i; + data->refspec_nr = refspec_nr; + data->refspecs = parse_fetch_refspec(refspec_nr, refspecs); + for (i = 0; i < refspec_nr; i++) { + free((char *)refspecs[i]); + } + free(refspecs); } return data->helper; } @@ -72,6 +94,9 @@ static int disconnect_helper(struct transport *transport) static int release_helper(struct transport *transport) { + struct helper_data *data = transport->data; + free_refspec(data->refspec_nr, data->refspecs); + data->refspecs = NULL; disconnect_helper(transport); free(transport->data); return 0; @@ -119,6 +144,7 @@ static int fetch_with_import(struct transport *transport, { struct child_process fastimport; struct child_process *helper = get_helper(transport); + struct helper_data *data = transport->data; int i; struct ref *posn; struct strbuf buf = STRBUF_INIT; @@ -139,10 +165,16 @@ static int fetch_with_import(struct transport *transport, finish_command(&fastimport); for (i = 0; i < nr_heads; i++) { + char *private; posn = to_fetch[i]; if (posn->status & REF_STATUS_UPTODATE) continue; - read_ref(posn->name, posn->old_sha1); + if (data->refspecs) + private = apply_refspecs(data->refspecs, data->refspec_nr, posn->name); + else + private = strdup(posn->name); + read_ref(private, posn->old_sha1); + free(private); } return 0; } -- cgit v1.3-5-g9baa