1#include "cache.h"
2#include "refs.h"
3#include "commit.h"
45
#define CHUNK_SIZE (1048576)
67
static char *get_stdin(void)
8{
9char *data = xmalloc(CHUNK_SIZE);
10int offset = 0, read = 0;
11read = xread(0, data, CHUNK_SIZE);
12while (read == CHUNK_SIZE) {
13offset += CHUNK_SIZE;
14data = xrealloc(data, offset + CHUNK_SIZE);
15read = xread(0, data + offset, CHUNK_SIZE);
16}
17return data;
18}
1920
static void show_new(char *type, unsigned char *sha1_new)
21{
22fprintf(stderr, " %s: %s\n", type,
23find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
24}
2526
static int update_ref(const char *action,
27const char *refname,
28unsigned char *sha1,
29unsigned char *oldval)
30{
31int len;
32char msg[1024];
33char *rla = getenv("GIT_REFLOG_ACTION");
34static struct ref_lock *lock;
3536
if (!rla)
37rla = "(reflog update)";
38len = snprintf(msg, sizeof(msg), "%s: %s", rla, action);
39if (sizeof(msg) <= len)
40die("insanely long action");
41lock = lock_any_ref_for_update(refname, oldval);
42if (!lock)
43return 1;
44if (write_ref_sha1(lock, sha1, msg) < 0)
45return 1;
46return 0;
47}
4849
static int update_local_ref(const char *name,
50const char *new_head,
51const char *note,
52int verbose, int force)
53{
54char type[20];
55unsigned char sha1_old[20], sha1_new[20];
56char oldh[41], newh[41];
57struct commit *current, *updated;
5859
if (get_sha1_hex(new_head, sha1_new))
60die("malformed object name %s", new_head);
61if (sha1_object_info(sha1_new, type, NULL))
62die("object %s not found", new_head);
6364
if (!*name) {
65/* Not storing */
66if (verbose) {
67fprintf(stderr, "* fetched %s\n", note);
68show_new(type, sha1_new);
69}
70return 0;
71}
7273
if (get_sha1(name, sha1_old)) {
74char *msg;
75just_store:
76/* new ref */
77if (!strncmp(name, "refs/tags/", 10))
78msg = "storing tag";
79else
80msg = "storing head";
81fprintf(stderr, "* %s: storing %s\n",
82name, note);
83show_new(type, sha1_new);
84return update_ref(msg, name, sha1_new, NULL);
85}
8687
if (!hashcmp(sha1_old, sha1_new)) {
88if (verbose) {
89fprintf(stderr, "* %s: same as %s\n", name, note);
90show_new(type, sha1_new);
91}
92return 0;
93}
9495
if (!strncmp(name, "refs/tags/", 10)) {
96fprintf(stderr, "* %s: updating with %s\n", name, note);
97show_new(type, sha1_new);
98return update_ref("updating tag", name, sha1_new, NULL);
99}
100101
current = lookup_commit_reference(sha1_old);
102updated = lookup_commit_reference(sha1_new);
103if (!current || !updated)
104goto just_store;
105106
strcpy(oldh, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
107strcpy(newh, find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
108109
if (in_merge_bases(current, &updated, 1)) {
110fprintf(stderr, "* %s: fast forward to %s\n",
111name, note);
112fprintf(stderr, " old..new: %s..%s\n", oldh, newh);
113return update_ref("fast forward", name, sha1_new, sha1_old);
114}
115if (!force) {
116fprintf(stderr,
117"* %s: not updating to non-fast forward %s\n",
118name, note);
119fprintf(stderr,
120" old...new: %s...%s\n", oldh, newh);
121return 1;
122}
123fprintf(stderr,
124"* %s: forcing update to non-fast forward %s\n",
125name, note);
126fprintf(stderr, " old...new: %s...%s\n", oldh, newh);
127return update_ref("forced-update", name, sha1_new, sha1_old);
128}
129130
static int append_fetch_head(FILE *fp,
131const char *head, const char *remote,
132const char *remote_name, const char *remote_nick,
133const char *local_name, int not_for_merge,
134int verbose, int force)
135{
136struct commit *commit;
137int remote_len, i, note_len;
138unsigned char sha1[20];
139char note[1024];
140const char *what, *kind;
141142
if (get_sha1(head, sha1))
143return error("Not a valid object name: %s", head);
144commit = lookup_commit_reference(sha1);
145if (!commit)
146not_for_merge = 1;
147148
if (!strcmp(remote_name, "HEAD")) {
149kind = "";
150what = "";
151}
152else if (!strncmp(remote_name, "refs/heads/", 11)) {
153kind = "branch";
154what = remote_name + 11;
155}
156else if (!strncmp(remote_name, "refs/tags/", 10)) {
157kind = "tag";
158what = remote_name + 10;
159}
160else if (!strncmp(remote_name, "refs/remotes/", 13)) {
161kind = "remote branch";
162what = remote_name + 13;
163}
164else {
165kind = "";
166what = remote_name;
167}
168169
remote_len = strlen(remote);
170for (i = remote_len - 1; remote[i] == '/' && 0 <= i; i--)
171;
172remote_len = i + 1;
173if (4 < i && !strncmp(".git", remote + i - 3, 4))
174remote_len = i - 3;
175note_len = sprintf(note, "%s\t%s\t",
176sha1_to_hex(commit ? commit->object.sha1 : sha1),
177not_for_merge ? "not-for-merge" : "");
178if (*what) {
179if (*kind)
180note_len += sprintf(note + note_len, "%s ", kind);
181note_len += sprintf(note + note_len, "'%s' of ", what);
182}
183note_len += sprintf(note + note_len, "%.*s", remote_len, remote);
184fprintf(fp, "%s\n", note);
185return update_local_ref(local_name, head, note, verbose, force);
186}
187188
static char *keep;
189static void remove_keep(void)
190{
191if (keep && *keep)
192unlink(keep);
193}
194195
static void remove_keep_on_signal(int signo)
196{
197remove_keep();
198signal(SIGINT, SIG_DFL);
199raise(signo);
200}
201202
static char *find_local_name(const char *remote_name, const char *refs,
203int *force_p, int *not_for_merge_p)
204{
205const char *ref = refs;
206int len = strlen(remote_name);
207208
while (ref) {
209const char *next;
210int single_force, not_for_merge;
211212
while (*ref == '\n')
213ref++;
214if (!*ref)
215break;
216next = strchr(ref, '\n');
217218
single_force = not_for_merge = 0;
219if (*ref == '+') {
220single_force = 1;
221ref++;
222}
223if (*ref == '.') {
224not_for_merge = 1;
225ref++;
226if (*ref == '+') {
227single_force = 1;
228ref++;
229}
230}
231if (!strncmp(remote_name, ref, len) && ref[len] == ':') {
232const char *local_part = ref + len + 1;
233char *ret;
234int retlen;
235236
if (!next)
237retlen = strlen(local_part);
238else
239retlen = next - local_part;
240ret = xmalloc(retlen + 1);
241memcpy(ret, local_part, retlen);
242ret[retlen] = 0;
243*force_p = single_force;
244*not_for_merge_p = not_for_merge;
245return ret;
246}
247ref = next;
248}
249return NULL;
250}
251252
static int fetch_native_store(FILE *fp,
253const char *remote,
254const char *remote_nick,
255const char *refs,
256int verbose, int force)
257{
258char buffer[1024];
259int err = 0;
260261
signal(SIGINT, remove_keep_on_signal);
262atexit(remove_keep);
263264
while (fgets(buffer, sizeof(buffer), stdin)) {
265int len;
266char *cp;
267char *local_name;
268int single_force, not_for_merge;
269270
for (cp = buffer; *cp && !isspace(*cp); cp++)
271;
272if (*cp)
273*cp++ = 0;
274len = strlen(cp);
275if (len && cp[len-1] == '\n')
276cp[--len] = 0;
277if (!strcmp(buffer, "failed"))
278die("Fetch failure: %s", remote);
279if (!strcmp(buffer, "pack"))
280continue;
281if (!strcmp(buffer, "keep")) {
282char *od = get_object_directory();
283int len = strlen(od) + strlen(cp) + 50;
284keep = xmalloc(len);
285sprintf(keep, "%s/pack/pack-%s.keep", od, cp);
286continue;
287}
288289
local_name = find_local_name(cp, refs,
290&single_force, ¬_for_merge);
291if (!local_name)
292continue;
293err |= append_fetch_head(fp,
294buffer, remote, cp, remote_nick,
295local_name, not_for_merge,
296verbose, force || single_force);
297}
298return err;
299}
300301
static int parse_reflist(const char *reflist)
302{
303const char *ref;
304305
printf("refs='");
306for (ref = reflist; ref; ) {
307const char *next;
308while (*ref && isspace(*ref))
309ref++;
310if (!*ref)
311break;
312for (next = ref; *next && !isspace(*next); next++)
313;
314printf("\n%.*s", (int)(next - ref), ref);
315ref = next;
316}
317printf("'\n");
318319
printf("rref='");
320for (ref = reflist; ref; ) {
321const char *next, *colon;
322while (*ref && isspace(*ref))
323ref++;
324if (!*ref)
325break;
326for (next = ref; *next && !isspace(*next); next++)
327;
328if (*ref == '.')
329ref++;
330if (*ref == '+')
331ref++;
332colon = strchr(ref, ':');
333putchar('\n');
334printf("%.*s", (int)((colon ? colon : next) - ref), ref);
335ref = next;
336}
337printf("'\n");
338return 0;
339}
340341
static int expand_refs_wildcard(const char *ls_remote_result, int numrefs,
342const char **refs)
343{
344int i, matchlen, replacelen;
345int found_one = 0;
346const char *remote = *refs++;
347numrefs--;
348349
if (numrefs == 0) {
350fprintf(stderr, "Nothing specified for fetching with remote.%s.fetch\n",
351remote);
352printf("empty\n");
353}
354355
for (i = 0; i < numrefs; i++) {
356const char *ref = refs[i];
357const char *lref = ref;
358const char *colon;
359const char *tail;
360const char *ls;
361const char *next;
362363
if (*lref == '+')
364lref++;
365colon = strchr(lref, ':');
366tail = lref + strlen(lref);
367if (!(colon &&
3682 < colon - lref &&
369colon[-1] == '*' &&
370colon[-2] == '/' &&
3712 < tail - (colon + 1) &&
372tail[-1] == '*' &&
373tail[-2] == '/')) {
374/* not a glob */
375if (!found_one++)
376printf("explicit\n");
377printf("%s\n", ref);
378continue;
379}
380381
/* glob */
382if (!found_one++)
383printf("glob\n");
384385
/* lref to colon-2 is remote hierarchy name;
386* colon+1 to tail-2 is local.
387*/
388matchlen = (colon-1) - lref;
389replacelen = (tail-1) - (colon+1);
390for (ls = ls_remote_result; ls; ls = next) {
391const char *eol;
392unsigned char sha1[20];
393int namelen;
394395
while (*ls && isspace(*ls))
396ls++;
397next = strchr(ls, '\n');
398eol = !next ? (ls + strlen(ls)) : next;
399if (!memcmp("^{}", eol-3, 3))
400continue;
401if (get_sha1_hex(ls, sha1))
402continue;
403ls += 40;
404while (ls < eol && isspace(*ls))
405ls++;
406/* ls to next (or eol) is the name.
407* is it identical to lref to colon-2?
408*/
409if ((eol - ls) <= matchlen ||
410strncmp(ls, lref, matchlen))
411continue;
412413
/* Yes, it is a match */
414namelen = eol - ls;
415if (lref != ref)
416putchar('+');
417printf("%.*s:%.*s%.*s\n",
418namelen, ls,
419replacelen, colon + 1,
420namelen - matchlen, ls + matchlen);
421}
422}
423return 0;
424}
425426
int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
427{
428int verbose = 0;
429int force = 0;
430431
while (1 < argc) {
432const char *arg = argv[1];
433if (!strcmp("-v", arg))
434verbose = 1;
435else if (!strcmp("-f", arg))
436force = 1;
437else
438break;
439argc--;
440argv++;
441}
442443
if (argc <= 1)
444return error("Missing subcommand");
445446
if (!strcmp("append-fetch-head", argv[1])) {
447int result;
448FILE *fp;
449450
if (argc != 8)
451return error("append-fetch-head takes 6 args");
452fp = fopen(git_path("FETCH_HEAD"), "a");
453result = append_fetch_head(fp, argv[2], argv[3],
454argv[4], argv[5],
455argv[6], !!argv[7][0],
456verbose, force);
457fclose(fp);
458return result;
459}
460if (!strcmp("update-local-ref", argv[1])) {
461if (argc != 5)
462return error("update-local-ref takes 3 args");
463return update_local_ref(argv[2], argv[3], argv[4],
464verbose, force);
465}
466if (!strcmp("native-store", argv[1])) {
467int result;
468FILE *fp;
469470
if (argc != 5)
471return error("fetch-native-store takes 3 args");
472fp = fopen(git_path("FETCH_HEAD"), "a");
473result = fetch_native_store(fp, argv[2], argv[3], argv[4],
474verbose, force);
475fclose(fp);
476return result;
477}
478if (!strcmp("parse-reflist", argv[1])) {
479const char *reflist;
480if (argc != 3)
481return error("parse-reflist takes 1 arg");
482reflist = argv[2];
483if (!strcmp(reflist, "-"))
484reflist = get_stdin();
485return parse_reflist(reflist);
486}
487if (!strcmp("expand-refs-wildcard", argv[1])) {
488const char *reflist;
489if (argc < 4)
490return error("expand-refs-wildcard takes at least 2 args");
491reflist = argv[2];
492if (!strcmp(reflist, "-"))
493reflist = get_stdin();
494return expand_refs_wildcard(reflist, argc - 3, argv + 3);
495}
496497
return error("Unknown subcommand: %s", argv[1]);
498}