summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 88293c6)
raw | patch | inline | side by side (parent: 88293c6)
author | Junio C Hamano <junkio@cox.net> | |
Tue, 6 Feb 2007 07:01:14 +0000 (23:01 -0800) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Tue, 6 Feb 2007 08:46:56 +0000 (00:46 -0800) |
This allows you to set up mothership-satellite configuration
more symmetrically and naturally by allowing the globbing
wildcard refspec for git-push. On your satellite machine:
[remote "mothership"]
url = mothership:project.git
fetch = refs/heads/*:refs/remotes/mothership/*
push = refs/heads/*:refs/remotes/satellite/*
You would say "git fetch mothership" to update your tracking
branches under mothership/ to keep track of the progress on the
mothership side, and when you are done working on the satellite
machine, you would "git push mothership" to update their
tracking branches under satellite/. Corresponding configuration
on the mothership machine can be used to make "git fetch satellite"
update its tracking branch under satellite/. on the mothership.
Signed-off-by: Junio C Hamano <junkio@cox.net>
more symmetrically and naturally by allowing the globbing
wildcard refspec for git-push. On your satellite machine:
[remote "mothership"]
url = mothership:project.git
fetch = refs/heads/*:refs/remotes/mothership/*
push = refs/heads/*:refs/remotes/satellite/*
You would say "git fetch mothership" to update your tracking
branches under mothership/ to keep track of the progress on the
mothership side, and when you are done working on the satellite
machine, you would "git push mothership" to update their
tracking branches under satellite/. Corresponding configuration
on the mothership machine can be used to make "git fetch satellite"
update its tracking branch under satellite/. on the mothership.
Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-push.c | patch | blob | history |
diff --git a/builtin-push.c b/builtin-push.c
index 5f4d7d34d35da35f0c843962f1ca1ae61a575456..c45649e26cf5284323aa80a5fe73b5842346eb14 100644 (file)
--- a/builtin-push.c
+++ b/builtin-push.c
for_each_ref(expand_one_ref, NULL);
}
+struct wildcard_cb {
+ const char *from_prefix;
+ int from_prefix_len;
+ const char *to_prefix;
+ int to_prefix_len;
+ int force;
+};
+
+static int expand_wildcard_ref(const char *ref, const unsigned char *sha1, int flag, void *cb_data)
+{
+ struct wildcard_cb *cb = cb_data;
+ int len = strlen(ref);
+ char *expanded, *newref;
+
+ if (len < cb->from_prefix_len ||
+ memcmp(cb->from_prefix, ref, cb->from_prefix_len))
+ return 0;
+ expanded = xmalloc(len * 2 + cb->force +
+ (cb->to_prefix_len - cb->from_prefix_len) + 2);
+ newref = expanded + cb->force;
+ if (cb->force)
+ expanded[0] = '+';
+ memcpy(newref, ref, len);
+ newref[len] = ':';
+ memcpy(newref + len + 1, cb->to_prefix, cb->to_prefix_len);
+ strcpy(newref + len + 1 + cb->to_prefix_len,
+ ref + cb->from_prefix_len);
+ add_refspec(expanded);
+ return 0;
+}
+
+static int wildcard_ref(const char *ref)
+{
+ int len;
+ const char *colon;
+ struct wildcard_cb cb;
+
+ memset(&cb, 0, sizeof(cb));
+ if (ref[0] == '+') {
+ cb.force = 1;
+ ref++;
+ }
+ len = strlen(ref);
+ colon = strchr(ref, ':');
+ if (! (colon && ref < colon &&
+ colon[-2] == '/' && colon[-1] == '*' &&
+ /* "<mine>/<asterisk>:<yours>/<asterisk>" is at least 7 bytes */
+ 7 <= len &&
+ ref[len-2] == '/' && ref[len-1] == '*') )
+ return 0 ;
+ cb.from_prefix = ref;
+ cb.from_prefix_len = colon - ref - 1;
+ cb.to_prefix = colon + 1;
+ cb.to_prefix_len = len - (colon - ref) - 2;
+ for_each_ref(expand_wildcard_ref, &cb);
+ return 1;
+}
+
static void set_refspecs(const char **refs, int nr)
{
if (nr) {
- int pass;
- for (pass = 0; pass < 2; pass++) {
- /* pass 0 counts and allocates, pass 1 fills */
- int i, cnt;
- for (i = cnt = 0; i < nr; i++) {
- if (!strcmp("tag", refs[i])) {
- int len;
- char *tag;
- if (nr <= ++i)
- die("tag <tag> shorthand without <tag>");
- if (pass) {
- len = strlen(refs[i]) + 11;
- tag = xmalloc(len);
- strcpy(tag, "refs/tags/");
- strcat(tag, refs[i]);
- refspec[cnt] = tag;
- }
- cnt++;
- continue;
- }
- if (pass)
- refspec[cnt] = refs[i];
- cnt++;
- }
- if (!pass) {
- size_t bytes = cnt * sizeof(char *);
- refspec_nr = cnt;
- refspec = xrealloc(refspec, bytes);
+ int i;
+ for (i = 0; i < nr; i++) {
+ const char *ref = refs[i];
+ if (!strcmp("tag", ref)) {
+ char *tag;
+ int len;
+ if (nr <= ++i)
+ die("tag shorthand without <tag>");
+ len = strlen(refs[i]) + 11;
+ tag = xmalloc(len);
+ strcpy(tag, "refs/tags/");
+ strcat(tag, refs[i]);
+ ref = tag;
}
+ else if (wildcard_ref(ref))
+ continue;
+ add_refspec(ref);
}
}
expand_refspecs();
else
error("more than %d URL's specified, ignoring the rest", MAX_URI);
}
- else if (is_refspec && !has_explicit_refspec)
- add_refspec(xstrdup(s));
+ else if (is_refspec && !has_explicit_refspec) {
+ if (!wildcard_ref(s))
+ add_refspec(xstrdup(s));
+ }
}
fclose(f);
if (!n)
error("more than %d URL's specified, ignoring the rest", MAX_URI);
}
else if (config_get_refspecs &&
- !strcmp(key + 7 + config_repo_len, ".push"))
- add_refspec(xstrdup(value));
+ !strcmp(key + 7 + config_repo_len, ".push")) {
+ if (!wildcard_ref(value))
+ add_refspec(xstrdup(value));
+ }
else if (config_get_receivepack &&
!strcmp(key + 7 + config_repo_len, ".receivepack")) {
if (!receivepack) {