shallow: convert shallow registration functions to object_id
[git] / branch.c
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"
7 #include "worktree.h"
8
9 struct tracking {
10         struct refspec spec;
11         char *src;
12         const char *remote;
13         int matches;
14 };
15
16 static int find_tracked_branch(struct remote *remote, void *priv)
17 {
18         struct tracking *tracking = priv;
19
20         if (!remote_find_tracking(remote, &tracking->spec)) {
21                 if (++tracking->matches == 1) {
22                         tracking->src = tracking->spec.src;
23                         tracking->remote = remote->name;
24                 } else {
25                         free(tracking->spec.src);
26                         if (tracking->src) {
27                                 free(tracking->src);
28                                 tracking->src = NULL;
29                         }
30                 }
31                 tracking->spec.src = NULL;
32         }
33
34         return 0;
35 }
36
37 static int should_setup_rebase(const char *origin)
38 {
39         switch (autorebase) {
40         case AUTOREBASE_NEVER:
41                 return 0;
42         case AUTOREBASE_LOCAL:
43                 return origin == NULL;
44         case AUTOREBASE_REMOTE:
45                 return origin != NULL;
46         case AUTOREBASE_ALWAYS:
47                 return 1;
48         }
49         return 0;
50 }
51
52 static const char tracking_advice[] =
53 N_("\n"
54 "After fixing the error cause you may try to fix up\n"
55 "the remote tracking information by invoking\n"
56 "\"git branch --set-upstream-to=%s%s%s\".");
57
58 int install_branch_config(int flag, const char *local, const char *origin, const char *remote)
59 {
60         const char *shortname = NULL;
61         struct strbuf key = STRBUF_INIT;
62         int rebasing = should_setup_rebase(origin);
63
64         if (skip_prefix(remote, "refs/heads/", &shortname)
65             && !strcmp(local, shortname)
66             && !origin) {
67                 warning(_("Not setting branch %s as its own upstream."),
68                         local);
69                 return 0;
70         }
71
72         strbuf_addf(&key, "branch.%s.remote", local);
73         if (git_config_set_gently(key.buf, origin ? origin : ".") < 0)
74                 goto out_err;
75
76         strbuf_reset(&key);
77         strbuf_addf(&key, "branch.%s.merge", local);
78         if (git_config_set_gently(key.buf, remote) < 0)
79                 goto out_err;
80
81         if (rebasing) {
82                 strbuf_reset(&key);
83                 strbuf_addf(&key, "branch.%s.rebase", local);
84                 if (git_config_set_gently(key.buf, "true") < 0)
85                         goto out_err;
86         }
87         strbuf_release(&key);
88
89         if (flag & BRANCH_CONFIG_VERBOSE) {
90                 if (shortname) {
91                         if (origin)
92                                 printf_ln(rebasing ?
93                                           _("Branch %s set up to track remote branch %s from %s by rebasing.") :
94                                           _("Branch %s set up to track remote branch %s from %s."),
95                                           local, shortname, origin);
96                         else
97                                 printf_ln(rebasing ?
98                                           _("Branch %s set up to track local branch %s by rebasing.") :
99                                           _("Branch %s set up to track local branch %s."),
100                                           local, shortname);
101                 } else {
102                         if (origin)
103                                 printf_ln(rebasing ?
104                                           _("Branch %s set up to track remote ref %s by rebasing.") :
105                                           _("Branch %s set up to track remote ref %s."),
106                                           local, remote);
107                         else
108                                 printf_ln(rebasing ?
109                                           _("Branch %s set up to track local ref %s by rebasing.") :
110                                           _("Branch %s set up to track local ref %s."),
111                                           local, remote);
112                 }
113         }
114
115         return 0;
116
117 out_err:
118         strbuf_release(&key);
119         error(_("Unable to write upstream branch configuration"));
120
121         advise(_(tracking_advice),
122                origin ? origin : "",
123                origin ? "/" : "",
124                shortname ? shortname : remote);
125
126         return -1;
127 }
128
129 /*
130  * This is called when new_ref is branched off of orig_ref, and tries
131  * to infer the settings for branch.<new_ref>.{remote,merge} from the
132  * config.
133  */
134 static void setup_tracking(const char *new_ref, const char *orig_ref,
135                            enum branch_track track, int quiet)
136 {
137         struct tracking tracking;
138         int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
139
140         memset(&tracking, 0, sizeof(tracking));
141         tracking.spec.dst = (char *)orig_ref;
142         if (for_each_remote(find_tracked_branch, &tracking))
143                 return;
144
145         if (!tracking.matches)
146                 switch (track) {
147                 case BRANCH_TRACK_ALWAYS:
148                 case BRANCH_TRACK_EXPLICIT:
149                 case BRANCH_TRACK_OVERRIDE:
150                         break;
151                 default:
152                         return;
153                 }
154
155         if (tracking.matches > 1)
156                 die(_("Not tracking: ambiguous information for ref %s"),
157                     orig_ref);
158
159         if (install_branch_config(config_flags, new_ref, tracking.remote,
160                               tracking.src ? tracking.src : orig_ref) < 0)
161                 exit(-1);
162
163         free(tracking.src);
164 }
165
166 int read_branch_desc(struct strbuf *buf, const char *branch_name)
167 {
168         char *v = NULL;
169         struct strbuf name = STRBUF_INIT;
170         strbuf_addf(&name, "branch.%s.description", branch_name);
171         if (git_config_get_string(name.buf, &v)) {
172                 strbuf_release(&name);
173                 return -1;
174         }
175         strbuf_addstr(buf, v);
176         free(v);
177         strbuf_release(&name);
178         return 0;
179 }
180
181 int validate_new_branchname(const char *name, struct strbuf *ref,
182                             int force, int attr_only)
183 {
184         if (strbuf_check_branch_ref(ref, name))
185                 die(_("'%s' is not a valid branch name."), name);
186
187         if (!ref_exists(ref->buf))
188                 return 0;
189         else if (!force && !attr_only)
190                 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
191
192         if (!attr_only) {
193                 const char *head;
194                 struct object_id oid;
195
196                 head = resolve_ref_unsafe("HEAD", 0, oid.hash, NULL);
197                 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
198                         die(_("Cannot force update the current branch."));
199         }
200         return 1;
201 }
202
203 static int check_tracking_branch(struct remote *remote, void *cb_data)
204 {
205         char *tracking_branch = cb_data;
206         struct refspec query;
207         memset(&query, 0, sizeof(struct refspec));
208         query.dst = tracking_branch;
209         return !remote_find_tracking(remote, &query);
210 }
211
212 static int validate_remote_tracking_branch(char *ref)
213 {
214         return !for_each_remote(check_tracking_branch, ref);
215 }
216
217 static const char upstream_not_branch[] =
218 N_("Cannot setup tracking information; starting point '%s' is not a branch.");
219 static const char upstream_missing[] =
220 N_("the requested upstream branch '%s' does not exist");
221 static const char upstream_advice[] =
222 N_("\n"
223 "If you are planning on basing your work on an upstream\n"
224 "branch that already exists at the remote, you may need to\n"
225 "run \"git fetch\" to retrieve it.\n"
226 "\n"
227 "If you are planning to push out a new local branch that\n"
228 "will track its remote counterpart, you may want to use\n"
229 "\"git push -u\" to set the upstream config as you push.");
230
231 void create_branch(const char *name, const char *start_name,
232                    int force, int reflog, int clobber_head,
233                    int quiet, enum branch_track track)
234 {
235         struct commit *commit;
236         struct object_id oid;
237         char *real_ref;
238         struct strbuf ref = STRBUF_INIT;
239         int forcing = 0;
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;
245
246         if (validate_new_branchname(name, &ref, force,
247                                     track == BRANCH_TRACK_OVERRIDE ||
248                                     clobber_head)) {
249                 if (!force)
250                         dont_change_ref = 1;
251                 else
252                         forcing = 1;
253         }
254
255         real_ref = NULL;
256         if (get_oid(start_name, &oid)) {
257                 if (explicit_tracking) {
258                         if (advice_set_upstream_failure) {
259                                 error(_(upstream_missing), start_name);
260                                 advise(_(upstream_advice));
261                                 exit(1);
262                         }
263                         die(_(upstream_missing), start_name);
264                 }
265                 die(_("Not a valid object name: '%s'."), start_name);
266         }
267
268         switch (dwim_ref(start_name, strlen(start_name), oid.hash, &real_ref)) {
269         case 0:
270                 /* Not branching from any existing branch */
271                 if (explicit_tracking)
272                         die(_(upstream_not_branch), start_name);
273                 break;
274         case 1:
275                 /* Unique completion -- good, only if it is a real branch */
276                 if (!starts_with(real_ref, "refs/heads/") &&
277                     validate_remote_tracking_branch(real_ref)) {
278                         if (explicit_tracking)
279                                 die(_(upstream_not_branch), start_name);
280                         else
281                                 real_ref = NULL;
282                 }
283                 break;
284         default:
285                 die(_("Ambiguous object name: '%s'."), start_name);
286                 break;
287         }
288
289         if ((commit = lookup_commit_reference(oid.hash)) == NULL)
290                 die(_("Not a valid branch point: '%s'."), start_name);
291         oidcpy(&oid, &commit->object.oid);
292
293         if (reflog)
294                 log_all_ref_updates = LOG_REFS_NORMAL;
295
296         if (!dont_change_ref) {
297                 struct ref_transaction *transaction;
298                 struct strbuf err = STRBUF_INIT;
299                 char *msg;
300
301                 if (forcing)
302                         msg = xstrfmt("branch: Reset to %s", start_name);
303                 else
304                         msg = xstrfmt("branch: Created from %s", start_name);
305
306                 transaction = ref_transaction_begin(&err);
307                 if (!transaction ||
308                     ref_transaction_update(transaction, ref.buf,
309                                            oid.hash, forcing ? NULL : null_sha1,
310                                            0, msg, &err) ||
311                     ref_transaction_commit(transaction, &err))
312                         die("%s", err.buf);
313                 ref_transaction_free(transaction);
314                 strbuf_release(&err);
315                 free(msg);
316         }
317
318         if (real_ref && track)
319                 setup_tracking(ref.buf + 11, real_ref, track, quiet);
320
321         strbuf_release(&ref);
322         free(real_ref);
323 }
324
325 void remove_branch_state(void)
326 {
327         unlink(git_path_cherry_pick_head());
328         unlink(git_path_revert_head());
329         unlink(git_path_merge_head());
330         unlink(git_path_merge_rr());
331         unlink(git_path_merge_msg());
332         unlink(git_path_merge_mode());
333         unlink(git_path_squash_msg());
334 }
335
336 void die_if_checked_out(const char *branch, int ignore_current_worktree)
337 {
338         const struct worktree *wt;
339
340         wt = find_shared_symref("HEAD", branch);
341         if (!wt || (ignore_current_worktree && wt->is_current))
342                 return;
343         skip_prefix(branch, "refs/heads/", &branch);
344         die(_("'%s' is already checked out at '%s'"),
345             branch, wt->path);
346 }
347
348 int replace_each_worktree_head_symref(const char *oldref, const char *newref,
349                                       const char *logmsg)
350 {
351         int ret = 0;
352         struct worktree **worktrees = get_worktrees(0);
353         int i;
354
355         for (i = 0; worktrees[i]; i++) {
356                 if (worktrees[i]->is_detached)
357                         continue;
358                 if (strcmp(oldref, worktrees[i]->head_ref))
359                         continue;
360
361                 if (set_worktree_head_symref(get_worktree_git_dir(worktrees[i]),
362                                              newref, logmsg)) {
363                         ret = -1;
364                         error(_("HEAD of working tree %s is not updated"),
365                               worktrees[i]->path);
366                 }
367         }
368
369         free_worktrees(worktrees);
370         return ret;
371 }