@matheusbsbs / matheus-bagliano / commits / 72ff894308
Fork 0

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 <barkalow@iabervon.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Daniel Barkalow committed Nov 18, 2009 at 02:42 UTC 72ff894308d4f6eb9f081167377857f7a3268bca
4 files changed +80 -2
Documentation/git-remote-helpers.txt
+15 -1
@@ -46,7 +46,11 @@ Supported if the helper has the "fetch" capability.
46 'import' <name>::
47 Produces a fast-import stream which imports the current value
48 of the named ref. It may additionally import other refs as
49 - needed to construct the history efficiently.
49 + needed to construct the history efficiently. The script writes
50 + to a helper-specific private namespace. The value of the named
51 + ref should be written to a location in this namespace derived
52 + by applying the refspecs from the "refspec" capability to the
53 + name of the ref.
54 +
55 Supported if the helper has the "import" capability.
56
@@ -67,6 +71,16 @@ CAPABILITIES
71 'import'::
72 This helper supports the 'import' command.
73
74 +'refspec' 'spec'::
75 + When using the import command, expect the source ref to have
76 + been written to the destination ref. The earliest applicable
77 + refspec takes precedence. For example
78 + "refs/heads/*:refs/svn/origin/branches/*" means that, after an
79 + "import refs/heads/name", the script has written to
80 + refs/svn/origin/branches/name. If this capability is used at
81 + all, it must cover all refs reported by the list command; if
82 + it is not used, it is effectively "*:*"
83 +
84 REF LIST ATTRIBUTES
85 -------------------
86
remote.c
+27
@@ -673,6 +673,16 @@ static struct refspec *parse_push_refspec(int nr_refspec, const char **refspec)
673 return parse_refspec_internal(nr_refspec, refspec, 0, 0);
674 }
675
676 +void free_refspec(int nr_refspec, struct refspec *refspec)
677 +{
678 + int i;
679 + for (i = 0; i < nr_refspec; i++) {
680 + free(refspec[i].src);
681 + free(refspec[i].dst);
682 + }
683 + free(refspec);
684 +}
685 +
686 static int valid_remote_nick(const char *name)
687 {
688 if (!name[0] || is_dot_or_dotdot(name))
@@ -811,6 +821,23 @@ static int match_name_with_pattern(const char *key, const char *name,
821 return ret;
822 }
823
824 +char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
825 + const char *name)
826 +{
827 + int i;
828 + char *ret = NULL;
829 + for (i = 0; i < nr_refspec; i++) {
830 + struct refspec *refspec = refspecs + i;
831 + if (refspec->pattern) {
832 + if (match_name_with_pattern(refspec->src, name,
833 + refspec->dst, &ret))
834 + return ret;
835 + } else if (!strcmp(refspec->src, name))
836 + return strdup(refspec->dst);
837 + }
838 + return NULL;
839 +}
840 +
841 int remote_find_tracking(struct remote *remote, struct refspec *refspec)
842 {
843 int find_src = refspec->src == NULL;
remote.h
+5
@@ -91,6 +91,11 @@ void ref_remove_duplicates(struct ref *ref_map);
91 int valid_fetch_refspec(const char *refspec);
92 struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);
93
94 +void free_refspec(int nr_refspec, struct refspec *refspec);
95 +
96 +char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
97 + const char *name);
98 +
99 int match_refs(struct ref *src, struct ref **dst,
100 int nr_refspec, const char **refspec, int all);
101
transport-helper.c
+33 -1
@@ -5,6 +5,7 @@
5 #include "commit.h"
6 #include "diff.h"
7 #include "revision.h"
8 +#include "remote.h"
9
10 struct helper_data
11 {
@@ -12,6 +13,9 @@ struct helper_data
13 struct child_process *helper;
14 unsigned fetch : 1;
15 unsigned import : 1;
16 + /* These go from remote name (as in "list") to private name */
17 + struct refspec *refspecs;
18 + int refspec_nr;
19 };
20
21 static struct child_process *get_helper(struct transport *transport)
@@ -20,6 +24,9 @@ static struct child_process *get_helper(struct transport *transport)
24 struct strbuf buf = STRBUF_INIT;
25 struct child_process *helper;
26 FILE *file;
27 + const char **refspecs = NULL;
28 + int refspec_nr = 0;
29 + int refspec_alloc = 0;
30
31 if (data->helper)
32 return data->helper;
@@ -51,6 +58,21 @@ static struct child_process *get_helper(struct transport *transport)
58 data->fetch = 1;
59 if (!strcmp(buf.buf, "import"))
60 data->import = 1;
61 + if (!data->refspecs && !prefixcmp(buf.buf, "refspec ")) {
62 + ALLOC_GROW(refspecs,
63 + refspec_nr + 1,
64 + refspec_alloc);
65 + refspecs[refspec_nr++] = strdup(buf.buf + strlen("refspec "));
66 + }
67 + }
68 + if (refspecs) {
69 + int i;
70 + data->refspec_nr = refspec_nr;
71 + data->refspecs = parse_fetch_refspec(refspec_nr, refspecs);
72 + for (i = 0; i < refspec_nr; i++) {
73 + free((char *)refspecs[i]);
74 + }
75 + free(refspecs);
76 }
77 return data->helper;
78 }
@@ -72,6 +94,9 @@ static int disconnect_helper(struct transport *transport)
94
95 static int release_helper(struct transport *transport)
96 {
97 + struct helper_data *data = transport->data;
98 + free_refspec(data->refspec_nr, data->refspecs);
99 + data->refspecs = NULL;
100 disconnect_helper(transport);
101 free(transport->data);
102 return 0;
@@ -119,6 +144,7 @@ static int fetch_with_import(struct transport *transport,
144 {
145 struct child_process fastimport;
146 struct child_process *helper = get_helper(transport);
147 + struct helper_data *data = transport->data;
148 int i;
149 struct ref *posn;
150 struct strbuf buf = STRBUF_INIT;
@@ -139,10 +165,16 @@ static int fetch_with_import(struct transport *transport,
165 finish_command(&fastimport);
166
167 for (i = 0; i < nr_heads; i++) {
168 + char *private;
169 posn = to_fetch[i];
170 if (posn->status & REF_STATUS_UPTODATE)
171 continue;
145 - read_ref(posn->name, posn->old_sha1);
172 + if (data->refspecs)
173 + private = apply_refspecs(data->refspecs, data->refspec_nr, posn->name);
174 + else
175 + private = strdup(posn->name);
176 + read_ref(private, posn->old_sha1);
177 + free(private);
178 }
179 return 0;
180 }