git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
/*
|
|
|
|
* "git push"
|
|
|
|
*/
|
|
|
|
#include "cache.h"
|
|
|
|
#include "refs.h"
|
|
|
|
#include "run-command.h"
|
|
|
|
#include "builtin.h"
|
2007-05-12 23:45:53 +08:00
|
|
|
#include "remote.h"
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
|
2007-01-19 20:49:27 +08:00
|
|
|
static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
|
2006-10-31 00:28:59 +08:00
|
|
|
static int all, tags, force, thin = 1, verbose;
|
2007-01-19 20:49:27 +08:00
|
|
|
static const char *receivepack;
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
|
2006-08-16 01:23:48 +08:00
|
|
|
static const char **refspec;
|
|
|
|
static int refspec_nr;
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
|
|
|
|
static void add_refspec(const char *ref)
|
|
|
|
{
|
|
|
|
int nr = refspec_nr + 1;
|
|
|
|
refspec = xrealloc(refspec, nr * sizeof(char *));
|
|
|
|
refspec[nr-1] = ref;
|
|
|
|
refspec_nr = nr;
|
|
|
|
}
|
|
|
|
|
2006-09-21 13:02:01 +08:00
|
|
|
static int expand_one_ref(const char *ref, const unsigned char *sha1, int flag, void *cb_data)
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
{
|
|
|
|
/* Ignore the "refs/" at the beginning of the refname */
|
|
|
|
ref += 5;
|
|
|
|
|
Mechanical conversion to use prefixcmp()
This mechanically converts strncmp() to use prefixcmp(), but only when
the parameters match specific patterns, so that they can be verified
easily. Leftover from this will be fixed in a separate step, including
idiotic conversions like
if (!strncmp("foo", arg, 3))
=>
if (!(-prefixcmp(arg, "foo")))
This was done by using this script in px.perl
#!/usr/bin/perl -i.bak -p
if (/strncmp\(([^,]+), "([^\\"]*)", (\d+)\)/ && (length($2) == $3)) {
s|strncmp\(([^,]+), "([^\\"]*)", (\d+)\)|prefixcmp($1, "$2")|;
}
if (/strncmp\("([^\\"]*)", ([^,]+), (\d+)\)/ && (length($1) == $3)) {
s|strncmp\("([^\\"]*)", ([^,]+), (\d+)\)|(-prefixcmp($2, "$1"))|;
}
and running:
$ git grep -l strncmp -- '*.c' | xargs perl px.perl
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 17:53:29 +08:00
|
|
|
if (!prefixcmp(ref, "tags/"))
|
2006-09-02 12:16:31 +08:00
|
|
|
add_refspec(xstrdup(ref));
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void expand_refspecs(void)
|
|
|
|
{
|
|
|
|
if (all) {
|
|
|
|
if (refspec_nr)
|
|
|
|
die("cannot mix '--all' and a refspec");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No need to expand "--all" - we'll just use
|
|
|
|
* the "--all" flag to send-pack
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!tags)
|
|
|
|
return;
|
2006-09-21 12:47:42 +08:00
|
|
|
for_each_ref(expand_one_ref, NULL);
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
}
|
|
|
|
|
2007-02-06 15:01:14 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
static void set_refspecs(const char **refs, int nr)
|
|
|
|
{
|
|
|
|
if (nr) {
|
2007-02-06 15:01:14 +08:00
|
|
|
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;
|
2006-12-14 02:03:39 +08:00
|
|
|
}
|
2007-02-06 15:01:14 +08:00
|
|
|
else if (wildcard_ref(ref))
|
|
|
|
continue;
|
|
|
|
add_refspec(ref);
|
2006-12-14 02:03:39 +08:00
|
|
|
}
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
}
|
|
|
|
expand_refspecs();
|
|
|
|
}
|
|
|
|
|
|
|
|
static int do_push(const char *repo)
|
|
|
|
{
|
2007-05-12 23:45:53 +08:00
|
|
|
int i, errs;
|
2006-06-06 04:02:29 +08:00
|
|
|
int common_argc;
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
const char **argv;
|
|
|
|
int argc;
|
2007-05-12 23:45:53 +08:00
|
|
|
struct remote *remote = remote_get(repo);
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
|
2007-05-12 23:45:53 +08:00
|
|
|
if (!remote)
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
die("bad repository '%s'", repo);
|
|
|
|
|
2007-05-12 23:45:53 +08:00
|
|
|
if (remote->receivepack) {
|
|
|
|
char *rp = xmalloc(strlen(remote->receivepack) + 16);
|
|
|
|
sprintf(rp, "--receive-pack=%s", remote->receivepack);
|
|
|
|
receivepack = rp;
|
|
|
|
}
|
|
|
|
if (!refspec && !all && !tags && remote->push_refspec_nr) {
|
|
|
|
for (i = 0; i < remote->push_refspec_nr; i++) {
|
|
|
|
if (!wildcard_ref(remote->push_refspec[i]))
|
|
|
|
add_refspec(remote->push_refspec[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
argv = xmalloc((refspec_nr + 10) * sizeof(char *));
|
|
|
|
argv[0] = "dummy-send-pack";
|
|
|
|
argc = 1;
|
|
|
|
if (all)
|
|
|
|
argv[argc++] = "--all";
|
|
|
|
if (force)
|
|
|
|
argv[argc++] = "--force";
|
2007-01-19 20:49:27 +08:00
|
|
|
if (receivepack)
|
|
|
|
argv[argc++] = receivepack;
|
2006-06-06 04:02:29 +08:00
|
|
|
common_argc = argc;
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
|
2007-04-07 14:04:53 +08:00
|
|
|
errs = 0;
|
2007-05-12 23:45:53 +08:00
|
|
|
for (i = 0; i < remote->uri_nr; i++) {
|
2006-08-23 18:39:10 +08:00
|
|
|
int err;
|
2006-06-06 04:02:29 +08:00
|
|
|
int dest_argc = common_argc;
|
|
|
|
int dest_refspec_nr = refspec_nr;
|
|
|
|
const char **dest_refspec = refspec;
|
2007-05-12 23:45:53 +08:00
|
|
|
const char *dest = remote->uri[i];
|
2007-03-13 07:00:15 +08:00
|
|
|
const char *sender = "send-pack";
|
Mechanical conversion to use prefixcmp()
This mechanically converts strncmp() to use prefixcmp(), but only when
the parameters match specific patterns, so that they can be verified
easily. Leftover from this will be fixed in a separate step, including
idiotic conversions like
if (!strncmp("foo", arg, 3))
=>
if (!(-prefixcmp(arg, "foo")))
This was done by using this script in px.perl
#!/usr/bin/perl -i.bak -p
if (/strncmp\(([^,]+), "([^\\"]*)", (\d+)\)/ && (length($2) == $3)) {
s|strncmp\(([^,]+), "([^\\"]*)", (\d+)\)|prefixcmp($1, "$2")|;
}
if (/strncmp\("([^\\"]*)", ([^,]+), (\d+)\)/ && (length($1) == $3)) {
s|strncmp\("([^\\"]*)", ([^,]+), (\d+)\)|(-prefixcmp($2, "$1"))|;
}
and running:
$ git grep -l strncmp -- '*.c' | xargs perl px.perl
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 17:53:29 +08:00
|
|
|
if (!prefixcmp(dest, "http://") ||
|
|
|
|
!prefixcmp(dest, "https://"))
|
2007-03-13 07:00:15 +08:00
|
|
|
sender = "http-push";
|
2007-05-16 10:50:19 +08:00
|
|
|
else {
|
|
|
|
char *rem = xmalloc(strlen(remote->name) + 10);
|
|
|
|
sprintf(rem, "--remote=%s", remote->name);
|
|
|
|
argv[dest_argc++] = rem;
|
|
|
|
if (thin)
|
|
|
|
argv[dest_argc++] = "--thin";
|
|
|
|
}
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
argv[0] = sender;
|
2006-06-06 04:02:29 +08:00
|
|
|
argv[dest_argc++] = dest;
|
|
|
|
while (dest_refspec_nr--)
|
|
|
|
argv[dest_argc++] = *dest_refspec++;
|
|
|
|
argv[dest_argc] = NULL;
|
2006-10-31 00:28:59 +08:00
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, "Pushing to %s\n", dest);
|
2007-03-13 07:00:15 +08:00
|
|
|
err = run_command_v_opt(argv, RUN_GIT_CMD);
|
2006-08-23 18:39:10 +08:00
|
|
|
if (!err)
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
continue;
|
2007-04-07 14:04:55 +08:00
|
|
|
|
2007-05-12 23:45:53 +08:00
|
|
|
error("failed to push to '%s'", remote->uri[i]);
|
2006-08-23 18:39:10 +08:00
|
|
|
switch (err) {
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
case -ERR_RUN_COMMAND_FORK:
|
2007-04-07 14:04:53 +08:00
|
|
|
error("unable to fork for %s", sender);
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
case -ERR_RUN_COMMAND_EXEC:
|
2007-04-07 14:04:53 +08:00
|
|
|
error("unable to exec %s", sender);
|
|
|
|
break;
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
case -ERR_RUN_COMMAND_WAITPID:
|
|
|
|
case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
|
|
|
|
case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
|
|
|
|
case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
|
2007-04-07 14:04:53 +08:00
|
|
|
error("%s died with strange error", sender);
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
}
|
2007-04-07 14:04:53 +08:00
|
|
|
errs++;
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
}
|
2007-04-07 14:04:53 +08:00
|
|
|
return !!errs;
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
}
|
|
|
|
|
2006-07-29 13:44:25 +08:00
|
|
|
int cmd_push(int argc, const char **argv, const char *prefix)
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
{
|
|
|
|
int i;
|
2007-05-12 23:45:53 +08:00
|
|
|
const char *repo = NULL; /* default repository */
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
|
|
const char *arg = argv[i];
|
|
|
|
|
|
|
|
if (arg[0] != '-') {
|
|
|
|
repo = arg;
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
}
|
2006-10-31 00:28:59 +08:00
|
|
|
if (!strcmp(arg, "-v")) {
|
|
|
|
verbose=1;
|
|
|
|
continue;
|
|
|
|
}
|
Mechanical conversion to use prefixcmp()
This mechanically converts strncmp() to use prefixcmp(), but only when
the parameters match specific patterns, so that they can be verified
easily. Leftover from this will be fixed in a separate step, including
idiotic conversions like
if (!strncmp("foo", arg, 3))
=>
if (!(-prefixcmp(arg, "foo")))
This was done by using this script in px.perl
#!/usr/bin/perl -i.bak -p
if (/strncmp\(([^,]+), "([^\\"]*)", (\d+)\)/ && (length($2) == $3)) {
s|strncmp\(([^,]+), "([^\\"]*)", (\d+)\)|prefixcmp($1, "$2")|;
}
if (/strncmp\("([^\\"]*)", ([^,]+), (\d+)\)/ && (length($1) == $3)) {
s|strncmp\("([^\\"]*)", ([^,]+), (\d+)\)|(-prefixcmp($2, "$1"))|;
}
and running:
$ git grep -l strncmp -- '*.c' | xargs perl px.perl
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 17:53:29 +08:00
|
|
|
if (!prefixcmp(arg, "--repo=")) {
|
2006-10-31 00:28:59 +08:00
|
|
|
repo = arg+7;
|
|
|
|
continue;
|
|
|
|
}
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
if (!strcmp(arg, "--all")) {
|
|
|
|
all = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!strcmp(arg, "--tags")) {
|
|
|
|
tags = 1;
|
|
|
|
continue;
|
|
|
|
}
|
2006-08-02 23:28:16 +08:00
|
|
|
if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
force = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!strcmp(arg, "--thin")) {
|
|
|
|
thin = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!strcmp(arg, "--no-thin")) {
|
|
|
|
thin = 0;
|
|
|
|
continue;
|
|
|
|
}
|
Mechanical conversion to use prefixcmp()
This mechanically converts strncmp() to use prefixcmp(), but only when
the parameters match specific patterns, so that they can be verified
easily. Leftover from this will be fixed in a separate step, including
idiotic conversions like
if (!strncmp("foo", arg, 3))
=>
if (!(-prefixcmp(arg, "foo")))
This was done by using this script in px.perl
#!/usr/bin/perl -i.bak -p
if (/strncmp\(([^,]+), "([^\\"]*)", (\d+)\)/ && (length($2) == $3)) {
s|strncmp\(([^,]+), "([^\\"]*)", (\d+)\)|prefixcmp($1, "$2")|;
}
if (/strncmp\("([^\\"]*)", ([^,]+), (\d+)\)/ && (length($1) == $3)) {
s|strncmp\("([^\\"]*)", ([^,]+), (\d+)\)|(-prefixcmp($2, "$1"))|;
}
and running:
$ git grep -l strncmp -- '*.c' | xargs perl px.perl
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 17:53:29 +08:00
|
|
|
if (!prefixcmp(arg, "--receive-pack=")) {
|
2007-01-19 20:49:27 +08:00
|
|
|
receivepack = arg;
|
|
|
|
continue;
|
|
|
|
}
|
Mechanical conversion to use prefixcmp()
This mechanically converts strncmp() to use prefixcmp(), but only when
the parameters match specific patterns, so that they can be verified
easily. Leftover from this will be fixed in a separate step, including
idiotic conversions like
if (!strncmp("foo", arg, 3))
=>
if (!(-prefixcmp(arg, "foo")))
This was done by using this script in px.perl
#!/usr/bin/perl -i.bak -p
if (/strncmp\(([^,]+), "([^\\"]*)", (\d+)\)/ && (length($2) == $3)) {
s|strncmp\(([^,]+), "([^\\"]*)", (\d+)\)|prefixcmp($1, "$2")|;
}
if (/strncmp\("([^\\"]*)", ([^,]+), (\d+)\)/ && (length($1) == $3)) {
s|strncmp\("([^\\"]*)", ([^,]+), (\d+)\)|(-prefixcmp($2, "$1"))|;
}
and running:
$ git grep -l strncmp -- '*.c' | xargs perl px.perl
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 17:53:29 +08:00
|
|
|
if (!prefixcmp(arg, "--exec=")) {
|
2007-01-19 20:49:27 +08:00
|
|
|
receivepack = arg;
|
git builtin "push"
This adds a builtin "push" command, which is largely just a C'ification of
the "git-push.sh" script.
Now, the reason I did it as a built-in is partly because it's yet another
step on relying less on shell, but it's actually mostly because I've
wanted to be able to push to _multiple_ repositories, and the most obvious
and simplest interface for that would seem be to just have a "remotes"
file that has multiple URL entries.
(For "pull", having multiple entries should either just select the first
one, or you could fall back on the others on failure - your choice).
And quite frankly, it just became too damn messy to do that in shell.
Besides, we actually have a fair amount of infrastructure in C, so it just
wasn't that hard to do.
Of course, this is almost totally untested. It probably doesn't work for
anything but the one trial I threw at it. "Simple" doesn't necessarily
mean "obviously correct".
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-30 12:22:49 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
usage(push_usage);
|
|
|
|
}
|
|
|
|
set_refspecs(argv + i, argc - i);
|
|
|
|
return do_push(repo);
|
|
|
|
}
|