]> git.ipfire.org Git - thirdparty/git.git/blame - branch.c
reset: trivial refactoring
[thirdparty/git.git] / branch.c
CommitLineData
e496c003
DB
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
a9f2c136 35static int should_setup_rebase(const char *origin)
c998ae9b
DS
36{
37 switch (autorebase) {
38 case AUTOREBASE_NEVER:
39 return 0;
40 case AUTOREBASE_LOCAL:
a9f2c136 41 return origin == NULL;
c998ae9b 42 case AUTOREBASE_REMOTE:
a9f2c136 43 return origin != NULL;
c998ae9b
DS
44 case AUTOREBASE_ALWAYS:
45 return 1;
46 }
47 return 0;
48}
49
a9f2c136
JH
50void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
51{
85e2233f
MM
52 const char *shortname = remote + 11;
53 int remote_is_branch = !prefixcmp(remote, "refs/heads/");
a9f2c136
JH
54 struct strbuf key = STRBUF_INIT;
55 int rebasing = should_setup_rebase(origin);
56
85e2233f
MM
57 if (remote_is_branch
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) {
d53a3503 80 if (remote_is_branch && 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);
d53a3503 85 else if (remote_is_branch && !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);
d53a3503 90 else if (!remote_is_branch && 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);
d53a3503 95 else if (!remote_is_branch && !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
d53a3503
NTND
101 die("BUG: impossible combination of %d and %p",
102 remote_is_branch, 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
DB
116
117 if (strlen(new_ref) > 1024 - 7 - 7 - 1)
bc554df8 118 return error(_("Tracking not set up: name too long: %s"),
e496c003
DB
119 new_ref);
120
121 memset(&tracking, 0, sizeof(tracking));
122 tracking.spec.dst = (char *)orig_ref;
9ed36cfa 123 if (for_each_remote(find_tracked_branch, &tracking))
e496c003
DB
124 return 1;
125
9ed36cfa
JS
126 if (!tracking.matches)
127 switch (track) {
128 case BRANCH_TRACK_ALWAYS:
129 case BRANCH_TRACK_EXPLICIT:
4fc50066 130 case BRANCH_TRACK_OVERRIDE:
9ed36cfa
JS
131 break;
132 default:
133 return 1;
134 }
135
e496c003 136 if (tracking.matches > 1)
bc554df8 137 return error(_("Not tracking: ambiguous information for ref %s"),
e496c003
DB
138 orig_ref);
139
f9a482e6 140 install_branch_config(config_flags, new_ref, tracking.remote,
a9f2c136 141 tracking.src ? tracking.src : orig_ref);
e496c003 142
a9f2c136 143 free(tracking.src);
e496c003
DB
144 return 0;
145}
146
6f9a3321
JH
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
fa799376
JH
178int validate_new_branchname(const char *name, struct strbuf *ref,
179 int force, int attr_only)
55c4a673 180{
55c4a673 181 if (strbuf_check_branch_ref(ref, name))
bc554df8 182 die(_("'%s' is not a valid branch name."), name);
55c4a673
CI
183
184 if (!ref_exists(ref->buf))
185 return 0;
fa799376 186 else if (!force && !attr_only)
bc554df8 187 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
55c4a673 188
fa799376
JH
189 if (!attr_only) {
190 const char *head;
191 unsigned char sha1[20];
55c4a673 192
8cad4744 193 head = resolve_ref_unsafe("HEAD", sha1, 0, NULL);
fa799376 194 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
bc554df8 195 die(_("Cannot force update the current branch."));
fa799376 196 }
55c4a673
CI
197 return 1;
198}
199
41c21f22
JH
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 prefixcmp(query.src, "refs/heads/"));
208}
209
210static int validate_remote_tracking_branch(char *ref)
211{
212 return !for_each_remote(check_tracking_branch, ref);
213}
214
e2b6aa5f 215static const char upstream_not_branch[] =
1a15d00b 216N_("Cannot setup tracking information; starting point '%s' is not a branch.");
a5e91c72 217static const char upstream_missing[] =
caa2036b
JK
218N_("the requested upstream branch '%s' does not exist");
219static const char upstream_advice[] =
220N_("\n"
221"If you are planning on basing your work on an upstream\n"
222"branch that already exists at the remote, you may need to\n"
223"run \"git fetch\" to retrieve it.\n"
224"\n"
225"If you are planning to push out a new local branch that\n"
226"will track its remote counterpart, you may want to use\n"
227"\"git push -u\" to set the upstream config as you push.");
e2b6aa5f 228
e496c003
DB
229void create_branch(const char *head,
230 const char *name, const char *start_name,
39bd6f72 231 int force, int reflog, int clobber_head,
f9a482e6 232 int quiet, enum branch_track track)
e496c003 233{
4fc50066 234 struct ref_lock *lock = NULL;
e496c003
DB
235 struct commit *commit;
236 unsigned char sha1[20];
8415d5c7
JH
237 char *real_ref, msg[PATH_MAX + 20];
238 struct strbuf ref = STRBUF_INIT;
e496c003 239 int forcing = 0;
4fc50066
IL
240 int dont_change_ref = 0;
241 int explicit_tracking = 0;
242
243 if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
244 explicit_tracking = 1;
e496c003 245
fa799376 246 if (validate_new_branchname(name, &ref, force,
39bd6f72
JN
247 track == BRANCH_TRACK_OVERRIDE ||
248 clobber_head)) {
55c4a673 249 if (!force)
4fc50066 250 dont_change_ref = 1;
55c4a673
CI
251 else
252 forcing = 1;
e496c003
DB
253 }
254
255 real_ref = NULL;
a5e91c72 256 if (get_sha1(start_name, sha1)) {
caa2036b
JK
257 if (explicit_tracking) {
258 if (advice_set_upstream_failure) {
259 error(_(upstream_missing), start_name);
260 advise(_(upstream_advice));
261 exit(1);
262 }
1a15d00b 263 die(_(upstream_missing), start_name);
caa2036b 264 }
bc554df8 265 die(_("Not a valid object name: '%s'."), start_name);
a5e91c72 266 }
e496c003
DB
267
268 switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
269 case 0:
270 /* Not branching from any existing branch */
4fc50066 271 if (explicit_tracking)
1a15d00b 272 die(_(upstream_not_branch), start_name);
e496c003
DB
273 break;
274 case 1:
21b5b1e8
JH
275 /* Unique completion -- good, only if it is a real branch */
276 if (prefixcmp(real_ref, "refs/heads/") &&
41c21f22 277 validate_remote_tracking_branch(real_ref)) {
21b5b1e8 278 if (explicit_tracking)
1a15d00b 279 die(_(upstream_not_branch), start_name);
21b5b1e8
JH
280 else
281 real_ref = NULL;
282 }
e496c003
DB
283 break;
284 default:
bc554df8 285 die(_("Ambiguous object name: '%s'."), start_name);
e496c003
DB
286 break;
287 }
288
289 if ((commit = lookup_commit_reference(sha1)) == NULL)
bc554df8 290 die(_("Not a valid branch point: '%s'."), start_name);
e496c003
DB
291 hashcpy(sha1, commit->object.sha1);
292
4fc50066
IL
293 if (!dont_change_ref) {
294 lock = lock_any_ref_for_update(ref.buf, NULL, 0);
295 if (!lock)
bc554df8 296 die_errno(_("Failed to lock ref for update"));
4fc50066 297 }
e496c003
DB
298
299 if (reflog)
300 log_all_ref_updates = 1;
301
302 if (forcing)
da288e25 303 snprintf(msg, sizeof msg, "branch: Reset to %s",
e496c003 304 start_name);
4fc50066 305 else if (!dont_change_ref)
e496c003
DB
306 snprintf(msg, sizeof msg, "branch: Created from %s",
307 start_name);
308
e496c003 309 if (real_ref && track)
f9a482e6 310 setup_tracking(ref.buf+11, real_ref, track, quiet);
e496c003 311
4fc50066
IL
312 if (!dont_change_ref)
313 if (write_ref_sha1(lock, sha1, msg) < 0)
bc554df8 314 die_errno(_("Failed to write ref"));
e496c003 315
8415d5c7 316 strbuf_release(&ref);
9ed36cfa 317 free(real_ref);
e496c003 318}
c369e7b8
DB
319
320void remove_branch_state(void)
321{
d7e5c0cb 322 unlink(git_path("CHERRY_PICK_HEAD"));
82433cdf 323 unlink(git_path("REVERT_HEAD"));
c369e7b8 324 unlink(git_path("MERGE_HEAD"));
0af0ac7e 325 unlink(git_path("MERGE_RR"));
c369e7b8 326 unlink(git_path("MERGE_MSG"));
cf10f9fd 327 unlink(git_path("MERGE_MODE"));
c369e7b8
DB
328 unlink(git_path("SQUASH_MSG"));
329}