]> git.scripts.mit.edu Git - git.git/blob - branch.c
test-sha1: add a binary output mode
[git.git] / branch.c
1 #include "cache.h"
2 #include "branch.h"
3 #include "refs.h"
4 #include "remote.h"
5 #include "commit.h"
6
7 struct tracking {
8         struct refspec spec;
9         char *src;
10         const char *remote;
11         int matches;
12 };
13
14 static 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
35 static int should_setup_rebase(const char *origin)
36 {
37         switch (autorebase) {
38         case AUTOREBASE_NEVER:
39                 return 0;
40         case AUTOREBASE_LOCAL:
41                 return origin == NULL;
42         case AUTOREBASE_REMOTE:
43                 return origin != NULL;
44         case AUTOREBASE_ALWAYS:
45                 return 1;
46         }
47         return 0;
48 }
49
50 void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
51 {
52         const char *shortname = remote + 11;
53         int remote_is_branch = !prefixcmp(remote, "refs/heads/");
54         struct strbuf key = STRBUF_INIT;
55         int rebasing = should_setup_rebase(origin);
56
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
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 (remote_is_branch && origin)
81                         printf_ln(rebasing ?
82                                   _("Branch %s set up to track remote branch %s from %s by rebasing.") :
83                                   _("Branch %s set up to track remote branch %s from %s."),
84                                   local, shortname, origin);
85                 else if (remote_is_branch && !origin)
86                         printf_ln(rebasing ?
87                                   _("Branch %s set up to track local branch %s by rebasing.") :
88                                   _("Branch %s set up to track local branch %s."),
89                                   local, shortname);
90                 else if (!remote_is_branch && origin)
91                         printf_ln(rebasing ?
92                                   _("Branch %s set up to track remote ref %s by rebasing.") :
93                                   _("Branch %s set up to track remote ref %s."),
94                                   local, remote);
95                 else if (!remote_is_branch && !origin)
96                         printf_ln(rebasing ?
97                                   _("Branch %s set up to track local ref %s by rebasing.") :
98                                   _("Branch %s set up to track local ref %s."),
99                                   local, remote);
100                 else
101                         die("BUG: impossible combination of %d and %p",
102                             remote_is_branch, origin);
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         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;
123         if (for_each_remote(find_tracked_branch, &tracking))
124                 return 1;
125
126         if (!tracking.matches)
127                 switch (track) {
128                 case BRANCH_TRACK_ALWAYS:
129                 case BRANCH_TRACK_EXPLICIT:
130                 case BRANCH_TRACK_OVERRIDE:
131                         break;
132                 default:
133                         return 1;
134                 }
135
136         if (tracking.matches > 1)
137                 return error(_("Not tracking: ambiguous information for ref %s"),
138                                 orig_ref);
139
140         install_branch_config(config_flags, new_ref, tracking.remote,
141                               tracking.src ? tracking.src : orig_ref);
142
143         free(tracking.src);
144         return 0;
145 }
146
147 struct branch_desc_cb {
148         const char *config_name;
149         const char *value;
150 };
151
152 static 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
161 int 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
178 int validate_new_branchname(const char *name, struct strbuf *ref,
179                             int force, int attr_only)
180 {
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;
186         else if (!force && !attr_only)
187                 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
188
189         if (!attr_only) {
190                 const char *head;
191                 unsigned char sha1[20];
192
193                 head = resolve_ref_unsafe("HEAD", sha1, 0, NULL);
194                 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
195                         die(_("Cannot force update the current branch."));
196         }
197         return 1;
198 }
199
200 static int check_tracking_branch(struct remote *remote, void *cb_data)
201 {
202         char *tracking_branch = cb_data;
203         struct refspec query;
204         memset(&query, 0, sizeof(struct refspec));
205         query.dst = tracking_branch;
206         return !(remote_find_tracking(remote, &query) ||
207                  prefixcmp(query.src, "refs/heads/"));
208 }
209
210 static int validate_remote_tracking_branch(char *ref)
211 {
212         return !for_each_remote(check_tracking_branch, ref);
213 }
214
215 static const char upstream_not_branch[] =
216 N_("Cannot setup tracking information; starting point '%s' is not a branch.");
217 static const char upstream_missing[] =
218 N_("the requested upstream branch '%s' does not exist");
219 static const char upstream_advice[] =
220 N_("\n"
221 "If you are planning on basing your work on an upstream\n"
222 "branch that already exists at the remote, you may need to\n"
223 "run \"git fetch\" to retrieve it.\n"
224 "\n"
225 "If you are planning to push out a new local branch that\n"
226 "will track its remote counterpart, you may want to use\n"
227 "\"git push -u\" to set the upstream config as you push.");
228
229 void create_branch(const char *head,
230                    const char *name, const char *start_name,
231                    int force, int reflog, int clobber_head,
232                    int quiet, enum branch_track track)
233 {
234         struct ref_lock *lock = NULL;
235         struct commit *commit;
236         unsigned char sha1[20];
237         char *real_ref, msg[PATH_MAX + 20];
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_sha1(start_name, sha1)) {
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), sha1, &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 (prefixcmp(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(sha1)) == NULL)
290                 die(_("Not a valid branch point: '%s'."), start_name);
291         hashcpy(sha1, commit->object.sha1);
292
293         if (!dont_change_ref) {
294                 lock = lock_any_ref_for_update(ref.buf, NULL, 0);
295                 if (!lock)
296                         die_errno(_("Failed to lock ref for update"));
297         }
298
299         if (reflog)
300                 log_all_ref_updates = 1;
301
302         if (forcing)
303                 snprintf(msg, sizeof msg, "branch: Reset to %s",
304                          start_name);
305         else if (!dont_change_ref)
306                 snprintf(msg, sizeof msg, "branch: Created from %s",
307                          start_name);
308
309         if (real_ref && track)
310                 setup_tracking(ref.buf+11, real_ref, track, quiet);
311
312         if (!dont_change_ref)
313                 if (write_ref_sha1(lock, sha1, msg) < 0)
314                         die_errno(_("Failed to write ref"));
315
316         strbuf_release(&ref);
317         free(real_ref);
318 }
319
320 void remove_branch_state(void)
321 {
322         unlink(git_path("CHERRY_PICK_HEAD"));
323         unlink(git_path("REVERT_HEAD"));
324         unlink(git_path("MERGE_HEAD"));
325         unlink(git_path("MERGE_RR"));
326         unlink(git_path("MERGE_MSG"));
327         unlink(git_path("MERGE_MODE"));
328         unlink(git_path("SQUASH_MSG"));
329 }