blob: e70838fb872f98820a641ccaccc06fd4c0c381f7 [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"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07003#include "config.h"
Daniel Barkalowe496c002008-02-07 11:40:08 -05004#include "branch.h"
5#include "refs.h"
Brandon Williamsec0cb492018-05-16 15:57:48 -07006#include "refspec.h"
Daniel Barkalowe496c002008-02-07 11:40:08 -05007#include "remote.h"
Phillip Woodb07d9bf2019-04-16 11:18:41 +01008#include "sequencer.h"
Daniel Barkalowe496c002008-02-07 11:40:08 -05009#include "commit.h"
Michael Rappazzoac6c5612015-10-02 07:55:31 -040010#include "worktree.h"
Daniel Barkalowe496c002008-02-07 11:40:08 -050011
12struct tracking {
Brandon Williams0ad4a5f2018-05-16 15:57:49 -070013 struct refspec_item spec;
Daniel Barkalowe496c002008-02-07 11:40:08 -050014 char *src;
15 const char *remote;
16 int matches;
17};
18
19static int find_tracked_branch(struct remote *remote, void *priv)
20{
21 struct tracking *tracking = priv;
22
23 if (!remote_find_tracking(remote, &tracking->spec)) {
24 if (++tracking->matches == 1) {
25 tracking->src = tracking->spec.src;
26 tracking->remote = remote->name;
27 } else {
28 free(tracking->spec.src);
Ævar Arnfjörð Bjarmasonce528de2018-08-17 13:02:50 +000029 FREE_AND_NULL(tracking->src);
Daniel Barkalowe496c002008-02-07 11:40:08 -050030 }
31 tracking->spec.src = NULL;
32 }
33
34 return 0;
35}
36
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080037static int should_setup_rebase(const char *origin)
Dustin Sallingsc998ae92008-05-10 15:36:29 -070038{
39 switch (autorebase) {
40 case AUTOREBASE_NEVER:
41 return 0;
42 case AUTOREBASE_LOCAL:
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080043 return origin == NULL;
Dustin Sallingsc998ae92008-05-10 15:36:29 -070044 case AUTOREBASE_REMOTE:
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080045 return origin != NULL;
Dustin Sallingsc998ae92008-05-10 15:36:29 -070046 case AUTOREBASE_ALWAYS:
47 return 1;
48 }
49 return 0;
50}
51
Patrick Steinhardt27852b22016-02-22 12:23:23 +010052static const char tracking_advice[] =
53N_("\n"
54"After fixing the error cause you may try to fix up\n"
55"the remote tracking information by invoking\n"
56"\"git branch --set-upstream-to=%s%s%s\".");
57
58int install_branch_config(int flag, const char *local, const char *origin, const char *remote)
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080059{
Jeff Kingcf4fff52014-06-18 15:44:19 -040060 const char *shortname = NULL;
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080061 struct strbuf key = STRBUF_INIT;
62 int rebasing = should_setup_rebase(origin);
63
Jeff Kingcf4fff52014-06-18 15:44:19 -040064 if (skip_prefix(remote, "refs/heads/", &shortname)
Matthieu Moy85e22332010-01-18 22:44:12 +020065 && !strcmp(local, shortname)
66 && !origin) {
Jiang Xinbc554df2013-04-16 11:37:50 +080067 warning(_("Not setting branch %s as its own upstream."),
Matthieu Moy85e22332010-01-18 22:44:12 +020068 local);
Patrick Steinhardt27852b22016-02-22 12:23:23 +010069 return 0;
Matthieu Moy85e22332010-01-18 22:44:12 +020070 }
71
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080072 strbuf_addf(&key, "branch.%s.remote", local);
Patrick Steinhardt30598ad2016-02-22 12:23:35 +010073 if (git_config_set_gently(key.buf, origin ? origin : ".") < 0)
Patrick Steinhardt27852b22016-02-22 12:23:23 +010074 goto out_err;
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080075
76 strbuf_reset(&key);
77 strbuf_addf(&key, "branch.%s.merge", local);
Patrick Steinhardt30598ad2016-02-22 12:23:35 +010078 if (git_config_set_gently(key.buf, remote) < 0)
Patrick Steinhardt27852b22016-02-22 12:23:23 +010079 goto out_err;
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080080
81 if (rebasing) {
82 strbuf_reset(&key);
83 strbuf_addf(&key, "branch.%s.rebase", local);
Patrick Steinhardt30598ad2016-02-22 12:23:35 +010084 if (git_config_set_gently(key.buf, "true") < 0)
Patrick Steinhardt27852b22016-02-22 12:23:23 +010085 goto out_err;
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080086 }
Nguyễn Thái Ngọc Duyd53a35032012-06-07 19:05:10 +070087 strbuf_release(&key);
Junio C Hamanoa9f2c132009-03-03 22:29:55 -080088
Junio C Hamano72f60082009-03-10 01:20:42 -070089 if (flag & BRANCH_CONFIG_VERBOSE) {
Junio C Hamano1d9aaed2014-03-31 16:31:19 -070090 if (shortname) {
Adam9fe0cf32014-03-10 01:32:01 -040091 if (origin)
92 printf_ln(rebasing ?
Kaartic Sivaraam9c93ff72017-08-17 08:24:25 +053093 _("Branch '%s' set up to track remote branch '%s' from '%s' by rebasing.") :
94 _("Branch '%s' set up to track remote branch '%s' from '%s'."),
Adam9fe0cf32014-03-10 01:32:01 -040095 local, shortname, origin);
96 else
97 printf_ln(rebasing ?
Kaartic Sivaraam9c93ff72017-08-17 08:24:25 +053098 _("Branch '%s' set up to track local branch '%s' by rebasing.") :
99 _("Branch '%s' set up to track local branch '%s'."),
Adam9fe0cf32014-03-10 01:32:01 -0400100 local, shortname);
101 } else {
102 if (origin)
103 printf_ln(rebasing ?
Kaartic Sivaraam9c93ff72017-08-17 08:24:25 +0530104 _("Branch '%s' set up to track remote ref '%s' by rebasing.") :
105 _("Branch '%s' set up to track remote ref '%s'."),
Adam9fe0cf32014-03-10 01:32:01 -0400106 local, remote);
107 else
108 printf_ln(rebasing ?
Kaartic Sivaraam9c93ff72017-08-17 08:24:25 +0530109 _("Branch '%s' set up to track local ref '%s' by rebasing.") :
110 _("Branch '%s' set up to track local ref '%s'."),
Adam9fe0cf32014-03-10 01:32:01 -0400111 local, remote);
112 }
Junio C Hamano72f60082009-03-10 01:20:42 -0700113 }
Patrick Steinhardt27852b22016-02-22 12:23:23 +0100114
115 return 0;
116
117out_err:
118 strbuf_release(&key);
119 error(_("Unable to write upstream branch configuration"));
120
121 advise(_(tracking_advice),
122 origin ? origin : "",
123 origin ? "/" : "",
124 shortname ? shortname : remote);
125
126 return -1;
Junio C Hamanoa9f2c132009-03-03 22:29:55 -0800127}
128
Daniel Barkalowe496c002008-02-07 11:40:08 -0500129/*
130 * This is called when new_ref is branched off of orig_ref, and tries
131 * to infer the settings for branch.<new_ref>.{remote,merge} from the
132 * config.
133 */
Patrick Steinhardt27852b22016-02-22 12:23:23 +0100134static void setup_tracking(const char *new_ref, const char *orig_ref,
135 enum branch_track track, int quiet)
Daniel Barkalowe496c002008-02-07 11:40:08 -0500136{
Daniel Barkalowe496c002008-02-07 11:40:08 -0500137 struct tracking tracking;
Jeff Kingf9a482e2012-03-26 19:51:01 -0400138 int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
Daniel Barkalowe496c002008-02-07 11:40:08 -0500139
Daniel Barkalowe496c002008-02-07 11:40:08 -0500140 memset(&tracking, 0, sizeof(tracking));
141 tracking.spec.dst = (char *)orig_ref;
Jay Soffian9ed36cf2008-02-19 11:24:37 -0500142 if (for_each_remote(find_tracked_branch, &tracking))
Patrick Steinhardt27852b22016-02-22 12:23:23 +0100143 return;
Daniel Barkalowe496c002008-02-07 11:40:08 -0500144
Jay Soffian9ed36cf2008-02-19 11:24:37 -0500145 if (!tracking.matches)
146 switch (track) {
147 case BRANCH_TRACK_ALWAYS:
148 case BRANCH_TRACK_EXPLICIT:
Ilari Liusvaara4fc50062010-01-18 22:44:11 +0200149 case BRANCH_TRACK_OVERRIDE:
Jay Soffian9ed36cf2008-02-19 11:24:37 -0500150 break;
151 default:
Patrick Steinhardt27852b22016-02-22 12:23:23 +0100152 return;
Jay Soffian9ed36cf2008-02-19 11:24:37 -0500153 }
154
Daniel Barkalowe496c002008-02-07 11:40:08 -0500155 if (tracking.matches > 1)
Patrick Steinhardt27852b22016-02-22 12:23:23 +0100156 die(_("Not tracking: ambiguous information for ref %s"),
157 orig_ref);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500158
Patrick Steinhardt27852b22016-02-22 12:23:23 +0100159 if (install_branch_config(config_flags, new_ref, tracking.remote,
160 tracking.src ? tracking.src : orig_ref) < 0)
161 exit(-1);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500162
Junio C Hamanoa9f2c132009-03-03 22:29:55 -0800163 free(tracking.src);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500164}
165
Junio C Hamano6f9a3322011-09-21 20:19:38 -0700166int read_branch_desc(struct strbuf *buf, const char *branch_name)
167{
Tanay Abhra540b0f42014-08-07 23:26:42 +0530168 char *v = NULL;
Junio C Hamano6f9a3322011-09-21 20:19:38 -0700169 struct strbuf name = STRBUF_INIT;
170 strbuf_addf(&name, "branch.%s.description", branch_name);
Tanay Abhra540b0f42014-08-07 23:26:42 +0530171 if (git_config_get_string(name.buf, &v)) {
172 strbuf_release(&name);
173 return -1;
174 }
175 strbuf_addstr(buf, v);
176 free(v);
Junio C Hamano6f9a3322011-09-21 20:19:38 -0700177 strbuf_release(&name);
178 return 0;
179}
180
Junio C Hamanobc1c9c02017-10-13 13:45:40 +0900181/*
182 * Check if 'name' can be a valid name for a branch; die otherwise.
183 * Return 1 if the named branch already exists; return 0 otherwise.
184 * Fill ref with the full refname for the branch.
185 */
186int validate_branchname(const char *name, struct strbuf *ref)
Conrad Irwin55c4a672011-08-20 14:49:48 -0700187{
Conrad Irwin55c4a672011-08-20 14:49:48 -0700188 if (strbuf_check_branch_ref(ref, name))
Jiang Xinbc554df2013-04-16 11:37:50 +0800189 die(_("'%s' is not a valid branch name."), name);
Conrad Irwin55c4a672011-08-20 14:49:48 -0700190
Junio C Hamanobc1c9c02017-10-13 13:45:40 +0900191 return ref_exists(ref->buf);
192}
Conrad Irwin55c4a672011-08-20 14:49:48 -0700193
Junio C Hamanobc1c9c02017-10-13 13:45:40 +0900194/*
195 * Check if a branch 'name' can be created as a new branch; die otherwise.
196 * 'force' can be used when it is OK for the named branch already exists.
197 * Return 1 if the named branch already exists; return 0 otherwise.
198 * Fill ref with the full refname for the branch.
199 */
200int validate_new_branchname(const char *name, struct strbuf *ref, int force)
201{
202 const char *head;
203
204 if (!validate_branchname(name, ref))
Conrad Irwin55c4a672011-08-20 14:49:48 -0700205 return 0;
Conrad Irwin55c4a672011-08-20 14:49:48 -0700206
Junio C Hamano8280c4c2017-10-13 12:57:02 +0900207 if (!force)
208 die(_("A branch named '%s' already exists."),
209 ref->buf + strlen("refs/heads/"));
Conrad Irwin55c4a672011-08-20 14:49:48 -0700210
Junio C Hamano8280c4c2017-10-13 12:57:02 +0900211 head = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
212 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
213 die(_("Cannot force update the current branch."));
214
Conrad Irwin55c4a672011-08-20 14:49:48 -0700215 return 1;
216}
217
Johan Herland41c21f22013-04-21 23:52:05 +0200218static int check_tracking_branch(struct remote *remote, void *cb_data)
219{
220 char *tracking_branch = cb_data;
Brandon Williams0ad4a5f2018-05-16 15:57:49 -0700221 struct refspec_item query;
222 memset(&query, 0, sizeof(struct refspec_item));
Johan Herland41c21f22013-04-21 23:52:05 +0200223 query.dst = tracking_branch;
Per Cederqvist1d7358c2013-09-08 22:58:15 +0200224 return !remote_find_tracking(remote, &query);
Johan Herland41c21f22013-04-21 23:52:05 +0200225}
226
227static int validate_remote_tracking_branch(char *ref)
228{
229 return !for_each_remote(check_tracking_branch, ref);
230}
231
Jeff Kinge2b6aa52013-04-02 15:03:55 -0400232static const char upstream_not_branch[] =
Jeff King1a15d002013-04-02 15:04:51 -0400233N_("Cannot setup tracking information; starting point '%s' is not a branch.");
Jeff Kinga5e91c72013-04-02 15:04:27 -0400234static const char upstream_missing[] =
Jeff Kingcaa20362013-04-02 15:05:12 -0400235N_("the requested upstream branch '%s' does not exist");
236static const char upstream_advice[] =
237N_("\n"
238"If you are planning on basing your work on an upstream\n"
239"branch that already exists at the remote, you may need to\n"
240"run \"git fetch\" to retrieve it.\n"
241"\n"
242"If you are planning to push out a new local branch that\n"
243"will track its remote counterpart, you may want to use\n"
244"\"git push -u\" to set the upstream config as you push.");
Jeff Kinge2b6aa52013-04-02 15:03:55 -0400245
Nguyễn Thái Ngọc Duy4edce172018-11-10 06:49:00 +0100246void create_branch(struct repository *r,
247 const char *name, const char *start_name,
Kaartic Sivaraame2bbd0c2017-11-18 22:56:46 +0530248 int force, int clobber_head_ok, int reflog,
Jeff Kingf9a482e2012-03-26 19:51:01 -0400249 int quiet, enum branch_track track)
Daniel Barkalowe496c002008-02-07 11:40:08 -0500250{
Daniel Barkalowe496c002008-02-07 11:40:08 -0500251 struct commit *commit;
brian m. carlson48713bf2017-05-01 02:29:00 +0000252 struct object_id oid;
Jeff King3818b252017-03-28 15:46:36 -0400253 char *real_ref;
Junio C Hamano8415d5c2009-02-13 23:08:05 -0800254 struct strbuf ref = STRBUF_INIT;
Daniel Barkalowe496c002008-02-07 11:40:08 -0500255 int forcing = 0;
Ilari Liusvaara4fc50062010-01-18 22:44:11 +0200256 int dont_change_ref = 0;
257 int explicit_tracking = 0;
258
259 if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
260 explicit_tracking = 1;
Daniel Barkalowe496c002008-02-07 11:40:08 -0500261
Junio C Hamano0faff982017-12-27 11:16:25 -0800262 if ((track == BRANCH_TRACK_OVERRIDE || clobber_head_ok)
Junio C Hamanobc1c9c02017-10-13 13:45:40 +0900263 ? validate_branchname(name, &ref)
264 : validate_new_branchname(name, &ref, force)) {
Conrad Irwin55c4a672011-08-20 14:49:48 -0700265 if (!force)
Ilari Liusvaara4fc50062010-01-18 22:44:11 +0200266 dont_change_ref = 1;
Conrad Irwin55c4a672011-08-20 14:49:48 -0700267 else
268 forcing = 1;
Daniel Barkalowe496c002008-02-07 11:40:08 -0500269 }
270
271 real_ref = NULL;
Denton Liue3d65392019-04-27 05:02:22 -0700272 if (get_oid_mb(start_name, &oid)) {
Jeff Kingcaa20362013-04-02 15:05:12 -0400273 if (explicit_tracking) {
274 if (advice_set_upstream_failure) {
275 error(_(upstream_missing), start_name);
276 advise(_(upstream_advice));
277 exit(1);
278 }
Jeff King1a15d002013-04-02 15:04:51 -0400279 die(_(upstream_missing), start_name);
Jeff Kingcaa20362013-04-02 15:05:12 -0400280 }
Jiang Xinbc554df2013-04-16 11:37:50 +0800281 die(_("Not a valid object name: '%s'."), start_name);
Jeff Kinga5e91c72013-04-02 15:04:27 -0400282 }
Daniel Barkalowe496c002008-02-07 11:40:08 -0500283
brian m. carlsoncca5fa62017-10-15 22:06:57 +0000284 switch (dwim_ref(start_name, strlen(start_name), &oid, &real_ref)) {
Daniel Barkalowe496c002008-02-07 11:40:08 -0500285 case 0:
286 /* Not branching from any existing branch */
Ilari Liusvaara4fc50062010-01-18 22:44:11 +0200287 if (explicit_tracking)
Jeff King1a15d002013-04-02 15:04:51 -0400288 die(_(upstream_not_branch), start_name);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500289 break;
290 case 1:
Johan Herland21b5b1e2011-02-17 00:12:20 +0100291 /* Unique completion -- good, only if it is a real branch */
Christian Couder59556542013-11-30 21:55:40 +0100292 if (!starts_with(real_ref, "refs/heads/") &&
Johan Herland41c21f22013-04-21 23:52:05 +0200293 validate_remote_tracking_branch(real_ref)) {
Johan Herland21b5b1e2011-02-17 00:12:20 +0100294 if (explicit_tracking)
Jeff King1a15d002013-04-02 15:04:51 -0400295 die(_(upstream_not_branch), start_name);
Johan Herland21b5b1e2011-02-17 00:12:20 +0100296 else
297 real_ref = NULL;
298 }
Daniel Barkalowe496c002008-02-07 11:40:08 -0500299 break;
300 default:
Jiang Xinbc554df2013-04-16 11:37:50 +0800301 die(_("Ambiguous object name: '%s'."), start_name);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500302 break;
303 }
304
Nguyễn Thái Ngọc Duy4edce172018-11-10 06:49:00 +0100305 if ((commit = lookup_commit_reference(r, &oid)) == NULL)
Jiang Xinbc554df2013-04-16 11:37:50 +0800306 die(_("Not a valid branch point: '%s'."), start_name);
brian m. carlson48713bf2017-05-01 02:29:00 +0000307 oidcpy(&oid, &commit->object.oid);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500308
Ronnie Sahlbergd43f9902014-04-16 16:21:53 -0700309 if (reflog)
Cornelius Weig341fb282017-01-27 11:09:47 +0100310 log_all_ref_updates = LOG_REFS_NORMAL;
Ronnie Sahlbergd43f9902014-04-16 16:21:53 -0700311
312 if (!dont_change_ref) {
313 struct ref_transaction *transaction;
314 struct strbuf err = STRBUF_INIT;
Jeff Kingcddac452017-03-28 15:46:40 -0400315 char *msg;
Jeff King3818b252017-03-28 15:46:36 -0400316
317 if (forcing)
Jeff Kingcddac452017-03-28 15:46:40 -0400318 msg = xstrfmt("branch: Reset to %s", start_name);
Jeff King3818b252017-03-28 15:46:36 -0400319 else
Jeff Kingcddac452017-03-28 15:46:40 -0400320 msg = xstrfmt("branch: Created from %s", start_name);
Ronnie Sahlbergd43f9902014-04-16 16:21:53 -0700321
322 transaction = ref_transaction_begin(&err);
323 if (!transaction ||
Michael Haggerty1d147bd2015-02-17 18:00:15 +0100324 ref_transaction_update(transaction, ref.buf,
brian m. carlson89f3bbd2017-10-15 22:06:53 +0000325 &oid, forcing ? NULL : &null_oid,
Michael Haggerty1d147bd2015-02-17 18:00:15 +0100326 0, msg, &err) ||
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -0700327 ref_transaction_commit(transaction, &err))
Ronnie Sahlbergd43f9902014-04-16 16:21:53 -0700328 die("%s", err.buf);
329 ref_transaction_free(transaction);
330 strbuf_release(&err);
Jeff Kingcddac452017-03-28 15:46:40 -0400331 free(msg);
Ronnie Sahlbergd43f9902014-04-16 16:21:53 -0700332 }
333
Daniel Barkalowe496c002008-02-07 11:40:08 -0500334 if (real_ref && track)
Felipe Contreras82a06722013-08-30 16:56:46 -0500335 setup_tracking(ref.buf + 11, real_ref, track, quiet);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500336
Junio C Hamano8415d5c2009-02-13 23:08:05 -0800337 strbuf_release(&ref);
Jay Soffian9ed36cf2008-02-19 11:24:37 -0500338 free(real_ref);
Daniel Barkalowe496c002008-02-07 11:40:08 -0500339}
Daniel Barkalowc369e7b2008-02-07 11:40:16 -0500340
Nguyễn Thái Ngọc Duyb6433552019-05-09 17:10:27 +0700341void remove_merge_branch_state(struct repository *r)
Daniel Barkalowc369e7b2008-02-07 11:40:16 -0500342{
Nguyễn Thái Ngọc Duy4edce172018-11-10 06:49:00 +0100343 unlink(git_path_merge_head(r));
344 unlink(git_path_merge_rr(r));
345 unlink(git_path_merge_msg(r));
346 unlink(git_path_merge_mode(r));
Nguyễn Thái Ngọc Duyb6433552019-05-09 17:10:27 +0700347}
348
349void remove_branch_state(struct repository *r)
350{
Junio C Hamanoc4a38d12019-06-13 13:19:41 -0700351 sequencer_post_commit_cleanup(r);
Nguyễn Thái Ngọc Duy4edce172018-11-10 06:49:00 +0100352 unlink(git_path_squash_msg(r));
Nguyễn Thái Ngọc Duyb6433552019-05-09 17:10:27 +0700353 remove_merge_branch_state(r);
Daniel Barkalowc369e7b2008-02-07 11:40:16 -0500354}
Eric Sunshineed89f842015-07-17 19:00:04 -0400355
Nguyễn Thái Ngọc Duy8d9fdd72016-04-22 20:01:33 +0700356void die_if_checked_out(const char *branch, int ignore_current_worktree)
David Turner41af6562015-08-10 13:52:44 -0400357{
Nguyễn Thái Ngọc Duyd3b9ac02016-04-22 20:01:27 +0700358 const struct worktree *wt;
David Turner41af6562015-08-10 13:52:44 -0400359
Nguyễn Thái Ngọc Duyd3b9ac02016-04-22 20:01:27 +0700360 wt = find_shared_symref("HEAD", branch);
Nguyễn Thái Ngọc Duy8d9fdd72016-04-22 20:01:33 +0700361 if (!wt || (ignore_current_worktree && wt->is_current))
Nguyễn Thái Ngọc Duyd3b9ac02016-04-22 20:01:27 +0700362 return;
363 skip_prefix(branch, "refs/heads/", &branch);
364 die(_("'%s' is already checked out at '%s'"),
365 branch, wt->path);
Eric Sunshineed89f842015-07-17 19:00:04 -0400366}
Kazuki Yamaguchi70999e92016-03-27 23:37:14 +0900367
Kyle Meyer39ee4c62017-02-20 20:10:35 -0500368int replace_each_worktree_head_symref(const char *oldref, const char *newref,
369 const char *logmsg)
Kazuki Yamaguchi70999e92016-03-27 23:37:14 +0900370{
371 int ret = 0;
Nguyễn Thái Ngọc Duy4fff1ef2016-11-28 16:36:55 +0700372 struct worktree **worktrees = get_worktrees(0);
Kazuki Yamaguchi70999e92016-03-27 23:37:14 +0900373 int i;
374
375 for (i = 0; worktrees[i]; i++) {
Nguyễn Thái Ngọc Duyd026a252017-04-24 17:01:24 +0700376 struct ref_store *refs;
377
Kazuki Yamaguchi70999e92016-03-27 23:37:14 +0900378 if (worktrees[i]->is_detached)
379 continue;
Nguyễn Thái Ngọc Duy31824d12017-08-24 17:41:24 +0700380 if (!worktrees[i]->head_ref)
381 continue;
382 if (strcmp(oldref, worktrees[i]->head_ref))
Kazuki Yamaguchi70999e92016-03-27 23:37:14 +0900383 continue;
384
Nguyễn Thái Ngọc Duyd026a252017-04-24 17:01:24 +0700385 refs = get_worktree_ref_store(worktrees[i]);
386 if (refs_create_symref(refs, "HEAD", newref, logmsg))
387 ret = error(_("HEAD of working tree %s is not updated"),
388 worktrees[i]->path);
Kazuki Yamaguchi70999e92016-03-27 23:37:14 +0900389 }
390
391 free_worktrees(worktrees);
392 return ret;
393}