]> git.ipfire.org Git - thirdparty/git.git/blame - branch.c
t9114.2: Don't use --track option against "svn-remote"-tracking branches
[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) {
60 warning("Not setting branch %s as its own upstream.",
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
NTND
80 if (remote_is_branch && origin)
81 printf(rebasing ?
82 "Branch %s set up to track remote branch %s from %s by rebasing.\n" :
83 "Branch %s set up to track remote branch %s from %s.\n",
84 local, shortname, origin);
85 else if (remote_is_branch && !origin)
86 printf(rebasing ?
87 "Branch %s set up to track local branch %s by rebasing.\n" :
88 "Branch %s set up to track local branch %s.\n",
89 local, shortname);
90 else if (!remote_is_branch && origin)
91 printf(rebasing ?
92 "Branch %s set up to track remote ref %s by rebasing.\n" :
93 "Branch %s set up to track remote ref %s.\n",
94 local, remote);
95 else if (!remote_is_branch && !origin)
96 printf(rebasing ?
97 "Branch %s set up to track local ref %s by rebasing.\n" :
98 "Branch %s set up to track local ref %s.\n",
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)
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;
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
DB
136 if (tracking.matches > 1)
137 return error("Not tracking: ambiguous information for ref %s",
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
CI
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;
fa799376 186 else if (!force && !attr_only)
587a9ee7 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
JH
194 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
195 die("Cannot force update the current branch.");
196 }
55c4a673
CI
197 return 1;
198}
199
e2b6aa5f 200static const char upstream_not_branch[] =
1a15d00b 201N_("Cannot setup tracking information; starting point '%s' is not a branch.");
a5e91c72 202static const char upstream_missing[] =
caa2036b
JK
203N_("the requested upstream branch '%s' does not exist");
204static const char upstream_advice[] =
205N_("\n"
206"If you are planning on basing your work on an upstream\n"
207"branch that already exists at the remote, you may need to\n"
208"run \"git fetch\" to retrieve it.\n"
209"\n"
210"If you are planning to push out a new local branch that\n"
211"will track its remote counterpart, you may want to use\n"
212"\"git push -u\" to set the upstream config as you push.");
e2b6aa5f 213
e496c003
DB
214void create_branch(const char *head,
215 const char *name, const char *start_name,
39bd6f72 216 int force, int reflog, int clobber_head,
f9a482e6 217 int quiet, enum branch_track track)
e496c003 218{
4fc50066 219 struct ref_lock *lock = NULL;
e496c003
DB
220 struct commit *commit;
221 unsigned char sha1[20];
8415d5c7
JH
222 char *real_ref, msg[PATH_MAX + 20];
223 struct strbuf ref = STRBUF_INIT;
e496c003 224 int forcing = 0;
4fc50066
IL
225 int dont_change_ref = 0;
226 int explicit_tracking = 0;
227
228 if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
229 explicit_tracking = 1;
e496c003 230
fa799376 231 if (validate_new_branchname(name, &ref, force,
39bd6f72
JN
232 track == BRANCH_TRACK_OVERRIDE ||
233 clobber_head)) {
55c4a673 234 if (!force)
4fc50066 235 dont_change_ref = 1;
55c4a673
CI
236 else
237 forcing = 1;
e496c003
DB
238 }
239
240 real_ref = NULL;
a5e91c72 241 if (get_sha1(start_name, sha1)) {
caa2036b
JK
242 if (explicit_tracking) {
243 if (advice_set_upstream_failure) {
244 error(_(upstream_missing), start_name);
245 advise(_(upstream_advice));
246 exit(1);
247 }
1a15d00b 248 die(_(upstream_missing), start_name);
caa2036b 249 }
e496c003 250 die("Not a valid object name: '%s'.", start_name);
a5e91c72 251 }
e496c003
DB
252
253 switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
254 case 0:
255 /* Not branching from any existing branch */
4fc50066 256 if (explicit_tracking)
1a15d00b 257 die(_(upstream_not_branch), start_name);
e496c003
DB
258 break;
259 case 1:
21b5b1e8
JH
260 /* Unique completion -- good, only if it is a real branch */
261 if (prefixcmp(real_ref, "refs/heads/") &&
262 prefixcmp(real_ref, "refs/remotes/")) {
263 if (explicit_tracking)
1a15d00b 264 die(_(upstream_not_branch), start_name);
21b5b1e8
JH
265 else
266 real_ref = NULL;
267 }
e496c003
DB
268 break;
269 default:
270 die("Ambiguous object name: '%s'.", start_name);
271 break;
272 }
273
274 if ((commit = lookup_commit_reference(sha1)) == NULL)
275 die("Not a valid branch point: '%s'.", start_name);
276 hashcpy(sha1, commit->object.sha1);
277
4fc50066
IL
278 if (!dont_change_ref) {
279 lock = lock_any_ref_for_update(ref.buf, NULL, 0);
280 if (!lock)
281 die_errno("Failed to lock ref for update");
282 }
e496c003
DB
283
284 if (reflog)
285 log_all_ref_updates = 1;
286
287 if (forcing)
da288e25 288 snprintf(msg, sizeof msg, "branch: Reset to %s",
e496c003 289 start_name);
4fc50066 290 else if (!dont_change_ref)
e496c003
DB
291 snprintf(msg, sizeof msg, "branch: Created from %s",
292 start_name);
293
e496c003 294 if (real_ref && track)
f9a482e6 295 setup_tracking(ref.buf+11, real_ref, track, quiet);
e496c003 296
4fc50066
IL
297 if (!dont_change_ref)
298 if (write_ref_sha1(lock, sha1, msg) < 0)
299 die_errno("Failed to write ref");
e496c003 300
8415d5c7 301 strbuf_release(&ref);
9ed36cfa 302 free(real_ref);
e496c003 303}
c369e7b8
DB
304
305void remove_branch_state(void)
306{
d7e5c0cb 307 unlink(git_path("CHERRY_PICK_HEAD"));
82433cdf 308 unlink(git_path("REVERT_HEAD"));
c369e7b8 309 unlink(git_path("MERGE_HEAD"));
0af0ac7e 310 unlink(git_path("MERGE_RR"));
c369e7b8 311 unlink(git_path("MERGE_MSG"));
cf10f9fd 312 unlink(git_path("MERGE_MODE"));
c369e7b8
DB
313 unlink(git_path("SQUASH_MSG"));
314}