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[] = { |
Nanako Shiraishi | fcb044e | 2009-10-19 11:54:12 +0900 | [diff] [blame] | 13 | "git push [<options>] [<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; |
Jan Krüger | f517f1f | 2009-12-30 20:57:42 +0100 | [diff] [blame] | 18 | static int deleterefs; |
Uwe Kleine-König | d23842f | 2007-01-19 13:49:27 +0100 | [diff] [blame] | 19 | static const char *receivepack; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 20 | |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 21 | static const char **refspec; |
| 22 | static int refspec_nr; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 23 | |
| 24 | static void add_refspec(const char *ref) |
| 25 | { |
| 26 | int nr = refspec_nr + 1; |
| 27 | refspec = xrealloc(refspec, nr * sizeof(char *)); |
| 28 | refspec[nr-1] = ref; |
| 29 | refspec_nr = nr; |
| 30 | } |
| 31 | |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 32 | static void set_refspecs(const char **refs, int nr) |
| 33 | { |
Daniel Barkalow | 8558fd9 | 2007-05-25 01:20:56 -0400 | [diff] [blame] | 34 | int i; |
| 35 | for (i = 0; i < nr; i++) { |
| 36 | const char *ref = refs[i]; |
| 37 | if (!strcmp("tag", ref)) { |
| 38 | char *tag; |
| 39 | int len; |
| 40 | if (nr <= ++i) |
| 41 | die("tag shorthand without <tag>"); |
| 42 | len = strlen(refs[i]) + 11; |
Jan Krüger | f517f1f | 2009-12-30 20:57:42 +0100 | [diff] [blame] | 43 | if (deleterefs) { |
| 44 | tag = xmalloc(len+1); |
| 45 | strcpy(tag, ":refs/tags/"); |
| 46 | } else { |
| 47 | tag = xmalloc(len); |
| 48 | strcpy(tag, "refs/tags/"); |
| 49 | } |
Daniel Barkalow | 8558fd9 | 2007-05-25 01:20:56 -0400 | [diff] [blame] | 50 | strcat(tag, refs[i]); |
| 51 | ref = tag; |
Jan Krüger | f517f1f | 2009-12-30 20:57:42 +0100 | [diff] [blame] | 52 | } else if (deleterefs && !strchr(ref, ':')) { |
| 53 | char *delref; |
| 54 | int len = strlen(ref)+1; |
| 55 | delref = xmalloc(len); |
| 56 | strcpy(delref, ":"); |
| 57 | strcat(delref, ref); |
| 58 | ref = delref; |
| 59 | } else if (deleterefs) |
| 60 | die("--delete only accepts plain target ref names"); |
Daniel Barkalow | 8558fd9 | 2007-05-25 01:20:56 -0400 | [diff] [blame] | 61 | add_refspec(ref); |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 62 | } |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 63 | } |
| 64 | |
Finn Arne Gangstad | 5215374 | 2009-03-16 16:42:51 +0100 | [diff] [blame] | 65 | static void setup_push_tracking(void) |
| 66 | { |
| 67 | struct strbuf refspec = STRBUF_INIT; |
| 68 | struct branch *branch = branch_get(NULL); |
| 69 | if (!branch) |
| 70 | die("You are not currently on a branch."); |
| 71 | if (!branch->merge_nr) |
| 72 | die("The current branch %s is not tracking anything.", |
| 73 | branch->name); |
| 74 | if (branch->merge_nr != 1) |
| 75 | die("The current branch %s is tracking multiple branches, " |
| 76 | "refusing to push.", branch->name); |
| 77 | strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src); |
| 78 | add_refspec(refspec.buf); |
| 79 | } |
| 80 | |
| 81 | static void setup_default_push_refspecs(void) |
| 82 | { |
Finn Arne Gangstad | 5215374 | 2009-03-16 16:42:51 +0100 | [diff] [blame] | 83 | switch (push_default) { |
Junio C Hamano | bba0fd2 | 2009-07-18 17:19:47 -0700 | [diff] [blame] | 84 | default: |
Finn Arne Gangstad | 5215374 | 2009-03-16 16:42:51 +0100 | [diff] [blame] | 85 | case PUSH_DEFAULT_MATCHING: |
| 86 | add_refspec(":"); |
| 87 | break; |
| 88 | |
| 89 | case PUSH_DEFAULT_TRACKING: |
| 90 | setup_push_tracking(); |
| 91 | break; |
| 92 | |
| 93 | case PUSH_DEFAULT_CURRENT: |
| 94 | add_refspec("HEAD"); |
| 95 | break; |
| 96 | |
| 97 | case PUSH_DEFAULT_NOTHING: |
| 98 | die("You didn't specify any refspecs to push, and " |
| 99 | "push.default is \"nothing\"."); |
| 100 | break; |
| 101 | } |
| 102 | } |
| 103 | |
Daniel Barkalow | fb0cc87 | 2009-11-18 02:42:22 +0100 | [diff] [blame] | 104 | static int push_with_options(struct transport *transport, int flags) |
| 105 | { |
| 106 | int err; |
| 107 | int nonfastforward; |
| 108 | if (receivepack) |
| 109 | transport_set_option(transport, |
| 110 | TRANS_OPT_RECEIVEPACK, receivepack); |
| 111 | if (thin) |
| 112 | transport_set_option(transport, TRANS_OPT_THIN, "yes"); |
| 113 | |
| 114 | if (flags & TRANSPORT_PUSH_VERBOSE) |
| 115 | fprintf(stderr, "Pushing to %s\n", transport->url); |
| 116 | err = transport_push(transport, refspec_nr, refspec, flags, |
| 117 | &nonfastforward); |
Tay Ray Chuan | 53970b9 | 2009-12-04 07:31:44 +0800 | [diff] [blame] | 118 | if (err != 0) |
| 119 | error("failed to push some refs to '%s'", transport->url); |
| 120 | |
Daniel Barkalow | fb0cc87 | 2009-11-18 02:42:22 +0100 | [diff] [blame] | 121 | err |= transport_disconnect(transport); |
| 122 | |
| 123 | if (!err) |
| 124 | return 0; |
| 125 | |
Daniel Barkalow | fb0cc87 | 2009-11-18 02:42:22 +0100 | [diff] [blame] | 126 | if (nonfastforward && advice_push_nonfastforward) { |
| 127 | printf("To prevent you from losing history, non-fast-forward updates were rejected\n" |
Matthieu Moy | c0eb604 | 2010-01-11 22:09:44 +0100 | [diff] [blame] | 128 | "Merge the remote changes before pushing again. See the 'Note about\n" |
| 129 | "fast-forwards' section of 'git push --help' for details.\n"); |
Daniel Barkalow | fb0cc87 | 2009-11-18 02:42:22 +0100 | [diff] [blame] | 130 | } |
| 131 | |
| 132 | return 1; |
| 133 | } |
| 134 | |
Daniel Barkalow | 9b28851 | 2007-09-10 23:03:04 -0400 | [diff] [blame] | 135 | static int do_push(const char *repo, int flags) |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 136 | { |
Daniel Barkalow | 5751f49 | 2007-05-12 11:45:53 -0400 | [diff] [blame] | 137 | int i, errs; |
Daniel Barkalow | 5751f49 | 2007-05-12 11:45:53 -0400 | [diff] [blame] | 138 | struct remote *remote = remote_get(repo); |
Michael J Gruber | 2034623 | 2009-06-09 18:01:34 +0200 | [diff] [blame] | 139 | const char **url; |
| 140 | int url_nr; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 141 | |
Daniel Barkalow | fa685bd | 2009-03-11 01:47:20 -0400 | [diff] [blame] | 142 | if (!remote) { |
| 143 | if (repo) |
| 144 | die("bad repository '%s'", repo); |
| 145 | die("No destination configured to push to."); |
| 146 | } |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 147 | |
Paolo Bonzini | 84bb2df | 2008-04-17 13:17:20 +0200 | [diff] [blame] | 148 | if (remote->mirror) |
| 149 | flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE); |
| 150 | |
Marek Zawirski | b259f09 | 2008-08-16 19:58:32 +0200 | [diff] [blame] | 151 | if ((flags & TRANSPORT_PUSH_ALL) && refspec) { |
| 152 | if (!strcmp(*refspec, "refs/tags/*")) |
| 153 | return error("--all and --tags are incompatible"); |
| 154 | return error("--all can't be combined with refspecs"); |
| 155 | } |
| 156 | |
| 157 | if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) { |
| 158 | if (!strcmp(*refspec, "refs/tags/*")) |
| 159 | return error("--mirror and --tags are incompatible"); |
| 160 | return error("--mirror can't be combined with refspecs"); |
| 161 | } |
Paolo Bonzini | 84bb2df | 2008-04-17 13:17:20 +0200 | [diff] [blame] | 162 | |
| 163 | if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) == |
| 164 | (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) { |
| 165 | return error("--all and --mirror are incompatible"); |
| 166 | } |
| 167 | |
Finn Arne Gangstad | 5215374 | 2009-03-16 16:42:51 +0100 | [diff] [blame] | 168 | if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) { |
| 169 | if (remote->push_refspec_nr) { |
| 170 | refspec = remote->push_refspec; |
| 171 | refspec_nr = remote->push_refspec_nr; |
| 172 | } else if (!(flags & TRANSPORT_PUSH_MIRROR)) |
| 173 | setup_default_push_refspecs(); |
Daniel Barkalow | 5751f49 | 2007-05-12 11:45:53 -0400 | [diff] [blame] | 174 | } |
Junio C Hamano | fd1d1b0 | 2007-04-06 23:04:53 -0700 | [diff] [blame] | 175 | errs = 0; |
Michael J Gruber | 2034623 | 2009-06-09 18:01:34 +0200 | [diff] [blame] | 176 | if (remote->pushurl_nr) { |
| 177 | url = remote->pushurl; |
| 178 | url_nr = remote->pushurl_nr; |
| 179 | } else { |
| 180 | url = remote->url; |
| 181 | url_nr = remote->url_nr; |
| 182 | } |
Daniel Barkalow | fb0cc87 | 2009-11-18 02:42:22 +0100 | [diff] [blame] | 183 | if (url_nr) { |
| 184 | for (i = 0; i < url_nr; i++) { |
| 185 | struct transport *transport = |
| 186 | transport_get(remote, url[i]); |
| 187 | if (push_with_options(transport, flags)) |
| 188 | errs++; |
Matthieu Moy | 07436e4 | 2009-08-08 09:51:08 +0200 | [diff] [blame] | 189 | } |
Daniel Barkalow | fb0cc87 | 2009-11-18 02:42:22 +0100 | [diff] [blame] | 190 | } else { |
| 191 | struct transport *transport = |
| 192 | transport_get(remote, NULL); |
| 193 | |
| 194 | if (push_with_options(transport, flags)) |
| 195 | errs++; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 196 | } |
Junio C Hamano | fd1d1b0 | 2007-04-06 23:04:53 -0700 | [diff] [blame] | 197 | return !!errs; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 198 | } |
| 199 | |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 200 | int cmd_push(int argc, const char **argv, const char *prefix) |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 201 | { |
Daniel Barkalow | 9b28851 | 2007-09-10 23:03:04 -0400 | [diff] [blame] | 202 | int flags = 0; |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 203 | int tags = 0; |
Paolo Bonzini | 84bb2df | 2008-04-17 13:17:20 +0200 | [diff] [blame] | 204 | int rc; |
Daniel Barkalow | 5751f49 | 2007-05-12 11:45:53 -0400 | [diff] [blame] | 205 | const char *repo = NULL; /* default repository */ |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 206 | struct option options[] = { |
Jeff King | afdeeb0 | 2009-08-05 16:22:19 -0400 | [diff] [blame] | 207 | OPT_BIT('q', "quiet", &flags, "be quiet", TRANSPORT_PUSH_QUIET), |
Michele Ballabio | c29c1b4 | 2008-07-20 14:02:20 +0200 | [diff] [blame] | 208 | OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE), |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 209 | OPT_STRING( 0 , "repo", &repo, "repository", "repository"), |
Michele Ballabio | c29c1b4 | 2008-07-20 14:02:20 +0200 | [diff] [blame] | 210 | OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL), |
| 211 | OPT_BIT( 0 , "mirror", &flags, "mirror all refs", |
| 212 | (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), |
Jan Krüger | f517f1f | 2009-12-30 20:57:42 +0100 | [diff] [blame] | 213 | OPT_BOOLEAN( 0, "delete", &deleterefs, "delete refs"), |
Jeff King | f740cc2 | 2009-10-30 11:04:53 -0400 | [diff] [blame] | 214 | OPT_BOOLEAN( 0 , "tags", &tags, "push tags (can't be used with --all or --mirror)"), |
Nelson Elhage | 9f67fee | 2009-09-13 12:56:45 -0400 | [diff] [blame] | 215 | OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN), |
Larry D'Anna | 1965ff7 | 2009-06-22 21:10:01 -0400 | [diff] [blame] | 216 | OPT_BIT( 0, "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN), |
Michele Ballabio | c29c1b4 | 2008-07-20 14:02:20 +0200 | [diff] [blame] | 217 | OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE), |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 218 | OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"), |
| 219 | OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"), |
| 220 | OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"), |
Ilari Liusvaara | e9fcd1e | 2010-01-16 23:45:31 +0200 | [diff] [blame] | 221 | OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status", |
| 222 | TRANSPORT_PUSH_SET_UPSTREAM), |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 223 | OPT_END() |
| 224 | }; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 225 | |
Jeff King | 2aae905 | 2009-10-25 15:15:22 -0400 | [diff] [blame] | 226 | git_config(git_default_config, NULL); |
Stephen Boyd | 3778292 | 2009-05-23 11:53:12 -0700 | [diff] [blame] | 227 | argc = parse_options(argc, argv, prefix, options, push_usage, 0); |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 228 | |
Jan Krüger | f517f1f | 2009-12-30 20:57:42 +0100 | [diff] [blame] | 229 | if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR)))) |
| 230 | die("--delete is incompatible with --all, --mirror and --tags"); |
| 231 | if (deleterefs && argc < 2) |
| 232 | die("--delete doesn't make sense without any refs"); |
| 233 | |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 234 | if (tags) |
| 235 | add_refspec("refs/tags/*"); |
Daniel Barkalow | 378c483 | 2007-11-04 22:35:37 -0500 | [diff] [blame] | 236 | |
| 237 | if (argc > 0) { |
| 238 | repo = argv[0]; |
| 239 | set_refspecs(argv + 1, argc - 1); |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 240 | } |
Daniel Barkalow | 8558fd9 | 2007-05-25 01:20:56 -0400 | [diff] [blame] | 241 | |
Paolo Bonzini | 84bb2df | 2008-04-17 13:17:20 +0200 | [diff] [blame] | 242 | rc = do_push(repo, flags); |
| 243 | if (rc == -1) |
Andy Whitcroft | 94c89ba | 2007-11-09 23:32:25 +0000 | [diff] [blame] | 244 | usage_with_options(push_usage, options); |
Paolo Bonzini | 84bb2df | 2008-04-17 13:17:20 +0200 | [diff] [blame] | 245 | else |
| 246 | return rc; |
Linus Torvalds | 755225d | 2006-04-29 21:22:49 -0700 | [diff] [blame] | 247 | } |