summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e65e91e)
raw | patch | inline | side by side (parent: e65e91e)
author | Daniel Barkalow <barkalow@iabervon.org> | |
Wed, 18 Nov 2009 01:42:28 +0000 (02:42 +0100) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Wed, 18 Nov 2009 05:45:44 +0000 (21:45 -0800) |
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 <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
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 <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-remote-helpers.txt | patch | blob | history | |
remote.c | patch | blob | history | |
remote.h | patch | blob | history | |
transport-helper.c | patch | blob | history |
index e9aa67e757ac777f10a684258366002dd932ada8..d6c5268d38cab106920f473bdb944d905bdab768 100644 (file)
'import' <name>::
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.
'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 09bb79c22c00a0fe3234218136ba1a6e970078cc..1f7870d107371af9dd4db1fb6e2e777138d682b3 100644 (file)
--- 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))
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 ac0ce2ff9cb1e787bbb231d2b5d9e9d2cfb2777d..cdc3b5b159351b550f7136594e0d9f930177e576 100644 (file)
--- a/remote.h
+++ b/remote.h
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 82caaaead6666eecaceedfbaa486dae4901a80a5..da8185a98150fddf692c9ead76097acbe7b9b41c 100644 (file)
--- a/transport-helper.c
+++ b/transport-helper.c
#include "commit.h"
#include "diff.h"
#include "revision.h"
+#include "remote.h"
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)
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;
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;
}
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;
{
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;
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;
}