1#include "git-compat-util.h"
2#include "cache.h"
3#include "config.h"
4#include "branch.h"
5#include "refs.h"
6#include "remote.h"
7#include "commit.h"
8#include "worktree.h"
9
10struct tracking {
11 struct refspec spec;
12 char *src;
13 const char *remote;
14 int matches;
15};
16
17static int find_tracked_branch(struct remote *remote, void *priv)
18{
19 struct tracking *tracking = priv;
20
21 if (!remote_find_tracking(remote, &tracking->spec)) {
22 if (++tracking->matches == 1) {
23 tracking->src = tracking->spec.src;
24 tracking->remote = remote->name;
25 } else {
26 free(tracking->spec.src);
27 if (tracking->src) {
28 free(tracking->src);
29 tracking->src = NULL;
30 }
31 }
32 tracking->spec.src = NULL;
33 }
34
35 return 0;
36}
37
38static int should_setup_rebase(const char *origin)
39{
40 switch (autorebase) {
41 case AUTOREBASE_NEVER:
42 return 0;
43 case AUTOREBASE_LOCAL:
44 return origin == NULL;
45 case AUTOREBASE_REMOTE:
46 return origin != NULL;
47 case AUTOREBASE_ALWAYS:
48 return 1;
49 }
50 return 0;
51}
52
53static const char tracking_advice[] =
54N_("\n"
55"After fixing the error cause you may try to fix up\n"
56"the remote tracking information by invoking\n"
57"\"git branch --set-upstream-to=%s%s%s\".");
58
59int install_branch_config(int flag, const char *local, const char *origin, const char *remote)
60{
61 const char *shortname = NULL;
62 struct strbuf key = STRBUF_INIT;
63 int rebasing = should_setup_rebase(origin);
64
65 if (skip_prefix(remote, "refs/heads/", &shortname)
66 && !strcmp(local, shortname)
67 && !origin) {
68 warning(_("Not setting branch %s as its own upstream."),
69 local);
70 return 0;
71 }
72
73 strbuf_addf(&key, "branch.%s.remote", local);
74 if (git_config_set_gently(key.buf, origin ? origin : ".") < 0)
75 goto out_err;
76
77 strbuf_reset(&key);
78 strbuf_addf(&key, "branch.%s.merge", local);
79 if (git_config_set_gently(key.buf, remote) < 0)
80 goto out_err;
81
82 if (rebasing) {
83 strbuf_reset(&key);
84 strbuf_addf(&key, "branch.%s.rebase", local);
85 if (git_config_set_gently(key.buf, "true") < 0)
86 goto out_err;
87 }
88 strbuf_release(&key);
89
90 if (flag & BRANCH_CONFIG_VERBOSE) {
91 if (shortname) {
92 if (origin)
93 printf_ln(rebasing ?
94 _("Branch %s set up to track remote branch %s from %s by rebasing.") :
95 _("Branch %s set up to track remote branch %s from %s."),
96 local, shortname, origin);
97 else
98 printf_ln(rebasing ?
99 _("Branch %s set up to track local branch %s by rebasing.") :
100 _("Branch %s set up to track local branch %s."),
101 local, shortname);
102 } else {
103 if (origin)
104 printf_ln(rebasing ?
105 _("Branch %s set up to track remote ref %s by rebasing.") :
106 _("Branch %s set up to track remote ref %s."),
107 local, remote);
108 else
109 printf_ln(rebasing ?
110 _("Branch %s set up to track local ref %s by rebasing.") :
111 _("Branch %s set up to track local ref %s."),
112 local, remote);
113 }
114 }
115
116 return 0;
117
118out_err:
119 strbuf_release(&key);
120 error(_("Unable to write upstream branch configuration"));
121
122 advise(_(tracking_advice),
123 origin ? origin : "",
124 origin ? "/" : "",
125 shortname ? shortname : remote);
126
127 return -1;
128}
129
130/*
131 * This is called when new_ref is branched off of orig_ref, and tries
132 * to infer the settings for branch.<new_ref>.{remote,merge} from the
133 * config.
134 */
135static void setup_tracking(const char *new_ref, const char *orig_ref,
136 enum branch_track track, int quiet)
137{
138 struct tracking tracking;
139 int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
140
141 memset(&tracking, 0, sizeof(tracking));
142 tracking.spec.dst = (char *)orig_ref;
143 if (for_each_remote(find_tracked_branch, &tracking))
144 return;
145
146 if (!tracking.matches)
147 switch (track) {
148 case BRANCH_TRACK_ALWAYS:
149 case BRANCH_TRACK_EXPLICIT:
150 case BRANCH_TRACK_OVERRIDE:
151 break;
152 default:
153 return;
154 }
155
156 if (tracking.matches > 1)
157 die(_("Not tracking: ambiguous information for ref %s"),
158 orig_ref);
159
160 if (install_branch_config(config_flags, new_ref, tracking.remote,
161 tracking.src ? tracking.src : orig_ref) < 0)
162 exit(-1);
163
164 free(tracking.src);
165}
166
167int read_branch_desc(struct strbuf *buf, const char *branch_name)
168{
169 char *v = NULL;
170 struct strbuf name = STRBUF_INIT;
171 strbuf_addf(&name, "branch.%s.description", branch_name);
172 if (git_config_get_string(name.buf, &v)) {
173 strbuf_release(&name);
174 return -1;
175 }
176 strbuf_addstr(buf, v);
177 free(v);
178 strbuf_release(&name);
179 return 0;
180}
181
182int validate_new_branchname(const char *name, struct strbuf *ref,
183 int force, int attr_only)
184{
185 if (strbuf_check_branch_ref(ref, name))
186 die(_("'%s' is not a valid branch name."), name);
187
188 if (!ref_exists(ref->buf))
189 return 0;
190 else if (!force && !attr_only)
191 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
192
193 if (!attr_only) {
194 const char *head;
195 struct object_id oid;
196
197 head = resolve_ref_unsafe("HEAD", 0, oid.hash, NULL);
198 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
199 die(_("Cannot force update the current branch."));
200 }
201 return 1;
202}
203
204static int check_tracking_branch(struct remote *remote, void *cb_data)
205{
206 char *tracking_branch = cb_data;
207 struct refspec query;
208 memset(&query, 0, sizeof(struct refspec));
209 query.dst = tracking_branch;
210 return !remote_find_tracking(remote, &query);
211}
212
213static int validate_remote_tracking_branch(char *ref)
214{
215 return !for_each_remote(check_tracking_branch, ref);
216}
217
218static const char upstream_not_branch[] =
219N_("Cannot setup tracking information; starting point '%s' is not a branch.");
220static const char upstream_missing[] =
221N_("the requested upstream branch '%s' does not exist");
222static const char upstream_advice[] =
223N_("\n"
224"If you are planning on basing your work on an upstream\n"
225"branch that already exists at the remote, you may need to\n"
226"run \"git fetch\" to retrieve it.\n"
227"\n"
228"If you are planning to push out a new local branch that\n"
229"will track its remote counterpart, you may want to use\n"
230"\"git push -u\" to set the upstream config as you push.");
231
232void create_branch(const char *name, const char *start_name,
233 int force, int reflog, int clobber_head,
234 int quiet, enum branch_track track)
235{
236 struct commit *commit;
237 struct object_id oid;
238 char *real_ref;
239 struct strbuf ref = STRBUF_INIT;
240 int forcing = 0;
241 int dont_change_ref = 0;
242 int explicit_tracking = 0;
243
244 if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
245 explicit_tracking = 1;
246
247 if (validate_new_branchname(name, &ref, force,
248 track == BRANCH_TRACK_OVERRIDE ||
249 clobber_head)) {
250 if (!force)
251 dont_change_ref = 1;
252 else
253 forcing = 1;
254 }
255
256 real_ref = NULL;
257 if (get_oid(start_name, &oid)) {
258 if (explicit_tracking) {
259 if (advice_set_upstream_failure) {
260 error(_(upstream_missing), start_name);
261 advise(_(upstream_advice));
262 exit(1);
263 }
264 die(_(upstream_missing), start_name);
265 }
266 die(_("Not a valid object name: '%s'."), start_name);
267 }
268
269 switch (dwim_ref(start_name, strlen(start_name), oid.hash, &real_ref)) {
270 case 0:
271 /* Not branching from any existing branch */
272 if (explicit_tracking)
273 die(_(upstream_not_branch), start_name);
274 break;
275 case 1:
276 /* Unique completion -- good, only if it is a real branch */
277 if (!starts_with(real_ref, "refs/heads/") &&
278 validate_remote_tracking_branch(real_ref)) {
279 if (explicit_tracking)
280 die(_(upstream_not_branch), start_name);
281 else
282 real_ref = NULL;
283 }
284 break;
285 default:
286 die(_("Ambiguous object name: '%s'."), start_name);
287 break;
288 }
289
290 if ((commit = lookup_commit_reference(&oid)) == NULL)
291 die(_("Not a valid branch point: '%s'."), start_name);
292 oidcpy(&oid, &commit->object.oid);
293
294 if (reflog)
295 log_all_ref_updates = LOG_REFS_NORMAL;
296
297 if (!dont_change_ref) {
298 struct ref_transaction *transaction;
299 struct strbuf err = STRBUF_INIT;
300 char *msg;
301
302 if (forcing)
303 msg = xstrfmt("branch: Reset to %s", start_name);
304 else
305 msg = xstrfmt("branch: Created from %s", start_name);
306
307 transaction = ref_transaction_begin(&err);
308 if (!transaction ||
309 ref_transaction_update(transaction, ref.buf,
310 oid.hash, forcing ? NULL : null_sha1,
311 0, msg, &err) ||
312 ref_transaction_commit(transaction, &err))
313 die("%s", err.buf);
314 ref_transaction_free(transaction);
315 strbuf_release(&err);
316 free(msg);
317 }
318
319 if (real_ref && track)
320 setup_tracking(ref.buf + 11, real_ref, track, quiet);
321
322 strbuf_release(&ref);
323 free(real_ref);
324}
325
326void remove_branch_state(void)
327{
328 unlink(git_path_cherry_pick_head());
329 unlink(git_path_revert_head());
330 unlink(git_path_merge_head());
331 unlink(git_path_merge_rr());
332 unlink(git_path_merge_msg());
333 unlink(git_path_merge_mode());
334 unlink(git_path_squash_msg());
335}
336
337void die_if_checked_out(const char *branch, int ignore_current_worktree)
338{
339 const struct worktree *wt;
340
341 wt = find_shared_symref("HEAD", branch);
342 if (!wt || (ignore_current_worktree && wt->is_current))
343 return;
344 skip_prefix(branch, "refs/heads/", &branch);
345 die(_("'%s' is already checked out at '%s'"),
346 branch, wt->path);
347}
348
349int replace_each_worktree_head_symref(const char *oldref, const char *newref,
350 const char *logmsg)
351{
352 int ret = 0;
353 struct worktree **worktrees = get_worktrees(0);
354 int i;
355
356 for (i = 0; worktrees[i]; i++) {
357 struct ref_store *refs;
358
359 if (worktrees[i]->is_detached)
360 continue;
361 if (worktrees[i]->head_ref &&
362 strcmp(oldref, worktrees[i]->head_ref))
363 continue;
364
365 refs = get_worktree_ref_store(worktrees[i]);
366 if (refs_create_symref(refs, "HEAD", newref, logmsg))
367 ret = error(_("HEAD of working tree %s is not updated"),
368 worktrees[i]->path);
369 }
370
371 free_worktrees(worktrees);
372 return ret;
373}