blob: 9a2228ebb46df721741db2249ab25cce5dfb4282 [file] [log] [blame]
Brian Gesiak303d1d02014-02-28 15:43:33 +09001#include "git-compat-util.h"
Daniel Barkalowe496c002008-02-07 11:40:08 -05002#include "cache.h"
3#include "branch.h"
4#include "refs.h"
5#include "remote.h"
6#include "commit.h"
7
8struct tracking {
9 struct refspec spec;
10 char *src;
11 const char *remote;
12 int matches;
13};
14
15static int find_tracked_branch(struct remote *remote, void *priv)
16{
17 struct tracking *tracking = priv;
18
19 if (!remote_find_tracking(remote, &tracking->spec)) {
20 if (++tracking->matches == 1) {
21 tracking->src = tracking->spec.src;
22 tracking->remote = remote->name;
23 } else {
24 free(tracking->spec.src);
25 if (tracking->src) {
26 free(tracking->src);
27 tracking->src = NULL;
28 }
29 }
30 tracking->spec.src = NULL;
31 }
32
33 return 0;
34}
35
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080036static int should_setup_rebase(const char *origin)
Dustin Sallingsc998ae92008-05-10 15:36:29 -070037{
38 switch (autorebase) {
39 case AUTOREBASE_NEVER:
40 return 0;
41 case AUTOREBASE_LOCAL:
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080042 return origin == NULL;
Dustin Sallingsc998ae92008-05-10 15:36:29 -070043 case AUTOREBASE_REMOTE:
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080044 return origin != NULL;
Dustin Sallingsc998ae92008-05-10 15:36:29 -070045 case AUTOREBASE_ALWAYS:
46 return 1;
47 }
48 return 0;
49}
50
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080051void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
52{
Jeff Kingcf4fff52014-06-18 15:44:19 -040053 const char *shortname = NULL;
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080054 struct strbuf key = STRBUF_INIT;
55 int rebasing = should_setup_rebase(origin);
56
Jeff Kingcf4fff52014-06-18 15:44:19 -040057 if (skip_prefix(remote, "refs/heads/", &shortname)
Matthieu Moy85e22332010-01-18 22:44:12 +020058 && !strcmp(local, shortname)
59 && !origin) {
Jiang Xinbc554df2013-04-16 11:37:50 +080060 warning(_("Not setting branch %s as its own upstream."),
Matthieu Moy85e22332010-01-18 22:44:12 +020061 local);
62 return;
63 }
64
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080065 strbuf_addf(&key, "branch.%s.remote", local);
66 git_config_set(key.buf, origin ? origin : ".");
67
68 strbuf_reset(&key);
69 strbuf_addf(&key, "branch.%s.merge", local);
70 git_config_set(key.buf, remote);
71
72 if (rebasing) {
73 strbuf_reset(&key);
74 strbuf_addf(&key, "branch.%s.rebase", local);
75 git_config_set(key.buf, "true");
76 }
Nguyễn Thái Ngọc Duyd53a35032012-06-07 19:05:10 +070077 strbuf_release(&key);
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080078
Junio C Hamano72f60082009-03-10 01:20:42 -070079 if (flag & BRANCH_CONFIG_VERBOSE) {
Junio C Hamano1d9aaed2014-03-31 16:31:19 -070080 if (shortname) {
Adam9fe0cf32014-03-10 01:32:01 -040081 if (origin)
82 printf_ln(rebasing ?
83 _("Branch %s set up to track remote branch %s from %s by rebasing.") :
84 _("Branch %s set up to track remote branch %s from %s."),
85 local, shortname, origin);
86 else
87 printf_ln(rebasing ?
88 _("Branch %s set up to track local branch %s by rebasing.") :
89 _("Branch %s set up to track local branch %s."),
90 local, shortname);
91 } else {
92 if (origin)
93 printf_ln(rebasing ?
94 _("Branch %s set up to track remote ref %s by rebasing.") :
95 _("Branch %s set up to track remote ref %s."),
96 local, remote);
97 else
98 printf_ln(rebasing ?
99 _("Branch %s set up to track local ref %s by rebasing.") :
100 _("Branch %s set up to track local ref %s."),
101 local, remote);
102 }
Junio C Hamano72f60082009-03-10 01:20:42 -0700103 }
Junio C Hamanoa9f2c132009-03-03 22:29:55 -0800104}
105
Daniel Barkalowe496c002008-02-07 11:40:08 -0500106/*
107 * This is called when new_ref is branched off of orig_ref, and tries
108 * to infer the settings for branch.<new_ref>.{remote,merge} from the
109 * config.
110 */
Jay Soffian9ed36cf2008-02-19 11:24:37 -0500111static int setup_tracking(const char *new_ref, const char *orig_ref,
Jeff Kingf9a482e2012-03-26 19:51:01 -0400112 enum branch_track track, int quiet)
Daniel Barkalowe496c002008-02-07 11:40:08 -0500113{
Daniel Barkalowe496c002008-02-07 11:40:08 -0500114 struct tracking tracking;
Jeff Kingf9a482e2012-03-26 19:51:01 -0400115 int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
Daniel Barkalowe496c002008-02-07 11:40:08 -0500116
Daniel Barkalowe496c002008-02-07 11:40:08 -0500117 memset(&tracking, 0, sizeof(tracking));
118 tracking.spec.dst = (char *)orig_ref;
Jay Soffian9ed36cf2008-02-19 11:24:37 -0500119 if (for_each_remote(find_tracked_branch, &tracking))
Daniel Barkalowe496c002008-02-07 11:40:08 -0500120 return 1;
121
Jay Soffian9ed36cf2008-02-19 11:24:37 -0500122 if (!tracking.matches)
123 switch (track) {
124 case BRANCH_TRACK_ALWAYS:
125 case BRANCH_TRACK_EXPLICIT:
Ilari Liusvaara4fc50062010-01-18 22:44:11 +0200126 case BRANCH_TRACK_OVERRIDE:
Jay Soffian9ed36cf2008-02-19 11:24:37 -0500127 break;
128 default:
129 return 1;
130 }
131
Daniel Barkalowe496c002008-02-07 11:40:08 -0500132 if (tracking.matches > 1)
Jiang Xinbc554df2013-04-16 11:37:50 +0800133 return error(_("Not tracking: ambiguous information for ref %s"),
Daniel Barkalowe496c002008-02-07 11:40:08 -0500134 orig_ref);
135
Jeff Kingf9a482e2012-03-26 19:51:01 -0400136 install_branch_config(config_flags, new_ref, tracking.remote,
Junio C Hamanoa9f2c132009-03-03 22:29:55 -0800137 tracking.src ? tracking.src : orig_ref);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500138
Junio C Hamanoa9f2c132009-03-03 22:29:55 -0800139 free(tracking.src);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500140 return 0;
141}
142
Junio C Hamano6f9a3322011-09-21 20:19:38 -0700143int read_branch_desc(struct strbuf *buf, const char *branch_name)
144{
Tanay Abhra540b0f42014-08-07 23:26:42 +0530145 char *v = NULL;
Junio C Hamano6f9a3322011-09-21 20:19:38 -0700146 struct strbuf name = STRBUF_INIT;
147 strbuf_addf(&name, "branch.%s.description", branch_name);
Tanay Abhra540b0f42014-08-07 23:26:42 +0530148 if (git_config_get_string(name.buf, &v)) {
149 strbuf_release(&name);
150 return -1;
151 }
152 strbuf_addstr(buf, v);
153 free(v);
Junio C Hamano6f9a3322011-09-21 20:19:38 -0700154 strbuf_release(&name);
155 return 0;
156}
157
Junio C Hamanofa799372011-09-16 16:28:38 -0700158int validate_new_branchname(const char *name, struct strbuf *ref,
159 int force, int attr_only)
Conrad Irwin55c4a672011-08-20 14:49:48 -0700160{
Conrad Irwin55c4a672011-08-20 14:49:48 -0700161 if (strbuf_check_branch_ref(ref, name))
Jiang Xinbc554df2013-04-16 11:37:50 +0800162 die(_("'%s' is not a valid branch name."), name);
Conrad Irwin55c4a672011-08-20 14:49:48 -0700163
164 if (!ref_exists(ref->buf))
165 return 0;
Junio C Hamanofa799372011-09-16 16:28:38 -0700166 else if (!force && !attr_only)
Jiang Xinbc554df2013-04-16 11:37:50 +0800167 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
Conrad Irwin55c4a672011-08-20 14:49:48 -0700168
Junio C Hamanofa799372011-09-16 16:28:38 -0700169 if (!attr_only) {
170 const char *head;
171 unsigned char sha1[20];
Conrad Irwin55c4a672011-08-20 14:49:48 -0700172
Nguyễn Thái Ngọc Duy8cad4742011-12-12 18:20:32 +0700173 head = resolve_ref_unsafe("HEAD", sha1, 0, NULL);
Junio C Hamanofa799372011-09-16 16:28:38 -0700174 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
Jiang Xinbc554df2013-04-16 11:37:50 +0800175 die(_("Cannot force update the current branch."));
Junio C Hamanofa799372011-09-16 16:28:38 -0700176 }
Conrad Irwin55c4a672011-08-20 14:49:48 -0700177 return 1;
178}
179
Johan Herland41c21f22013-04-21 23:52:05 +0200180static int check_tracking_branch(struct remote *remote, void *cb_data)
181{
182 char *tracking_branch = cb_data;
183 struct refspec query;
184 memset(&query, 0, sizeof(struct refspec));
185 query.dst = tracking_branch;
Per Cederqvist1d7358c2013-09-08 22:58:15 +0200186 return !remote_find_tracking(remote, &query);
Johan Herland41c21f22013-04-21 23:52:05 +0200187}
188
189static int validate_remote_tracking_branch(char *ref)
190{
191 return !for_each_remote(check_tracking_branch, ref);
192}
193
Jeff Kinge2b6aa52013-04-02 15:03:55 -0400194static const char upstream_not_branch[] =
Jeff King1a15d002013-04-02 15:04:51 -0400195N_("Cannot setup tracking information; starting point '%s' is not a branch.");
Jeff Kinga5e91c72013-04-02 15:04:27 -0400196static const char upstream_missing[] =
Jeff Kingcaa20362013-04-02 15:05:12 -0400197N_("the requested upstream branch '%s' does not exist");
198static const char upstream_advice[] =
199N_("\n"
200"If you are planning on basing your work on an upstream\n"
201"branch that already exists at the remote, you may need to\n"
202"run \"git fetch\" to retrieve it.\n"
203"\n"
204"If you are planning to push out a new local branch that\n"
205"will track its remote counterpart, you may want to use\n"
206"\"git push -u\" to set the upstream config as you push.");
Jeff Kinge2b6aa52013-04-02 15:03:55 -0400207
Daniel Barkalowe496c002008-02-07 11:40:08 -0500208void create_branch(const char *head,
209 const char *name, const char *start_name,
Jonathan Nieder39bd6f72011-11-26 02:54:55 -0600210 int force, int reflog, int clobber_head,
Jeff Kingf9a482e2012-03-26 19:51:01 -0400211 int quiet, enum branch_track track)
Daniel Barkalowe496c002008-02-07 11:40:08 -0500212{
Daniel Barkalowe496c002008-02-07 11:40:08 -0500213 struct commit *commit;
214 unsigned char sha1[20];
Junio C Hamano8415d5c2009-02-13 23:08:05 -0800215 char *real_ref, msg[PATH_MAX + 20];
216 struct strbuf ref = STRBUF_INIT;
Daniel Barkalowe496c002008-02-07 11:40:08 -0500217 int forcing = 0;
Ilari Liusvaara4fc50062010-01-18 22:44:11 +0200218 int dont_change_ref = 0;
219 int explicit_tracking = 0;
220
221 if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
222 explicit_tracking = 1;
Daniel Barkalowe496c002008-02-07 11:40:08 -0500223
Junio C Hamanofa799372011-09-16 16:28:38 -0700224 if (validate_new_branchname(name, &ref, force,
Jonathan Nieder39bd6f72011-11-26 02:54:55 -0600225 track == BRANCH_TRACK_OVERRIDE ||
226 clobber_head)) {
Conrad Irwin55c4a672011-08-20 14:49:48 -0700227 if (!force)
Ilari Liusvaara4fc50062010-01-18 22:44:11 +0200228 dont_change_ref = 1;
Conrad Irwin55c4a672011-08-20 14:49:48 -0700229 else
230 forcing = 1;
Daniel Barkalowe496c002008-02-07 11:40:08 -0500231 }
232
233 real_ref = NULL;
Jeff Kinga5e91c72013-04-02 15:04:27 -0400234 if (get_sha1(start_name, sha1)) {
Jeff Kingcaa20362013-04-02 15:05:12 -0400235 if (explicit_tracking) {
236 if (advice_set_upstream_failure) {
237 error(_(upstream_missing), start_name);
238 advise(_(upstream_advice));
239 exit(1);
240 }
Jeff King1a15d002013-04-02 15:04:51 -0400241 die(_(upstream_missing), start_name);
Jeff Kingcaa20362013-04-02 15:05:12 -0400242 }
Jiang Xinbc554df2013-04-16 11:37:50 +0800243 die(_("Not a valid object name: '%s'."), start_name);
Jeff Kinga5e91c72013-04-02 15:04:27 -0400244 }
Daniel Barkalowe496c002008-02-07 11:40:08 -0500245
246 switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
247 case 0:
248 /* Not branching from any existing branch */
Ilari Liusvaara4fc50062010-01-18 22:44:11 +0200249 if (explicit_tracking)
Jeff King1a15d002013-04-02 15:04:51 -0400250 die(_(upstream_not_branch), start_name);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500251 break;
252 case 1:
Johan Herland21b5b1e2011-02-17 00:12:20 +0100253 /* Unique completion -- good, only if it is a real branch */
Christian Couder59556542013-11-30 21:55:40 +0100254 if (!starts_with(real_ref, "refs/heads/") &&
Johan Herland41c21f22013-04-21 23:52:05 +0200255 validate_remote_tracking_branch(real_ref)) {
Johan Herland21b5b1e2011-02-17 00:12:20 +0100256 if (explicit_tracking)
Jeff King1a15d002013-04-02 15:04:51 -0400257 die(_(upstream_not_branch), start_name);
Johan Herland21b5b1e2011-02-17 00:12:20 +0100258 else
259 real_ref = NULL;
260 }
Daniel Barkalowe496c002008-02-07 11:40:08 -0500261 break;
262 default:
Jiang Xinbc554df2013-04-16 11:37:50 +0800263 die(_("Ambiguous object name: '%s'."), start_name);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500264 break;
265 }
266
267 if ((commit = lookup_commit_reference(sha1)) == NULL)
Jiang Xinbc554df2013-04-16 11:37:50 +0800268 die(_("Not a valid branch point: '%s'."), start_name);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500269 hashcpy(sha1, commit->object.sha1);
270
Daniel Barkalowe496c002008-02-07 11:40:08 -0500271 if (forcing)
Junio C Hamanoda288e22010-04-09 20:42:10 -0700272 snprintf(msg, sizeof msg, "branch: Reset to %s",
Daniel Barkalowe496c002008-02-07 11:40:08 -0500273 start_name);
Ilari Liusvaara4fc50062010-01-18 22:44:11 +0200274 else if (!dont_change_ref)
Daniel Barkalowe496c002008-02-07 11:40:08 -0500275 snprintf(msg, sizeof msg, "branch: Created from %s",
276 start_name);
277
Ronnie Sahlbergd43f9902014-04-16 16:21:53 -0700278 if (reflog)
279 log_all_ref_updates = 1;
280
281 if (!dont_change_ref) {
282 struct ref_transaction *transaction;
283 struct strbuf err = STRBUF_INIT;
284
285 transaction = ref_transaction_begin(&err);
286 if (!transaction ||
287 ref_transaction_update(transaction, ref.buf, sha1,
288 null_sha1, 0, !forcing, &err) ||
289 ref_transaction_commit(transaction, msg, &err))
290 die("%s", err.buf);
291 ref_transaction_free(transaction);
292 strbuf_release(&err);
293 }
294
Daniel Barkalowe496c002008-02-07 11:40:08 -0500295 if (real_ref && track)
Felipe Contreras82a06722013-08-30 16:56:46 -0500296 setup_tracking(ref.buf + 11, real_ref, track, quiet);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500297
Junio C Hamano8415d5c2009-02-13 23:08:05 -0800298 strbuf_release(&ref);
Jay Soffian9ed36cf2008-02-19 11:24:37 -0500299 free(real_ref);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500300}
Daniel Barkalowc369e7b2008-02-07 11:40:16 -0500301
302void remove_branch_state(void)
303{
Jay Soffiand7e5c0c2011-02-19 23:12:27 -0500304 unlink(git_path("CHERRY_PICK_HEAD"));
Jonathan Nieder82433cd2011-11-22 05:17:36 -0600305 unlink(git_path("REVERT_HEAD"));
Daniel Barkalowc369e7b2008-02-07 11:40:16 -0500306 unlink(git_path("MERGE_HEAD"));
Johannes Schindelin0af0ac72008-07-12 15:56:19 +0100307 unlink(git_path("MERGE_RR"));
Daniel Barkalowc369e7b2008-02-07 11:40:16 -0500308 unlink(git_path("MERGE_MSG"));
Miklos Vajnacf10f9f2008-10-03 14:04:47 +0200309 unlink(git_path("MERGE_MODE"));
Daniel Barkalowc369e7b2008-02-07 11:40:16 -0500310 unlink(git_path("SQUASH_MSG"));
311}