Merge branch 'jc/maint-apply-match-beginning'
[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 /*
36  * This is called when new_ref is branched off of orig_ref, and tries
37  * to infer the settings for branch.<new_ref>.{remote,merge} from the
38  * config.
39  */
40 static int setup_tracking(const char *new_ref, const char *orig_ref,
41                           enum branch_track track)
42 {
43         char key[1024];
44         struct tracking tracking;
45
46         if (strlen(new_ref) > 1024 - 7 - 7 - 1)
47                 return error("Tracking not set up: name too long: %s",
48                                 new_ref);
49
50         memset(&tracking, 0, sizeof(tracking));
51         tracking.spec.dst = (char *)orig_ref;
52         if (for_each_remote(find_tracked_branch, &tracking))
53                 return 1;
54
55         if (!tracking.matches)
56                 switch (track) {
57                 case BRANCH_TRACK_ALWAYS:
58                 case BRANCH_TRACK_EXPLICIT:
59                         break;
60                 default:
61                         return 1;
62                 }
63
64         if (tracking.matches > 1)
65                 return error("Not tracking: ambiguous information for ref %s",
66                                 orig_ref);
67
68         sprintf(key, "branch.%s.remote", new_ref);
69         git_config_set(key, tracking.remote ?  tracking.remote : ".");
70         sprintf(key, "branch.%s.merge", new_ref);
71         git_config_set(key, tracking.src ? tracking.src : orig_ref);
72         free(tracking.src);
73         printf("Branch %s set up to track %s branch %s.\n", new_ref,
74                 tracking.remote ? "remote" : "local", orig_ref);
75
76         return 0;
77 }
78
79 void create_branch(const char *head,
80                    const char *name, const char *start_name,
81                    int force, int reflog, enum branch_track track)
82 {
83         struct ref_lock *lock;
84         struct commit *commit;
85         unsigned char sha1[20];
86         char *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20];
87         int forcing = 0;
88
89         snprintf(ref, sizeof ref, "refs/heads/%s", name);
90         if (check_ref_format(ref))
91                 die("'%s' is not a valid branch name.", name);
92
93         if (resolve_ref(ref, sha1, 1, NULL)) {
94                 if (!force)
95                         die("A branch named '%s' already exists.", name);
96                 else if (!is_bare_repository() && !strcmp(head, name))
97                         die("Cannot force update the current branch.");
98                 forcing = 1;
99         }
100
101         real_ref = NULL;
102         if (get_sha1(start_name, sha1))
103                 die("Not a valid object name: '%s'.", start_name);
104
105         switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
106         case 0:
107                 /* Not branching from any existing branch */
108                 if (track == BRANCH_TRACK_EXPLICIT)
109                         die("Cannot setup tracking information; starting point is not a branch.");
110                 break;
111         case 1:
112                 /* Unique completion -- good */
113                 break;
114         default:
115                 die("Ambiguous object name: '%s'.", start_name);
116                 break;
117         }
118
119         if ((commit = lookup_commit_reference(sha1)) == NULL)
120                 die("Not a valid branch point: '%s'.", start_name);
121         hashcpy(sha1, commit->object.sha1);
122
123         lock = lock_any_ref_for_update(ref, NULL, 0);
124         if (!lock)
125                 die("Failed to lock ref for update: %s.", strerror(errno));
126
127         if (reflog)
128                 log_all_ref_updates = 1;
129
130         if (forcing)
131                 snprintf(msg, sizeof msg, "branch: Reset from %s",
132                          start_name);
133         else
134                 snprintf(msg, sizeof msg, "branch: Created from %s",
135                          start_name);
136
137         if (real_ref && track)
138                 setup_tracking(name, real_ref, track);
139
140         if (write_ref_sha1(lock, sha1, msg) < 0)
141                 die("Failed to write ref: %s.", strerror(errno));
142
143         free(real_ref);
144 }
145
146 void remove_branch_state(void)
147 {
148         unlink(git_path("MERGE_HEAD"));
149         unlink(git_path("rr-cache/MERGE_RR"));
150         unlink(git_path("MERGE_MSG"));
151         unlink(git_path("SQUASH_MSG"));
152 }