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