1#include "git-compat-util.h"
2#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
36static int should_setup_rebase(const char *origin)
37{
38 switch (autorebase) {
39 case AUTOREBASE_NEVER:
40 return 0;
41 case AUTOREBASE_LOCAL:
42 return origin == NULL;
43 case AUTOREBASE_REMOTE:
44 return origin != NULL;
45 case AUTOREBASE_ALWAYS:
46 return 1;
47 }
48 return 0;
49}
50
51void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
52{
53 const char *shortname = NULL;
54 struct strbuf key = STRBUF_INIT;
55 int rebasing = should_setup_rebase(origin);
56
57 if (skip_prefix(remote, "refs/heads/", &shortname)
58 && !strcmp(local, shortname)
59 && !origin) {
60 warning(_("Not setting branch %s as its own upstream."),
61 local);
62 return;
63 }
64
65 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 }
77 strbuf_release(&key);
78
79 if (flag & BRANCH_CONFIG_VERBOSE) {
80 if (shortname) {
81 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 }
103 }
104}
105
106/*
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 */
111static int setup_tracking(const char *new_ref, const char *orig_ref,
112 enum branch_track track, int quiet)
113{
114 struct tracking tracking;
115 int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
116
117 memset(&tracking, 0, sizeof(tracking));
118 tracking.spec.dst = (char *)orig_ref;
119 if (for_each_remote(find_tracked_branch, &tracking))
120 return 1;
121
122 if (!tracking.matches)
123 switch (track) {
124 case BRANCH_TRACK_ALWAYS:
125 case BRANCH_TRACK_EXPLICIT:
126 case BRANCH_TRACK_OVERRIDE:
127 break;
128 default:
129 return 1;
130 }
131
132 if (tracking.matches > 1)
133 return error(_("Not tracking: ambiguous information for ref %s"),
134 orig_ref);
135
136 install_branch_config(config_flags, new_ref, tracking.remote,
137 tracking.src ? tracking.src : orig_ref);
138
139 free(tracking.src);
140 return 0;
141}
142
143int read_branch_desc(struct strbuf *buf, const char *branch_name)
144{
145 char *v = NULL;
146 struct strbuf name = STRBUF_INIT;
147 strbuf_addf(&name, "branch.%s.description", branch_name);
148 if (git_config_get_string(name.buf, &v)) {
149 strbuf_release(&name);
150 return -1;
151 }
152 strbuf_addstr(buf, v);
153 free(v);
154 strbuf_release(&name);
155 return 0;
156}
157
158int validate_new_branchname(const char *name, struct strbuf *ref,
159 int force, int attr_only)
160{
161 if (strbuf_check_branch_ref(ref, name))
162 die(_("'%s' is not a valid branch name."), name);
163
164 if (!ref_exists(ref->buf))
165 return 0;
166 else if (!force && !attr_only)
167 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
168
169 if (!attr_only) {
170 const char *head;
171 unsigned char sha1[20];
172
173 head = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
174 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
175 die(_("Cannot force update the current branch."));
176 }
177 return 1;
178}
179
180static 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;
186 return !remote_find_tracking(remote, &query);
187}
188
189static int validate_remote_tracking_branch(char *ref)
190{
191 return !for_each_remote(check_tracking_branch, ref);
192}
193
194static const char upstream_not_branch[] =
195N_("Cannot setup tracking information; starting point '%s' is not a branch.");
196static const char upstream_missing[] =
197N_("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.");
207
208void create_branch(const char *head,
209 const char *name, const char *start_name,
210 int force, int reflog, int clobber_head,
211 int quiet, enum branch_track track)
212{
213 struct commit *commit;
214 unsigned char sha1[20];
215 char *real_ref, msg[PATH_MAX + 20];
216 struct strbuf ref = STRBUF_INIT;
217 int forcing = 0;
218 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;
223
224 if (validate_new_branchname(name, &ref, force,
225 track == BRANCH_TRACK_OVERRIDE ||
226 clobber_head)) {
227 if (!force)
228 dont_change_ref = 1;
229 else
230 forcing = 1;
231 }
232
233 real_ref = NULL;
234 if (get_sha1(start_name, sha1)) {
235 if (explicit_tracking) {
236 if (advice_set_upstream_failure) {
237 error(_(upstream_missing), start_name);
238 advise(_(upstream_advice));
239 exit(1);
240 }
241 die(_(upstream_missing), start_name);
242 }
243 die(_("Not a valid object name: '%s'."), start_name);
244 }
245
246 switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
247 case 0:
248 /* Not branching from any existing branch */
249 if (explicit_tracking)
250 die(_(upstream_not_branch), start_name);
251 break;
252 case 1:
253 /* Unique completion -- good, only if it is a real branch */
254 if (!starts_with(real_ref, "refs/heads/") &&
255 validate_remote_tracking_branch(real_ref)) {
256 if (explicit_tracking)
257 die(_(upstream_not_branch), start_name);
258 else
259 real_ref = NULL;
260 }
261 break;
262 default:
263 die(_("Ambiguous object name: '%s'."), start_name);
264 break;
265 }
266
267 if ((commit = lookup_commit_reference(sha1)) == NULL)
268 die(_("Not a valid branch point: '%s'."), start_name);
269 hashcpy(sha1, commit->object.sha1);
270
271 if (forcing)
272 snprintf(msg, sizeof msg, "branch: Reset to %s",
273 start_name);
274 else if (!dont_change_ref)
275 snprintf(msg, sizeof msg, "branch: Created from %s",
276 start_name);
277
278 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,
288 sha1, forcing ? NULL : null_sha1,
289 0, msg, &err) ||
290 ref_transaction_commit(transaction, &err))
291 die("%s", err.buf);
292 ref_transaction_free(transaction);
293 strbuf_release(&err);
294 }
295
296 if (real_ref && track)
297 setup_tracking(ref.buf + 11, real_ref, track, quiet);
298
299 strbuf_release(&ref);
300 free(real_ref);
301}
302
303void remove_branch_state(void)
304{
305 unlink(git_path("CHERRY_PICK_HEAD"));
306 unlink(git_path("REVERT_HEAD"));
307 unlink(git_path("MERGE_HEAD"));
308 unlink(git_path("MERGE_RR"));
309 unlink(git_path("MERGE_MSG"));
310 unlink(git_path("MERGE_MODE"));
311 unlink(git_path("SQUASH_MSG"));
312}
313
314static void check_linked_checkout(const char *branch, const char *id)
315{
316 struct strbuf sb = STRBUF_INIT;
317 struct strbuf path = STRBUF_INIT;
318 struct strbuf gitdir = STRBUF_INIT;
319
320 /*
321 * $GIT_COMMON_DIR/HEAD is practically outside
322 * $GIT_DIR so resolve_ref_unsafe() won't work (it
323 * uses git_path). Parse the ref ourselves.
324 */
325 if (id)
326 strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);
327 else
328 strbuf_addf(&path, "%s/HEAD", get_git_common_dir());
329
330 if (!strbuf_readlink(&sb, path.buf, 0)) {
331 if (!starts_with(sb.buf, "refs/") ||
332 check_refname_format(sb.buf, 0))
333 goto done;
334 } else if (strbuf_read_file(&sb, path.buf, 0) >= 0 &&
335 starts_with(sb.buf, "ref:")) {
336 strbuf_remove(&sb, 0, strlen("ref:"));
337 strbuf_trim(&sb);
338 } else
339 goto done;
340 if (strcmp(sb.buf, branch))
341 goto done;
342 if (id) {
343 strbuf_reset(&path);
344 strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id);
345 if (strbuf_read_file(&gitdir, path.buf, 0) <= 0)
346 goto done;
347 strbuf_rtrim(&gitdir);
348 } else
349 strbuf_addstr(&gitdir, get_git_common_dir());
350 skip_prefix(branch, "refs/heads/", &branch);
351 strbuf_strip_suffix(&gitdir, ".git");
352 die(_("'%s' is already checked out at '%s'"), branch, gitdir.buf);
353done:
354 strbuf_release(&path);
355 strbuf_release(&sb);
356 strbuf_release(&gitdir);
357}
358
359void die_if_checked_out(const char *branch)
360{
361 struct strbuf path = STRBUF_INIT;
362 DIR *dir;
363 struct dirent *d;
364
365 check_linked_checkout(branch, NULL);
366
367 strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
368 dir = opendir(path.buf);
369 strbuf_release(&path);
370 if (!dir)
371 return;
372
373 while ((d = readdir(dir)) != NULL) {
374 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
375 continue;
376 check_linked_checkout(branch, d->d_name);
377 }
378 closedir(dir);
379}