branch.c: use ref transaction for all ref updates
[alt-git.git] / branch.c
blob37ac555324e4358c300e57f8a398b12250bd5835
1 #include "git-compat-util.h"
2 #include "cache.h"
3 #include "branch.h"
4 #include "refs.h"
5 #include "remote.h"
6 #include "commit.h"
8 struct tracking {
9 struct refspec spec;
10 char *src;
11 const char *remote;
12 int matches;
15 static int find_tracked_branch(struct remote *remote, void *priv)
17 struct tracking *tracking = priv;
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;
30 tracking->spec.src = NULL;
33 return 0;
36 static int should_setup_rebase(const char *origin)
38 switch (autorebase) {
39 case AUTOREBASE_NEVER:
40 return 0;
41 case AUTOREBASE_LOCAL:
42 return origin == NULL;
43 case AUTOREBASE_REMOTE:
44 return origin != NULL;
45 case AUTOREBASE_ALWAYS:
46 return 1;
48 return 0;
51 void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
53 const char *shortname = skip_prefix(remote, "refs/heads/");
54 struct strbuf key = STRBUF_INIT;
55 int rebasing = should_setup_rebase(origin);
57 if (shortname
58 && !strcmp(local, shortname)
59 && !origin) {
60 warning(_("Not setting branch %s as its own upstream."),
61 local);
62 return;
65 strbuf_addf(&key, "branch.%s.remote", local);
66 git_config_set(key.buf, origin ? origin : ".");
68 strbuf_reset(&key);
69 strbuf_addf(&key, "branch.%s.merge", local);
70 git_config_set(key.buf, remote);
72 if (rebasing) {
73 strbuf_reset(&key);
74 strbuf_addf(&key, "branch.%s.rebase", local);
75 git_config_set(key.buf, "true");
77 strbuf_release(&key);
79 if (flag & BRANCH_CONFIG_VERBOSE) {
80 if (shortname) {
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);
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.
111 static int setup_tracking(const char *new_ref, const char *orig_ref,
112 enum branch_track track, int quiet)
114 struct tracking tracking;
115 int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
117 memset(&tracking, 0, sizeof(tracking));
118 tracking.spec.dst = (char *)orig_ref;
119 if (for_each_remote(find_tracked_branch, &tracking))
120 return 1;
122 if (!tracking.matches)
123 switch (track) {
124 case BRANCH_TRACK_ALWAYS:
125 case BRANCH_TRACK_EXPLICIT:
126 case BRANCH_TRACK_OVERRIDE:
127 break;
128 default:
129 return 1;
132 if (tracking.matches > 1)
133 return error(_("Not tracking: ambiguous information for ref %s"),
134 orig_ref);
136 install_branch_config(config_flags, new_ref, tracking.remote,
137 tracking.src ? tracking.src : orig_ref);
139 free(tracking.src);
140 return 0;
143 struct branch_desc_cb {
144 const char *config_name;
145 const char *value;
148 static int read_branch_desc_cb(const char *var, const char *value, void *cb)
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);
157 int read_branch_desc(struct strbuf *buf, const char *branch_name)
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;
168 if (cb.value)
169 strbuf_addstr(buf, cb.value);
170 strbuf_release(&name);
171 return 0;
174 int validate_new_branchname(const char *name, struct strbuf *ref,
175 int force, int attr_only)
177 if (strbuf_check_branch_ref(ref, name))
178 die(_("'%s' is not a valid branch name."), name);
180 if (!ref_exists(ref->buf))
181 return 0;
182 else if (!force && !attr_only)
183 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
185 if (!attr_only) {
186 const char *head;
187 unsigned char sha1[20];
189 head = resolve_ref_unsafe("HEAD", sha1, 0, NULL);
190 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
191 die(_("Cannot force update the current branch."));
193 return 1;
196 static int check_tracking_branch(struct remote *remote, void *cb_data)
198 char *tracking_branch = cb_data;
199 struct refspec query;
200 memset(&query, 0, sizeof(struct refspec));
201 query.dst = tracking_branch;
202 return !remote_find_tracking(remote, &query);
205 static int validate_remote_tracking_branch(char *ref)
207 return !for_each_remote(check_tracking_branch, ref);
210 static const char upstream_not_branch[] =
211 N_("Cannot setup tracking information; starting point '%s' is not a branch.");
212 static const char upstream_missing[] =
213 N_("the requested upstream branch '%s' does not exist");
214 static const char upstream_advice[] =
215 N_("\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.");
224 void create_branch(const char *head,
225 const char *name, const char *start_name,
226 int force, int reflog, int clobber_head,
227 int quiet, enum branch_track track)
229 struct commit *commit;
230 unsigned char sha1[20];
231 char *real_ref, msg[PATH_MAX + 20];
232 struct strbuf ref = STRBUF_INIT;
233 int forcing = 0;
234 int dont_change_ref = 0;
235 int explicit_tracking = 0;
237 if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
238 explicit_tracking = 1;
240 if (validate_new_branchname(name, &ref, force,
241 track == BRANCH_TRACK_OVERRIDE ||
242 clobber_head)) {
243 if (!force)
244 dont_change_ref = 1;
245 else
246 forcing = 1;
249 real_ref = NULL;
250 if (get_sha1(start_name, sha1)) {
251 if (explicit_tracking) {
252 if (advice_set_upstream_failure) {
253 error(_(upstream_missing), start_name);
254 advise(_(upstream_advice));
255 exit(1);
257 die(_(upstream_missing), start_name);
259 die(_("Not a valid object name: '%s'."), start_name);
262 switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
263 case 0:
264 /* Not branching from any existing branch */
265 if (explicit_tracking)
266 die(_(upstream_not_branch), start_name);
267 break;
268 case 1:
269 /* Unique completion -- good, only if it is a real branch */
270 if (!starts_with(real_ref, "refs/heads/") &&
271 validate_remote_tracking_branch(real_ref)) {
272 if (explicit_tracking)
273 die(_(upstream_not_branch), start_name);
274 else
275 real_ref = NULL;
277 break;
278 default:
279 die(_("Ambiguous object name: '%s'."), start_name);
280 break;
283 if ((commit = lookup_commit_reference(sha1)) == NULL)
284 die(_("Not a valid branch point: '%s'."), start_name);
285 hashcpy(sha1, commit->object.sha1);
287 if (forcing)
288 snprintf(msg, sizeof msg, "branch: Reset to %s",
289 start_name);
290 else if (!dont_change_ref)
291 snprintf(msg, sizeof msg, "branch: Created from %s",
292 start_name);
294 if (reflog)
295 log_all_ref_updates = 1;
297 if (!dont_change_ref) {
298 struct ref_transaction *transaction;
299 struct strbuf err = STRBUF_INIT;
301 transaction = ref_transaction_begin(&err);
302 if (!transaction ||
303 ref_transaction_update(transaction, ref.buf, sha1,
304 null_sha1, 0, !forcing, &err) ||
305 ref_transaction_commit(transaction, msg, &err))
306 die("%s", err.buf);
307 ref_transaction_free(transaction);
308 strbuf_release(&err);
311 if (real_ref && track)
312 setup_tracking(ref.buf + 11, real_ref, track, quiet);
314 strbuf_release(&ref);
315 free(real_ref);
318 void remove_branch_state(void)
320 unlink(git_path("CHERRY_PICK_HEAD"));
321 unlink(git_path("REVERT_HEAD"));
322 unlink(git_path("MERGE_HEAD"));
323 unlink(git_path("MERGE_RR"));
324 unlink(git_path("MERGE_MSG"));
325 unlink(git_path("MERGE_MODE"));
326 unlink(git_path("SQUASH_MSG"));