]> git.ipfire.org Git - thirdparty/git.git/blame - branch.c
Merge branch 'jk/tests-cleanup'
[thirdparty/git.git] / branch.c
CommitLineData
303d1d0b 1#include "git-compat-util.h"
e496c003
DB
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
a9f2c136 36static int should_setup_rebase(const char *origin)
c998ae9b
DS
37{
38 switch (autorebase) {
39 case AUTOREBASE_NEVER:
40 return 0;
41 case AUTOREBASE_LOCAL:
a9f2c136 42 return origin == NULL;
c998ae9b 43 case AUTOREBASE_REMOTE:
a9f2c136 44 return origin != NULL;
c998ae9b
DS
45 case AUTOREBASE_ALWAYS:
46 return 1;
47 }
48 return 0;
49}
50
a9f2c136
JH
51void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
52{
303d1d0b 53 const char *shortname = skip_prefix(remote, "refs/heads/");
a9f2c136
JH
54 struct strbuf key = STRBUF_INIT;
55 int rebasing = should_setup_rebase(origin);
56
303d1d0b 57 if (shortname
85e2233f
MM
58 && !strcmp(local, shortname)
59 && !origin) {
bc554df8 60 warning(_("Not setting branch %s as its own upstream."),
85e2233f
MM
61 local);
62 return;
63 }
64
a9f2c136
JH
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 }
d53a3503 77 strbuf_release(&key);
a9f2c136 78
72f60083 79 if (flag & BRANCH_CONFIG_VERBOSE) {
303d1d0b 80 if (shortname && origin)
bc554df8
JX
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);
303d1d0b 85 else if (shortname && !origin)
bc554df8
JX
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);
303d1d0b 90 else if (!shortname && origin)
bc554df8
JX
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);
303d1d0b 95 else if (!shortname && !origin)
bc554df8
JX
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);
72f60083 100 else
303d1d0b
BG
101 die("BUG: impossible combination of %p and %p",
102 shortname, origin);
72f60083 103 }
a9f2c136
JH
104}
105
e496c003
DB
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 */
9ed36cfa 111static int setup_tracking(const char *new_ref, const char *orig_ref,
f9a482e6 112 enum branch_track track, int quiet)
e496c003 113{
e496c003 114 struct tracking tracking;
f9a482e6 115 int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
e496c003 116
e496c003
DB
117 memset(&tracking, 0, sizeof(tracking));
118 tracking.spec.dst = (char *)orig_ref;
9ed36cfa 119 if (for_each_remote(find_tracked_branch, &tracking))
e496c003
DB
120 return 1;
121
9ed36cfa
JS
122 if (!tracking.matches)
123 switch (track) {
124 case BRANCH_TRACK_ALWAYS:
125 case BRANCH_TRACK_EXPLICIT:
4fc50066 126 case BRANCH_TRACK_OVERRIDE:
9ed36cfa
JS
127 break;
128 default:
129 return 1;
130 }
131
e496c003 132 if (tracking.matches > 1)
bc554df8 133 return error(_("Not tracking: ambiguous information for ref %s"),
e496c003
DB
134 orig_ref);
135
f9a482e6 136 install_branch_config(config_flags, new_ref, tracking.remote,
a9f2c136 137 tracking.src ? tracking.src : orig_ref);
e496c003 138
a9f2c136 139 free(tracking.src);
e496c003
DB
140 return 0;
141}
142
6f9a3321
JH
143struct branch_desc_cb {
144 const char *config_name;
145 const char *value;
146};
147
148static int read_branch_desc_cb(const char *var, const char *value, void *cb)
149{
150 struct branch_desc_cb *desc = cb;
151 if (strcmp(desc->config_name, var))
152 return 0;
153 free((char *)desc->value);
154 return git_config_string(&desc->value, var, value);
155}
156
157int read_branch_desc(struct strbuf *buf, const char *branch_name)
158{
159 struct branch_desc_cb cb;
160 struct strbuf name = STRBUF_INIT;
161 strbuf_addf(&name, "branch.%s.description", branch_name);
162 cb.config_name = name.buf;
163 cb.value = NULL;
164 if (git_config(read_branch_desc_cb, &cb) < 0) {
165 strbuf_release(&name);
166 return -1;
167 }
168 if (cb.value)
169 strbuf_addstr(buf, cb.value);
170 strbuf_release(&name);
171 return 0;
172}
173
fa799376
JH
174int validate_new_branchname(const char *name, struct strbuf *ref,
175 int force, int attr_only)
55c4a673 176{
55c4a673 177 if (strbuf_check_branch_ref(ref, name))
bc554df8 178 die(_("'%s' is not a valid branch name."), name);
55c4a673
CI
179
180 if (!ref_exists(ref->buf))
181 return 0;
fa799376 182 else if (!force && !attr_only)
bc554df8 183 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
55c4a673 184
fa799376
JH
185 if (!attr_only) {
186 const char *head;
187 unsigned char sha1[20];
55c4a673 188
8cad4744 189 head = resolve_ref_unsafe("HEAD", sha1, 0, NULL);
fa799376 190 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
bc554df8 191 die(_("Cannot force update the current branch."));
fa799376 192 }
55c4a673
CI
193 return 1;
194}
195
41c21f22
JH
196static int check_tracking_branch(struct remote *remote, void *cb_data)
197{
198 char *tracking_branch = cb_data;
199 struct refspec query;
200 memset(&query, 0, sizeof(struct refspec));
201 query.dst = tracking_branch;
1d7358c5 202 return !remote_find_tracking(remote, &query);
41c21f22
JH
203}
204
205static int validate_remote_tracking_branch(char *ref)
206{
207 return !for_each_remote(check_tracking_branch, ref);
208}
209
e2b6aa5f 210static const char upstream_not_branch[] =
1a15d00b 211N_("Cannot setup tracking information; starting point '%s' is not a branch.");
a5e91c72 212static const char upstream_missing[] =
caa2036b
JK
213N_("the requested upstream branch '%s' does not exist");
214static const char upstream_advice[] =
215N_("\n"
216"If you are planning on basing your work on an upstream\n"
217"branch that already exists at the remote, you may need to\n"
218"run \"git fetch\" to retrieve it.\n"
219"\n"
220"If you are planning to push out a new local branch that\n"
221"will track its remote counterpart, you may want to use\n"
222"\"git push -u\" to set the upstream config as you push.");
e2b6aa5f 223
e496c003
DB
224void create_branch(const char *head,
225 const char *name, const char *start_name,
39bd6f72 226 int force, int reflog, int clobber_head,
f9a482e6 227 int quiet, enum branch_track track)
e496c003 228{
4fc50066 229 struct ref_lock *lock = NULL;
e496c003
DB
230 struct commit *commit;
231 unsigned char sha1[20];
8415d5c7
JH
232 char *real_ref, msg[PATH_MAX + 20];
233 struct strbuf ref = STRBUF_INIT;
e496c003 234 int forcing = 0;
4fc50066
IL
235 int dont_change_ref = 0;
236 int explicit_tracking = 0;
237
238 if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
239 explicit_tracking = 1;
e496c003 240
fa799376 241 if (validate_new_branchname(name, &ref, force,
39bd6f72
JN
242 track == BRANCH_TRACK_OVERRIDE ||
243 clobber_head)) {
55c4a673 244 if (!force)
4fc50066 245 dont_change_ref = 1;
55c4a673
CI
246 else
247 forcing = 1;
e496c003
DB
248 }
249
250 real_ref = NULL;
a5e91c72 251 if (get_sha1(start_name, sha1)) {
caa2036b
JK
252 if (explicit_tracking) {
253 if (advice_set_upstream_failure) {
254 error(_(upstream_missing), start_name);
255 advise(_(upstream_advice));
256 exit(1);
257 }
1a15d00b 258 die(_(upstream_missing), start_name);
caa2036b 259 }
bc554df8 260 die(_("Not a valid object name: '%s'."), start_name);
a5e91c72 261 }
e496c003
DB
262
263 switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
264 case 0:
265 /* Not branching from any existing branch */
4fc50066 266 if (explicit_tracking)
1a15d00b 267 die(_(upstream_not_branch), start_name);
e496c003
DB
268 break;
269 case 1:
21b5b1e8 270 /* Unique completion -- good, only if it is a real branch */
59556548 271 if (!starts_with(real_ref, "refs/heads/") &&
41c21f22 272 validate_remote_tracking_branch(real_ref)) {
21b5b1e8 273 if (explicit_tracking)
1a15d00b 274 die(_(upstream_not_branch), start_name);
21b5b1e8
JH
275 else
276 real_ref = NULL;
277 }
e496c003
DB
278 break;
279 default:
bc554df8 280 die(_("Ambiguous object name: '%s'."), start_name);
e496c003
DB
281 break;
282 }
283
284 if ((commit = lookup_commit_reference(sha1)) == NULL)
bc554df8 285 die(_("Not a valid branch point: '%s'."), start_name);
e496c003
DB
286 hashcpy(sha1, commit->object.sha1);
287
4fc50066 288 if (!dont_change_ref) {
9bbb0fa1 289 lock = lock_any_ref_for_update(ref.buf, NULL, 0, NULL);
4fc50066 290 if (!lock)
bc554df8 291 die_errno(_("Failed to lock ref for update"));
4fc50066 292 }
e496c003
DB
293
294 if (reflog)
295 log_all_ref_updates = 1;
296
297 if (forcing)
da288e25 298 snprintf(msg, sizeof msg, "branch: Reset to %s",
e496c003 299 start_name);
4fc50066 300 else if (!dont_change_ref)
e496c003
DB
301 snprintf(msg, sizeof msg, "branch: Created from %s",
302 start_name);
303
e496c003 304 if (real_ref && track)
82a0672f 305 setup_tracking(ref.buf + 11, real_ref, track, quiet);
e496c003 306
4fc50066
IL
307 if (!dont_change_ref)
308 if (write_ref_sha1(lock, sha1, msg) < 0)
bc554df8 309 die_errno(_("Failed to write ref"));
e496c003 310
8415d5c7 311 strbuf_release(&ref);
9ed36cfa 312 free(real_ref);
e496c003 313}
c369e7b8
DB
314
315void remove_branch_state(void)
316{
d7e5c0cb 317 unlink(git_path("CHERRY_PICK_HEAD"));
82433cdf 318 unlink(git_path("REVERT_HEAD"));
c369e7b8 319 unlink(git_path("MERGE_HEAD"));
0af0ac7e 320 unlink(git_path("MERGE_RR"));
c369e7b8 321 unlink(git_path("MERGE_MSG"));
cf10f9fd 322 unlink(git_path("MERGE_MODE"));
c369e7b8
DB
323 unlink(git_path("SQUASH_MSG"));
324}