Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 1 | /* |
| 2 | * "git push" |
| 3 | */ |
| 4 | #include "cache.h" |
| 5 | #include "refs.h" |
| 6 | #include "run-command.h" |
| 7 | #include "builtin.h" |
Daniel Barkalow | 5751f49 | 2007-05-12 11:45:53 -0400 | [diff] [blame] | 8 | #include "remote.h" |
Daniel Barkalow | 9b28851 | 2007-09-10 23:03:04 -0400 | [diff] [blame] | 9 | #include "transport.h" |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 10 | #include "parse-options.h" |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 11 | |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 12 | static const char * const push_usage[] = { |
Johannes Sixt | bf07cc5 | 2008-10-07 16:26:20 +0200 | [diff] [blame] | 13 | "git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]", |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 14 | NULL, |
| 15 | }; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 16 | |
Michele Ballabio | c29c1b4 | 2008-07-20 14:02:20 +0200 | [diff] [blame] | 17 | static int thin; |
Uwe Kleine-König | d23842f | 2007-01-19 13:49:27 +0100 | [diff] [blame] | 18 | static const char *receivepack; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 19 | |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 20 | static const char **refspec; |
| 21 | static int refspec_nr; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 22 | |
| 23 | static void add_refspec(const char *ref) |
| 24 | { |
| 25 | int nr = refspec_nr + 1; |
| 26 | refspec = xrealloc(refspec, nr * sizeof(char *)); |
| 27 | refspec[nr-1] = ref; |
| 28 | refspec_nr = nr; |
| 29 | } |
| 30 | |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 31 | static void set_refspecs(const char **refs, int nr) |
| 32 | { |
Daniel Barkalow | 8558fd9 | 2007-05-25 01:20:56 -0400 | [diff] [blame] | 33 | int i; |
| 34 | for (i = 0; i < nr; i++) { |
| 35 | const char *ref = refs[i]; |
| 36 | if (!strcmp("tag", ref)) { |
| 37 | char *tag; |
| 38 | int len; |
| 39 | if (nr <= ++i) |
| 40 | die("tag shorthand without <tag>"); |
| 41 | len = strlen(refs[i]) + 11; |
| 42 | tag = xmalloc(len); |
| 43 | strcpy(tag, "refs/tags/"); |
| 44 | strcat(tag, refs[i]); |
| 45 | ref = tag; |
Junio C Hamano | 411fb8b | 2006-12-13 10:03:39 -0800 | [diff] [blame] | 46 | } |
Daniel Barkalow | 8558fd9 | 2007-05-25 01:20:56 -0400 | [diff] [blame] | 47 | add_refspec(ref); |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 48 | } |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 49 | } |
| 50 | |
Finn Arne Gangstad | 5215374 | 2009-03-16 16:42:51 +0100 | [diff] [blame] | 51 | static void setup_push_tracking(void) |
| 52 | { |
| 53 | struct strbuf refspec = STRBUF_INIT; |
| 54 | struct branch *branch = branch_get(NULL); |
| 55 | if (!branch) |
| 56 | die("You are not currently on a branch."); |
| 57 | if (!branch->merge_nr) |
| 58 | die("The current branch %s is not tracking anything.", |
| 59 | branch->name); |
| 60 | if (branch->merge_nr != 1) |
| 61 | die("The current branch %s is tracking multiple branches, " |
| 62 | "refusing to push.", branch->name); |
| 63 | strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src); |
| 64 | add_refspec(refspec.buf); |
| 65 | } |
| 66 | |
Finn Arne Gangstad | 665d3e8 | 2009-03-16 16:42:52 +0100 | [diff] [blame] | 67 | static const char *warn_unconfigured_push_msg[] = { |
| 68 | "You did not specify any refspecs to push, and the current remote", |
| 69 | "has not configured any push refspecs. The default action in this", |
| 70 | "case is to push all matching refspecs, that is, all branches", |
| 71 | "that exist both locally and remotely will be updated. This may", |
| 72 | "not necessarily be what you want to happen.", |
| 73 | "", |
| 74 | "You can specify what action you want to take in this case, and", |
| 75 | "avoid seeing this message again, by configuring 'push.default' to:", |
Kevin Ballard | b2655cd | 2009-03-25 13:14:03 -0700 | [diff] [blame] | 76 | " 'nothing' : Do not push anything", |
Finn Arne Gangstad | 665d3e8 | 2009-03-16 16:42:52 +0100 | [diff] [blame] | 77 | " 'matching' : Push all matching branches (default)", |
| 78 | " 'tracking' : Push the current branch to whatever it is tracking", |
| 79 | " 'current' : Push the current branch" |
| 80 | }; |
| 81 | |
| 82 | static void warn_unconfigured_push(void) |
| 83 | { |
| 84 | int i; |
| 85 | for (i = 0; i < ARRAY_SIZE(warn_unconfigured_push_msg); i++) |
| 86 | warning("%s", warn_unconfigured_push_msg[i]); |
| 87 | } |
| 88 | |
Finn Arne Gangstad | 5215374 | 2009-03-16 16:42:51 +0100 | [diff] [blame] | 89 | static void setup_default_push_refspecs(void) |
| 90 | { |
| 91 | git_config(git_default_config, NULL); |
| 92 | switch (push_default) { |
| 93 | case PUSH_DEFAULT_UNSPECIFIED: |
Finn Arne Gangstad | 665d3e8 | 2009-03-16 16:42:52 +0100 | [diff] [blame] | 94 | warn_unconfigured_push(); |
Finn Arne Gangstad | 5215374 | 2009-03-16 16:42:51 +0100 | [diff] [blame] | 95 | /* fallthrough */ |
| 96 | |
| 97 | case PUSH_DEFAULT_MATCHING: |
| 98 | add_refspec(":"); |
| 99 | break; |
| 100 | |
| 101 | case PUSH_DEFAULT_TRACKING: |
| 102 | setup_push_tracking(); |
| 103 | break; |
| 104 | |
| 105 | case PUSH_DEFAULT_CURRENT: |
| 106 | add_refspec("HEAD"); |
| 107 | break; |
| 108 | |
| 109 | case PUSH_DEFAULT_NOTHING: |
| 110 | die("You didn't specify any refspecs to push, and " |
| 111 | "push.default is \"nothing\"."); |
| 112 | break; |
| 113 | } |
| 114 | } |
| 115 | |
Daniel Barkalow | 9b28851 | 2007-09-10 23:03:04 -0400 | [diff] [blame] | 116 | static int do_push(const char *repo, int flags) |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 117 | { |
Daniel Barkalow | 5751f49 | 2007-05-12 11:45:53 -0400 | [diff] [blame] | 118 | int i, errs; |
Daniel Barkalow | 5751f49 | 2007-05-12 11:45:53 -0400 | [diff] [blame] | 119 | struct remote *remote = remote_get(repo); |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 120 | |
Daniel Barkalow | fa685bd | 2009-03-11 01:47:20 -0400 | [diff] [blame] | 121 | if (!remote) { |
| 122 | if (repo) |
| 123 | die("bad repository '%s'", repo); |
| 124 | die("No destination configured to push to."); |
| 125 | } |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 126 | |
Paolo Bonzini | 84bb2df | 2008-04-17 13:17:20 +0200 | [diff] [blame] | 127 | if (remote->mirror) |
| 128 | flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE); |
| 129 | |
Marek Zawirski | b259f09 | 2008-08-16 19:58:32 +0200 | [diff] [blame] | 130 | if ((flags & TRANSPORT_PUSH_ALL) && refspec) { |
| 131 | if (!strcmp(*refspec, "refs/tags/*")) |
| 132 | return error("--all and --tags are incompatible"); |
| 133 | return error("--all can't be combined with refspecs"); |
| 134 | } |
| 135 | |
| 136 | if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) { |
| 137 | if (!strcmp(*refspec, "refs/tags/*")) |
| 138 | return error("--mirror and --tags are incompatible"); |
| 139 | return error("--mirror can't be combined with refspecs"); |
| 140 | } |
Paolo Bonzini | 84bb2df | 2008-04-17 13:17:20 +0200 | [diff] [blame] | 141 | |
| 142 | if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) == |
| 143 | (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) { |
| 144 | return error("--all and --mirror are incompatible"); |
| 145 | } |
| 146 | |
Finn Arne Gangstad | 5215374 | 2009-03-16 16:42:51 +0100 | [diff] [blame] | 147 | if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) { |
| 148 | if (remote->push_refspec_nr) { |
| 149 | refspec = remote->push_refspec; |
| 150 | refspec_nr = remote->push_refspec_nr; |
| 151 | } else if (!(flags & TRANSPORT_PUSH_MIRROR)) |
| 152 | setup_default_push_refspecs(); |
Daniel Barkalow | 5751f49 | 2007-05-12 11:45:53 -0400 | [diff] [blame] | 153 | } |
Junio C Hamano | fd1d1b0 | 2007-04-06 23:04:53 -0700 | [diff] [blame] | 154 | errs = 0; |
Shawn O. Pearce | 28b91f8 | 2007-09-19 00:49:27 -0400 | [diff] [blame] | 155 | for (i = 0; i < remote->url_nr; i++) { |
Daniel Barkalow | 9b28851 | 2007-09-10 23:03:04 -0400 | [diff] [blame] | 156 | struct transport *transport = |
Shawn O. Pearce | 28b91f8 | 2007-09-19 00:49:27 -0400 | [diff] [blame] | 157 | transport_get(remote, remote->url[i]); |
Pierre Habouzit | 60b7f38 | 2006-08-23 12:39:10 +0200 | [diff] [blame] | 158 | int err; |
Daniel Barkalow | 9b28851 | 2007-09-10 23:03:04 -0400 | [diff] [blame] | 159 | if (receivepack) |
| 160 | transport_set_option(transport, |
| 161 | TRANS_OPT_RECEIVEPACK, receivepack); |
| 162 | if (thin) |
| 163 | transport_set_option(transport, TRANS_OPT_THIN, "yes"); |
| 164 | |
Michele Ballabio | c29c1b4 | 2008-07-20 14:02:20 +0200 | [diff] [blame] | 165 | if (flags & TRANSPORT_PUSH_VERBOSE) |
Shawn O. Pearce | 28b91f8 | 2007-09-19 00:49:27 -0400 | [diff] [blame] | 166 | fprintf(stderr, "Pushing to %s\n", remote->url[i]); |
Daniel Barkalow | 9b28851 | 2007-09-10 23:03:04 -0400 | [diff] [blame] | 167 | err = transport_push(transport, refspec_nr, refspec, flags); |
| 168 | err |= transport_disconnect(transport); |
| 169 | |
Pierre Habouzit | 60b7f38 | 2006-08-23 12:39:10 +0200 | [diff] [blame] | 170 | if (!err) |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 171 | continue; |
Junio C Hamano | 39878b0 | 2007-04-06 23:04:55 -0700 | [diff] [blame] | 172 | |
Jeff King | 2b8130c | 2008-02-19 11:25:01 -0500 | [diff] [blame] | 173 | error("failed to push some refs to '%s'", remote->url[i]); |
Junio C Hamano | fd1d1b0 | 2007-04-06 23:04:53 -0700 | [diff] [blame] | 174 | errs++; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 175 | } |
Junio C Hamano | fd1d1b0 | 2007-04-06 23:04:53 -0700 | [diff] [blame] | 176 | return !!errs; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 177 | } |
| 178 | |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 179 | int cmd_push(int argc, const char **argv, const char *prefix) |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 180 | { |
Daniel Barkalow | 9b28851 | 2007-09-10 23:03:04 -0400 | [diff] [blame] | 181 | int flags = 0; |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 182 | int tags = 0; |
Paolo Bonzini | 84bb2df | 2008-04-17 13:17:20 +0200 | [diff] [blame] | 183 | int rc; |
Daniel Barkalow | 5751f49 | 2007-05-12 11:45:53 -0400 | [diff] [blame] | 184 | const char *repo = NULL; /* default repository */ |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 185 | |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 186 | struct option options[] = { |
Michele Ballabio | c29c1b4 | 2008-07-20 14:02:20 +0200 | [diff] [blame] | 187 | OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE), |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 188 | OPT_STRING( 0 , "repo", &repo, "repository", "repository"), |
Michele Ballabio | c29c1b4 | 2008-07-20 14:02:20 +0200 | [diff] [blame] | 189 | OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL), |
| 190 | OPT_BIT( 0 , "mirror", &flags, "mirror all refs", |
| 191 | (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 192 | OPT_BOOLEAN( 0 , "tags", &tags, "push tags"), |
Michele Ballabio | c29c1b4 | 2008-07-20 14:02:20 +0200 | [diff] [blame] | 193 | OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN), |
| 194 | OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE), |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 195 | OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"), |
| 196 | OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"), |
| 197 | OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"), |
| 198 | OPT_END() |
| 199 | }; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 200 | |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 201 | argc = parse_options(argc, argv, options, push_usage, 0); |
| 202 | |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 203 | if (tags) |
| 204 | add_refspec("refs/tags/*"); |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 205 | |
| 206 | if (argc > 0) { |
| 207 | repo = argv[0]; |
| 208 | set_refspecs(argv + 1, argc - 1); |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 209 | } |
Daniel Barkalow | 8558fd9 | 2007-05-25 01:20:56 -0400 | [diff] [blame] | 210 | |
Paolo Bonzini | 84bb2df | 2008-04-17 13:17:20 +0200 | [diff] [blame] | 211 | rc = do_push(repo, flags); |
| 212 | if (rc == -1) |
Andy Whitcroft | 94c89ba | 2007-11-09 23:32:25 +0000 | [diff] [blame] | 213 | usage_with_options(push_usage, options); |
Paolo Bonzini | 84bb2df | 2008-04-17 13:17:20 +0200 | [diff] [blame] | 214 | else |
| 215 | return rc; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 216 | } |