t2026: rename worktree prune test
[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
8 struct tracking {
9         struct refspec spec;
10         char *src;
11         const char *remote;
12         int matches;
13 };
14
15 static 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
36 static int should_setup_rebase(const char *origin)
37 {
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;
47         }
48         return 0;
49 }
50
51 void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
52 {
53         const char *shortname = NULL;
54         struct strbuf key = STRBUF_INIT;
55         int rebasing = should_setup_rebase(origin);
56
57         if (skip_prefix(remote, "refs/heads/", &shortname)
58             && !strcmp(local, shortname)
59             && !origin) {
60                 warning(_("Not setting branch %s as its own upstream."),
61                         local);
62                 return;
63         }
64
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         }
77         strbuf_release(&key);
78
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);
102                 }
103         }
104 }
105
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  */
111 static int setup_tracking(const char *new_ref, const char *orig_ref,
112                           enum branch_track track, int quiet)
113 {
114         struct tracking tracking;
115         int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
116
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;
121
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;
130                 }
131
132         if (tracking.matches > 1)
133                 return error(_("Not tracking: ambiguous information for ref %s"),
134                                 orig_ref);
135
136         install_branch_config(config_flags, new_ref, tracking.remote,
137                               tracking.src ? tracking.src : orig_ref);
138
139         free(tracking.src);
140         return 0;
141 }
142
143 int read_branch_desc(struct strbuf *buf, const char *branch_name)
144 {
145         char *v = NULL;
146         struct strbuf name = STRBUF_INIT;
147         strbuf_addf(&name, "branch.%s.description", branch_name);
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);
154         strbuf_release(&name);
155         return 0;
156 }
157
158 int validate_new_branchname(const char *name, struct strbuf *ref,
159                             int force, int attr_only)
160 {
161         if (strbuf_check_branch_ref(ref, name))
162                 die(_("'%s' is not a valid branch name."), name);
163
164         if (!ref_exists(ref->buf))
165                 return 0;
166         else if (!force && !attr_only)
167                 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
168
169         if (!attr_only) {
170                 const char *head;
171                 unsigned char sha1[20];
172
173                 head = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
174                 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
175                         die(_("Cannot force update the current branch."));
176         }
177         return 1;
178 }
179
180 static 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;
186         return !remote_find_tracking(remote, &query);
187 }
188
189 static int validate_remote_tracking_branch(char *ref)
190 {
191         return !for_each_remote(check_tracking_branch, ref);
192 }
193
194 static const char upstream_not_branch[] =
195 N_("Cannot setup tracking information; starting point '%s' is not a branch.");
196 static const char upstream_missing[] =
197 N_("the requested upstream branch '%s' does not exist");
198 static const char upstream_advice[] =
199 N_("\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.");
207
208 void create_branch(const char *head,
209                    const char *name, const char *start_name,
210                    int force, int reflog, int clobber_head,
211                    int quiet, enum branch_track track)
212 {
213         struct commit *commit;
214         unsigned char sha1[20];
215         char *real_ref, msg[PATH_MAX + 20];
216         struct strbuf ref = STRBUF_INIT;
217         int forcing = 0;
218         int dont_change_ref = 0;
219         int explicit_tracking = 0;
220
221         if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
222                 explicit_tracking = 1;
223
224         if (validate_new_branchname(name, &ref, force,
225                                     track == BRANCH_TRACK_OVERRIDE ||
226                                     clobber_head)) {
227                 if (!force)
228                         dont_change_ref = 1;
229                 else
230                         forcing = 1;
231         }
232
233         real_ref = NULL;
234         if (get_sha1(start_name, sha1)) {
235                 if (explicit_tracking) {
236                         if (advice_set_upstream_failure) {
237                                 error(_(upstream_missing), start_name);
238                                 advise(_(upstream_advice));
239                                 exit(1);
240                         }
241                         die(_(upstream_missing), start_name);
242                 }
243                 die(_("Not a valid object name: '%s'."), start_name);
244         }
245
246         switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
247         case 0:
248                 /* Not branching from any existing branch */
249                 if (explicit_tracking)
250                         die(_(upstream_not_branch), start_name);
251                 break;
252         case 1:
253                 /* Unique completion -- good, only if it is a real branch */
254                 if (!starts_with(real_ref, "refs/heads/") &&
255                     validate_remote_tracking_branch(real_ref)) {
256                         if (explicit_tracking)
257                                 die(_(upstream_not_branch), start_name);
258                         else
259                                 real_ref = NULL;
260                 }
261                 break;
262         default:
263                 die(_("Ambiguous object name: '%s'."), start_name);
264                 break;
265         }
266
267         if ((commit = lookup_commit_reference(sha1)) == NULL)
268                 die(_("Not a valid branch point: '%s'."), start_name);
269         hashcpy(sha1, commit->object.sha1);
270
271         if (forcing)
272                 snprintf(msg, sizeof msg, "branch: Reset to %s",
273                          start_name);
274         else if (!dont_change_ref)
275                 snprintf(msg, sizeof msg, "branch: Created from %s",
276                          start_name);
277
278         if (reflog)
279                 log_all_ref_updates = 1;
280
281         if (!dont_change_ref) {
282                 struct ref_transaction *transaction;
283                 struct strbuf err = STRBUF_INIT;
284
285                 transaction = ref_transaction_begin(&err);
286                 if (!transaction ||
287                     ref_transaction_update(transaction, ref.buf, sha1,
288                                            null_sha1, 0, !forcing, msg, &err) ||
289                     ref_transaction_commit(transaction, &err))
290                         die("%s", err.buf);
291                 ref_transaction_free(transaction);
292                 strbuf_release(&err);
293         }
294
295         if (real_ref && track)
296                 setup_tracking(ref.buf + 11, real_ref, track, quiet);
297
298         strbuf_release(&ref);
299         free(real_ref);
300 }
301
302 void remove_branch_state(void)
303 {
304         unlink(git_path("CHERRY_PICK_HEAD"));
305         unlink(git_path("REVERT_HEAD"));
306         unlink(git_path("MERGE_HEAD"));
307         unlink(git_path("MERGE_RR"));
308         unlink(git_path("MERGE_MSG"));
309         unlink(git_path("MERGE_MODE"));
310         unlink(git_path("SQUASH_MSG"));
311 }
312
313 static void check_linked_checkout(const char *branch, const char *id)
314 {
315         struct strbuf sb = STRBUF_INIT;
316         struct strbuf path = STRBUF_INIT;
317         struct strbuf gitdir = STRBUF_INIT;
318
319         /*
320          * $GIT_COMMON_DIR/HEAD is practically outside
321          * $GIT_DIR so resolve_ref_unsafe() won't work (it
322          * uses git_path). Parse the ref ourselves.
323          */
324         if (id)
325                 strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);
326         else
327                 strbuf_addf(&path, "%s/HEAD", get_git_common_dir());
328
329         if (!strbuf_readlink(&sb, path.buf, 0)) {
330                 if (!starts_with(sb.buf, "refs/") ||
331                     check_refname_format(sb.buf, 0))
332                         goto done;
333         } else if (strbuf_read_file(&sb, path.buf, 0) >= 0 &&
334             starts_with(sb.buf, "ref:")) {
335                 strbuf_remove(&sb, 0, strlen("ref:"));
336                 strbuf_trim(&sb);
337         } else
338                 goto done;
339         if (strcmp(sb.buf, branch))
340                 goto done;
341         if (id) {
342                 strbuf_reset(&path);
343                 strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id);
344                 if (strbuf_read_file(&gitdir, path.buf, 0) <= 0)
345                         goto done;
346                 strbuf_rtrim(&gitdir);
347         } else
348                 strbuf_addstr(&gitdir, get_git_common_dir());
349         skip_prefix(branch, "refs/heads/", &branch);
350         strbuf_strip_suffix(&gitdir, ".git");
351         die(_("'%s' is already checked out at '%s'"), branch, gitdir.buf);
352 done:
353         strbuf_release(&path);
354         strbuf_release(&sb);
355         strbuf_release(&gitdir);
356 }
357
358 void die_if_checked_out(const char *branch)
359 {
360         struct strbuf path = STRBUF_INIT;
361         DIR *dir;
362         struct dirent *d;
363
364         check_linked_checkout(branch, NULL);
365
366         strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
367         dir = opendir(path.buf);
368         strbuf_release(&path);
369         if (!dir)
370                 return;
371
372         while ((d = readdir(dir)) != NULL) {
373                 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
374                         continue;
375                 check_linked_checkout(branch, d->d_name);
376         }
377         closedir(dir);
378 }