remote: show published status and help
[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 void install_branch_publish(const char *name, const char *remote, const char *remote_ref)
167 {
168         struct strbuf key = STRBUF_INIT;
169
170         if (!remote && !strcmp(name, remote_ref + 11) &&
171                         starts_with(remote_ref, "refs/heads")) {
172                 warning(_("Not setting branch %s as its own publish branch."), name);
173                 return;
174         }
175
176         strbuf_addf(&key, "branch.%s.pushremote", name);
177         git_config_set(key.buf, remote ? remote : ".");
178
179         strbuf_reset(&key);
180         strbuf_addf(&key, "branch.%s.push", name);
181         git_config_set(key.buf, remote_ref);
182
183         strbuf_release(&key);
184 }
185
186 int setup_publish(const char *name, const char *ref)
187 {
188         struct tracking tracking;
189         const char *remote, *remote_ref;
190
191         memset(&tracking, 0, sizeof(tracking));
192         tracking.spec.dst = (char *)ref;
193         if (for_each_remote(find_tracked_branch, &tracking))
194                 return 1;
195
196         if (tracking.matches > 1)
197                 return error(_("Not tracking: ambiguous information for ref %s"),
198                                 ref);
199
200         remote = tracking.remote;
201         remote_ref = tracking.src ? tracking.src : ref;
202
203         install_branch_publish(name, remote, remote_ref);
204
205         free(tracking.src);
206
207         return 0;
208 }
209
210 int read_branch_desc(struct strbuf *buf, const char *branch_name)
211 {
212         char *v = NULL;
213         struct strbuf name = STRBUF_INIT;
214         strbuf_addf(&name, "branch.%s.description", branch_name);
215         if (git_config_get_string(name.buf, &v)) {
216                 strbuf_release(&name);
217                 return -1;
218         }
219         strbuf_addstr(buf, v);
220         free(v);
221         strbuf_release(&name);
222         return 0;
223 }
224
225 int validate_new_branchname(const char *name, struct strbuf *ref,
226                             int force, int attr_only)
227 {
228         if (strbuf_check_branch_ref(ref, name))
229                 die(_("'%s' is not a valid branch name."), name);
230
231         if (!ref_exists(ref->buf))
232                 return 0;
233         else if (!force && !attr_only)
234                 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
235
236         if (!attr_only) {
237                 const char *head;
238                 unsigned char sha1[20];
239
240                 head = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
241                 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
242                         die(_("Cannot force update the current branch."));
243         }
244         return 1;
245 }
246
247 static int check_tracking_branch(struct remote *remote, void *cb_data)
248 {
249         char *tracking_branch = cb_data;
250         struct refspec query;
251         memset(&query, 0, sizeof(struct refspec));
252         query.dst = tracking_branch;
253         return !remote_find_tracking(remote, &query);
254 }
255
256 static int validate_remote_tracking_branch(char *ref)
257 {
258         return !for_each_remote(check_tracking_branch, ref);
259 }
260
261 static const char upstream_not_branch[] =
262 N_("Cannot setup tracking information; starting point '%s' is not a branch.");
263 static const char upstream_missing[] =
264 N_("the requested upstream branch '%s' does not exist");
265 static const char upstream_advice[] =
266 N_("\n"
267 "If you are planning on basing your work on an upstream\n"
268 "branch that already exists at the remote, you may need to\n"
269 "run \"git fetch\" to retrieve it.\n"
270 "\n"
271 "If you are planning to push out a new local branch that\n"
272 "will track its remote counterpart, you may want to use\n"
273 "\"git push -u\" to set the upstream config as you push.");
274
275 void create_branch(const char *head,
276                    const char *name, const char *start_name,
277                    int force, int reflog, int clobber_head,
278                    int quiet, enum branch_track track)
279 {
280         struct commit *commit;
281         unsigned char sha1[20];
282         char *real_ref, msg[PATH_MAX + 20];
283         struct strbuf ref = STRBUF_INIT;
284         int forcing = 0;
285         int dont_change_ref = 0;
286         int explicit_tracking = 0;
287
288         if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
289                 explicit_tracking = 1;
290
291         if (validate_new_branchname(name, &ref, force,
292                                     track == BRANCH_TRACK_OVERRIDE ||
293                                     clobber_head)) {
294                 if (!force)
295                         dont_change_ref = 1;
296                 else
297                         forcing = 1;
298         }
299
300         real_ref = NULL;
301         if (get_sha1(start_name, sha1)) {
302                 if (explicit_tracking) {
303                         if (advice_set_upstream_failure) {
304                                 error(_(upstream_missing), start_name);
305                                 advise(_(upstream_advice));
306                                 exit(1);
307                         }
308                         die(_(upstream_missing), start_name);
309                 }
310                 die(_("Not a valid object name: '%s'."), start_name);
311         }
312
313         switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
314         case 0:
315                 /* Not branching from any existing branch */
316                 if (explicit_tracking)
317                         die(_(upstream_not_branch), start_name);
318                 break;
319         case 1:
320                 /* Unique completion -- good, only if it is a real branch */
321                 if (!starts_with(real_ref, "refs/heads/") &&
322                     validate_remote_tracking_branch(real_ref)) {
323                         if (explicit_tracking)
324                                 die(_(upstream_not_branch), start_name);
325                         else
326                                 real_ref = NULL;
327                 }
328                 break;
329         default:
330                 die(_("Ambiguous object name: '%s'."), start_name);
331                 break;
332         }
333
334         if ((commit = lookup_commit_reference(sha1)) == NULL)
335                 die(_("Not a valid branch point: '%s'."), start_name);
336         hashcpy(sha1, commit->object.oid.hash);
337
338         if (forcing)
339                 snprintf(msg, sizeof msg, "branch: Reset to %s",
340                          start_name);
341         else if (!dont_change_ref)
342                 snprintf(msg, sizeof msg, "branch: Created from %s",
343                          start_name);
344
345         if (reflog)
346                 log_all_ref_updates = 1;
347
348         if (!dont_change_ref) {
349                 struct ref_transaction *transaction;
350                 struct strbuf err = STRBUF_INIT;
351
352                 transaction = ref_transaction_begin(&err);
353                 if (!transaction ||
354                     ref_transaction_update(transaction, ref.buf,
355                                            sha1, forcing ? NULL : null_sha1,
356                                            0, msg, &err) ||
357                     ref_transaction_commit(transaction, &err))
358                         die("%s", err.buf);
359                 ref_transaction_free(transaction);
360                 strbuf_release(&err);
361         }
362
363         if (real_ref && track)
364                 setup_tracking(ref.buf + 11, real_ref, track, quiet);
365
366         strbuf_release(&ref);
367         free(real_ref);
368 }
369
370 void remove_branch_state(void)
371 {
372         unlink(git_path_cherry_pick_head());
373         unlink(git_path_revert_head());
374         unlink(git_path_merge_head());
375         unlink(git_path_merge_rr());
376         unlink(git_path_merge_msg());
377         unlink(git_path_merge_mode());
378         unlink(git_path_squash_msg());
379 }
380
381 void die_if_checked_out(const char *branch)
382 {
383         char *existing;
384
385         existing = find_shared_symref("HEAD", branch);
386         if (existing) {
387                 skip_prefix(branch, "refs/heads/", &branch);
388                 die(_("'%s' is already checked out at '%s'"), branch, existing);
389         }
390 }