]> git.ipfire.org Git - thirdparty/git.git/blame - branch.c
Merge branch 'nd/mv-code-cleaning'
[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{
cf4fff57 53 const char *shortname = NULL;
a9f2c136
JH
54 struct strbuf key = STRBUF_INIT;
55 int rebasing = should_setup_rebase(origin);
56
cf4fff57 57 if (skip_prefix(remote, "refs/heads/", &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) {
1d9aaed2 80 if (shortname) {
9fe0cf3a
A
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 }
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
143int read_branch_desc(struct strbuf *buf, const char *branch_name)
144{
540b0f49 145 char *v = NULL;
6f9a3321
JH
146 struct strbuf name = STRBUF_INIT;
147 strbuf_addf(&name, "branch.%s.description", branch_name);
540b0f49
TA
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);
6f9a3321
JH
154 strbuf_release(&name);
155 return 0;
156}
157
fa799376
JH
158int validate_new_branchname(const char *name, struct strbuf *ref,
159 int force, int attr_only)
55c4a673 160{
55c4a673 161 if (strbuf_check_branch_ref(ref, name))
bc554df8 162 die(_("'%s' is not a valid branch name."), name);
55c4a673
CI
163
164 if (!ref_exists(ref->buf))
165 return 0;
fa799376 166 else if (!force && !attr_only)
bc554df8 167 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
55c4a673 168
fa799376
JH
169 if (!attr_only) {
170 const char *head;
171 unsigned char sha1[20];
55c4a673 172
8cad4744 173 head = resolve_ref_unsafe("HEAD", sha1, 0, NULL);
fa799376 174 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
bc554df8 175 die(_("Cannot force update the current branch."));
fa799376 176 }
55c4a673
CI
177 return 1;
178}
179
41c21f22
JH
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;
1d7358c5 186 return !remote_find_tracking(remote, &query);
41c21f22
JH
187}
188
189static int validate_remote_tracking_branch(char *ref)
190{
191 return !for_each_remote(check_tracking_branch, ref);
192}
193
e2b6aa5f 194static const char upstream_not_branch[] =
1a15d00b 195N_("Cannot setup tracking information; starting point '%s' is not a branch.");
a5e91c72 196static const char upstream_missing[] =
caa2036b
JK
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.");
e2b6aa5f 207
e496c003
DB
208void create_branch(const char *head,
209 const char *name, const char *start_name,
39bd6f72 210 int force, int reflog, int clobber_head,
f9a482e6 211 int quiet, enum branch_track track)
e496c003 212{
4fc50066 213 struct ref_lock *lock = NULL;
e496c003
DB
214 struct commit *commit;
215 unsigned char sha1[20];
8415d5c7
JH
216 char *real_ref, msg[PATH_MAX + 20];
217 struct strbuf ref = STRBUF_INIT;
e496c003 218 int forcing = 0;
4fc50066
IL
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;
e496c003 224
fa799376 225 if (validate_new_branchname(name, &ref, force,
39bd6f72
JN
226 track == BRANCH_TRACK_OVERRIDE ||
227 clobber_head)) {
55c4a673 228 if (!force)
4fc50066 229 dont_change_ref = 1;
55c4a673
CI
230 else
231 forcing = 1;
e496c003
DB
232 }
233
234 real_ref = NULL;
a5e91c72 235 if (get_sha1(start_name, sha1)) {
caa2036b
JK
236 if (explicit_tracking) {
237 if (advice_set_upstream_failure) {
238 error(_(upstream_missing), start_name);
239 advise(_(upstream_advice));
240 exit(1);
241 }
1a15d00b 242 die(_(upstream_missing), start_name);
caa2036b 243 }
bc554df8 244 die(_("Not a valid object name: '%s'."), start_name);
a5e91c72 245 }
e496c003
DB
246
247 switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
248 case 0:
249 /* Not branching from any existing branch */
4fc50066 250 if (explicit_tracking)
1a15d00b 251 die(_(upstream_not_branch), start_name);
e496c003
DB
252 break;
253 case 1:
21b5b1e8 254 /* Unique completion -- good, only if it is a real branch */
59556548 255 if (!starts_with(real_ref, "refs/heads/") &&
41c21f22 256 validate_remote_tracking_branch(real_ref)) {
21b5b1e8 257 if (explicit_tracking)
1a15d00b 258 die(_(upstream_not_branch), start_name);
21b5b1e8
JH
259 else
260 real_ref = NULL;
261 }
e496c003
DB
262 break;
263 default:
bc554df8 264 die(_("Ambiguous object name: '%s'."), start_name);
e496c003
DB
265 break;
266 }
267
268 if ((commit = lookup_commit_reference(sha1)) == NULL)
bc554df8 269 die(_("Not a valid branch point: '%s'."), start_name);
e496c003
DB
270 hashcpy(sha1, commit->object.sha1);
271
4fc50066 272 if (!dont_change_ref) {
9bbb0fa1 273 lock = lock_any_ref_for_update(ref.buf, NULL, 0, NULL);
4fc50066 274 if (!lock)
bc554df8 275 die_errno(_("Failed to lock ref for update"));
4fc50066 276 }
e496c003
DB
277
278 if (reflog)
279 log_all_ref_updates = 1;
280
281 if (forcing)
da288e25 282 snprintf(msg, sizeof msg, "branch: Reset to %s",
e496c003 283 start_name);
4fc50066 284 else if (!dont_change_ref)
e496c003
DB
285 snprintf(msg, sizeof msg, "branch: Created from %s",
286 start_name);
287
e496c003 288 if (real_ref && track)
82a0672f 289 setup_tracking(ref.buf + 11, real_ref, track, quiet);
e496c003 290
4fc50066
IL
291 if (!dont_change_ref)
292 if (write_ref_sha1(lock, sha1, msg) < 0)
bc554df8 293 die_errno(_("Failed to write ref"));
e496c003 294
8415d5c7 295 strbuf_release(&ref);
9ed36cfa 296 free(real_ref);
e496c003 297}
c369e7b8
DB
298
299void remove_branch_state(void)
300{
d7e5c0cb 301 unlink(git_path("CHERRY_PICK_HEAD"));
82433cdf 302 unlink(git_path("REVERT_HEAD"));
c369e7b8 303 unlink(git_path("MERGE_HEAD"));
0af0ac7e 304 unlink(git_path("MERGE_RR"));
c369e7b8 305 unlink(git_path("MERGE_MSG"));
cf10f9fd 306 unlink(git_path("MERGE_MODE"));
c369e7b8
DB
307 unlink(git_path("SQUASH_MSG"));
308}