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