From 262a6ef76a1dde97ab50d79fa5cd6d3f9f125765 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Sat, 29 Apr 2006 15:50:28 +0000 Subject: [PATCH 1/2] git-format-patch: Use rfc2822 compliant date. Signed-off-by: Huw Davies Signed-off-by: Junio C Hamano --- git-format-patch.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/git-format-patch.sh b/git-format-patch.sh index c7133bc126..c077f44ca1 100755 --- a/git-format-patch.sh +++ b/git-format-patch.sh @@ -205,11 +205,10 @@ sub show_date { } my $t = $time + $minutes * 60; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime($t); - return sprintf("%s %s %d %02d:%02d:%02d %d %+05d", - $weekday_names[$wday], - $month_names[$mon], - $mday, $hour, $min, $sec, - $year+1900, $tz); + return sprintf("%s, %d %s %d %02d:%02d:%02d %+05d", + $weekday_names[$wday], $mday, + $month_names[$mon], $year+1900, + $hour, $min, $sec, $tz); } print "From nobody Mon Sep 17 00:00:00 2001\n"; From 755225de6ce4c7b39137afefb35208d0dbc14d9d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 29 Apr 2006 21:22:49 -0700 Subject: [PATCH 2/2] 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 Signed-off-by: Junio C Hamano --- Makefile | 2 +- builtin-push.c | 255 +++++++++++++++++++++++++++++++++++++++++++++++++ builtin.h | 2 + git.c | 1 + 4 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 builtin-push.c diff --git a/Makefile b/Makefile index 8ce27a65fb..9919992392 100644 --- a/Makefile +++ b/Makefile @@ -214,7 +214,7 @@ LIB_OBJS = \ $(DIFF_OBJS) BUILTIN_OBJS = \ - builtin-log.o builtin-help.o + builtin-log.o builtin-help.o builtin-push.o GITLIBS = $(LIB_FILE) $(XDIFF_LIB) LIBS = $(GITLIBS) -lz diff --git a/builtin-push.c b/builtin-push.c new file mode 100644 index 0000000000..a0c1caab52 --- /dev/null +++ b/builtin-push.c @@ -0,0 +1,255 @@ +/* + * "git push" + */ +#include "cache.h" +#include "refs.h" +#include "run-command.h" +#include "builtin.h" + +#define MAX_URI (16) + +static const char push_usage[] = "git push [--all] [--tags] [--force] [...]"; + +static int all = 0, tags = 0, force = 0, thin = 1; +static const char *execute = NULL; + +#define BUF_SIZE (2084) +static char buffer[BUF_SIZE]; + +static const char **refspec = NULL; +static int refspec_nr = 0; + +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; +} + +static int expand_one_ref(const char *ref, const unsigned char *sha1) +{ + /* Ignore the "refs/" at the beginning of the refname */ + ref += 5; + + if (strncmp(ref, "tags/", 5)) + return 0; + + add_refspec(strdup(ref)); + 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; + for_each_ref(expand_one_ref); +} + +static void set_refspecs(const char **refs, int nr) +{ + if (nr) { + size_t bytes = nr * sizeof(char *); + + refspec = xrealloc(refspec, bytes); + memcpy(refspec, refs, bytes); + refspec_nr = nr; + } + expand_refspecs(); +} + +static int get_remotes_uri(const char *repo, const char *uri[MAX_URI]) +{ + int n = 0; + FILE *f = fopen(git_path("remotes/%s", repo), "r"); + + if (!f) + return -1; + while (fgets(buffer, BUF_SIZE, f)) { + char *s, *p; + + if (strncmp("URL: ", buffer, 5)) + continue; + s = buffer + 5; + + /* Remove whitespace at the head.. */ + while (isspace(*s)) + s++; + if (!*s) + continue; + + /* ..and at the end */ + p = s + strlen(s); + while (isspace(p[-1])) + *--p = 0; + + uri[n++] = strdup(s); + if (n == MAX_URI) + break; + } + fclose(f); + if (!n) + die("remote '%s' has no URL", repo); + return n; +} + +static int get_branches_uri(const char *repo, const char *uri[MAX_URI]) +{ + const char *slash = strchr(repo, '/'); + int n = slash ? slash - repo : 1000; + FILE *f = fopen(git_path("branches/%.*s", n, repo), "r"); + char *s, *p; + int len; + + if (!f) + return 0; + s = fgets(buffer, BUF_SIZE, f); + fclose(f); + if (!s) + return 0; + while (isspace(*s)) + s++; + if (!*s) + return 0; + p = s + strlen(s); + while (isspace(p[-1])) + *--p = 0; + len = p - s; + if (slash) + len += strlen(slash); + p = xmalloc(len + 1); + strcpy(p, s); + if (slash) + strcat(p, slash); + uri[0] = p; + return 1; +} + +static int get_uri(const char *repo, const char *uri[MAX_URI]) +{ + int n; + + if (*repo != '/') { + n = get_remotes_uri(repo, uri); + if (n > 0) + return n; + + n = get_branches_uri(repo, uri); + if (n > 0) + return n; + } + + uri[0] = repo; + return 1; +} + +static int do_push(const char *repo) +{ + const char *uri[MAX_URI]; + int i, n = get_uri(repo, uri); + int remote; + const char **argv; + int argc; + + n = get_uri(repo, uri); + if (n <= 0) + die("bad repository '%s'", repo); + + argv = xmalloc((refspec_nr + 10) * sizeof(char *)); + argv[0] = "dummy-send-pack"; + argc = 1; + if (all) + argv[argc++] = "--all"; + if (force) + argv[argc++] = "--force"; + if (execute) + argv[argc++] = execute; + if (thin) + argv[argc++] = "--thin"; + remote = argc; + argv[argc++] = "dummy-remote"; + while (refspec_nr--) + argv[argc++] = *refspec++; + argv[argc] = NULL; + + for (i = 0; i < n; i++) { + int error; + const char *dest = uri[i]; + const char *sender = "git-send-pack"; + if (!strncmp(dest, "http://", 7) || + !strncmp(dest, "https://", 8)) + sender = "git-http-push"; + argv[0] = sender; + argv[remote] = dest; + error = run_command_v(argc, argv); + if (!error) + continue; + switch (error) { + case -ERR_RUN_COMMAND_FORK: + die("unable to fork for %s", sender); + case -ERR_RUN_COMMAND_EXEC: + die("unable to exec %s", sender); + case -ERR_RUN_COMMAND_WAITPID: + case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: + case -ERR_RUN_COMMAND_WAITPID_SIGNAL: + case -ERR_RUN_COMMAND_WAITPID_NOEXIT: + die("%s died with strange error", sender); + default: + return -error; + } + } + return 0; +} + +int cmd_push(int argc, const char **argv, char **envp) +{ + int i; + const char *repo = "origin"; // default repository + + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + + if (arg[0] != '-') { + repo = arg; + i++; + break; + } + if (!strcmp(arg, "--all")) { + all = 1; + continue; + } + if (!strcmp(arg, "--tags")) { + tags = 1; + continue; + } + if (!strcmp(arg, "--force")) { + force = 1; + continue; + } + if (!strcmp(arg, "--thin")) { + thin = 1; + continue; + } + if (!strcmp(arg, "--no-thin")) { + thin = 0; + continue; + } + if (!strncmp(arg, "--exec=", 7)) { + execute = arg; + continue; + } + usage(push_usage); + } + set_refspecs(argv + i, argc - i); + return do_push(repo); +} diff --git a/builtin.h b/builtin.h index 47408a0585..94fa9b5465 100644 --- a/builtin.h +++ b/builtin.h @@ -20,4 +20,6 @@ extern int cmd_whatchanged(int argc, const char **argv, char **envp); extern int cmd_show(int argc, const char **argv, char **envp); extern int cmd_log(int argc, const char **argv, char **envp); +extern int cmd_push(int argc, const char **argv, char **envp); + #endif diff --git a/git.c b/git.c index 01b7e28b8c..fd479e97c1 100644 --- a/git.c +++ b/git.c @@ -46,6 +46,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp) { "log", cmd_log }, { "whatchanged", cmd_whatchanged }, { "show", cmd_show }, + { "push", cmd_push }, }; int i;