]> git.ipfire.org Git - thirdparty/git.git/blame - builtin/fast-export.c
Merge branch 'jk/always-allow-large-packets'
[thirdparty/git.git] / builtin / fast-export.c
CommitLineData
f2dc849e
JS
1/*
2 * "git fast-export" builtin command
3 *
4 * Copyright (C) 2007 Johannes E. Schindelin
5 */
6#include "builtin.h"
7#include "cache.h"
8#include "commit.h"
9#include "object.h"
10#include "tag.h"
11#include "diff.h"
12#include "diffcore.h"
13#include "log-tree.h"
14#include "revision.h"
15#include "decorate.h"
c455c87c 16#include "string-list.h"
f2dc849e
JS
17#include "utf8.h"
18#include "parse-options.h"
6280dfdc 19#include "quote.h"
03e9010c 20#include "remote.h"
a8722750 21#include "blob.h"
f2dc849e
JS
22
23static const char *fast_export_usage[] = {
3b787b96 24 N_("git fast-export [rev-list-opts]"),
f2dc849e
JS
25 NULL
26};
27
28static int progress;
cd16c59b 29static enum { ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = ABORT;
d7a10c31 30static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ERROR;
4e46a8d6 31static int fake_missing_tagger;
82670a5c 32static int use_done_feature;
79559f27 33static int no_data;
7f40ab09 34static int full_tree;
1d844ee7 35static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
03e9010c
FC
36static struct refspec *refspecs;
37static int refspecs_nr;
a8722750 38static int anonymize;
f2dc849e
JS
39
40static int parse_opt_signed_tag_mode(const struct option *opt,
41 const char *arg, int unset)
42{
43 if (unset || !strcmp(arg, "abort"))
44 signed_tag_mode = ABORT;
ee4bc371
JS
45 else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore"))
46 signed_tag_mode = VERBATIM;
f2dc849e
JS
47 else if (!strcmp(arg, "warn"))
48 signed_tag_mode = WARN;
cd16c59b
JK
49 else if (!strcmp(arg, "warn-strip"))
50 signed_tag_mode = WARN_STRIP;
f2dc849e
JS
51 else if (!strcmp(arg, "strip"))
52 signed_tag_mode = STRIP;
53 else
04a74b6c 54 return error("Unknown signed-tags mode: %s", arg);
f2dc849e
JS
55 return 0;
56}
57
2d8ad469
EN
58static int parse_opt_tag_of_filtered_mode(const struct option *opt,
59 const char *arg, int unset)
60{
61 if (unset || !strcmp(arg, "abort"))
d7a10c31 62 tag_of_filtered_mode = ERROR;
2d8ad469
EN
63 else if (!strcmp(arg, "drop"))
64 tag_of_filtered_mode = DROP;
65 else if (!strcmp(arg, "rewrite"))
66 tag_of_filtered_mode = REWRITE;
67 else
68 return error("Unknown tag-of-filtered mode: %s", arg);
69 return 0;
70}
71
f2dc849e
JS
72static struct decoration idnums;
73static uint32_t last_idnum;
74
75static int has_unshown_parent(struct commit *commit)
76{
77 struct commit_list *parent;
78
79 for (parent = commit->parents; parent; parent = parent->next)
80 if (!(parent->item->object.flags & SHOWN) &&
81 !(parent->item->object.flags & UNINTERESTING))
82 return 1;
83 return 0;
84}
85
a8722750
JK
86struct anonymized_entry {
87 struct hashmap_entry hash;
88 const char *orig;
89 size_t orig_len;
90 const char *anon;
91 size_t anon_len;
92};
93
94static int anonymized_entry_cmp(const void *va, const void *vb,
95 const void *data)
96{
97 const struct anonymized_entry *a = va, *b = vb;
98 return a->orig_len != b->orig_len ||
99 memcmp(a->orig, b->orig, a->orig_len);
100}
101
102/*
103 * Basically keep a cache of X->Y so that we can repeatedly replace
104 * the same anonymized string with another. The actual generation
105 * is farmed out to the generate function.
106 */
107static const void *anonymize_mem(struct hashmap *map,
108 void *(*generate)(const void *, size_t *),
109 const void *orig, size_t *len)
110{
111 struct anonymized_entry key, *ret;
112
113 if (!map->cmpfn)
114 hashmap_init(map, anonymized_entry_cmp, 0);
115
116 hashmap_entry_init(&key, memhash(orig, *len));
117 key.orig = orig;
118 key.orig_len = *len;
119 ret = hashmap_get(map, &key, NULL);
120
121 if (!ret) {
122 ret = xmalloc(sizeof(*ret));
123 hashmap_entry_init(&ret->hash, key.hash.hash);
124 ret->orig = xstrdup(orig);
125 ret->orig_len = *len;
126 ret->anon = generate(orig, len);
127 ret->anon_len = *len;
128 hashmap_put(map, ret);
129 }
130
131 *len = ret->anon_len;
132 return ret->anon;
133}
134
135/*
136 * We anonymize each component of a path individually,
137 * so that paths a/b and a/c will share a common root.
138 * The paths are cached via anonymize_mem so that repeated
139 * lookups for "a" will yield the same value.
140 */
141static void anonymize_path(struct strbuf *out, const char *path,
142 struct hashmap *map,
143 void *(*generate)(const void *, size_t *))
144{
145 while (*path) {
146 const char *end_of_component = strchrnul(path, '/');
147 size_t len = end_of_component - path;
148 const char *c = anonymize_mem(map, generate, path, &len);
149 strbuf_add(out, c, len);
150 path = end_of_component;
151 if (*path)
152 strbuf_addch(out, *path++);
153 }
154}
155
f2dc849e 156/* Since intptr_t is C99, we do not use it here */
df6a7ff7 157static inline uint32_t *mark_to_ptr(uint32_t mark)
f2dc849e 158{
df6a7ff7
PB
159 return ((uint32_t *)NULL) + mark;
160}
161
162static inline uint32_t ptr_to_mark(void * mark)
163{
164 return (uint32_t *)mark - (uint32_t *)NULL;
165}
166
167static inline void mark_object(struct object *object, uint32_t mark)
168{
169 add_decoration(&idnums, object, mark_to_ptr(mark));
170}
171
172static inline void mark_next_object(struct object *object)
173{
174 mark_object(object, ++last_idnum);
f2dc849e
JS
175}
176
177static int get_object_mark(struct object *object)
178{
179 void *decoration = lookup_decoration(&idnums, object);
180 if (!decoration)
181 return 0;
df6a7ff7 182 return ptr_to_mark(decoration);
f2dc849e
JS
183}
184
185static void show_progress(void)
186{
187 static int counter = 0;
188 if (!progress)
189 return;
190 if ((++counter % progress) == 0)
191 printf("progress %d objects\n", counter);
192}
193
a8722750
JK
194/*
195 * Ideally we would want some transformation of the blob data here
196 * that is unreversible, but would still be the same size and have
197 * the same data relationship to other blobs (so that we get the same
198 * delta and packing behavior as the original). But the first and last
199 * requirements there are probably mutually exclusive, so let's take
200 * the easy way out for now, and just generate arbitrary content.
201 *
202 * There's no need to cache this result with anonymize_mem, since
203 * we already handle blob content caching with marks.
204 */
205static char *anonymize_blob(unsigned long *size)
206{
207 static int counter;
208 struct strbuf out = STRBUF_INIT;
209 strbuf_addf(&out, "anonymous blob %d", counter++);
210 *size = out.len;
211 return strbuf_detach(&out, NULL);
212}
213
f9b54e26 214static void export_blob(const unsigned char *sha1)
f2dc849e
JS
215{
216 unsigned long size;
217 enum object_type type;
218 char *buf;
219 struct object *object;
30b939c3 220 int eaten;
f2dc849e 221
79559f27
GI
222 if (no_data)
223 return;
224
f2dc849e
JS
225 if (is_null_sha1(sha1))
226 return;
227
30b939c3
JK
228 object = lookup_object(sha1);
229 if (object && object->flags & SHOWN)
f2dc849e
JS
230 return;
231
a8722750
JK
232 if (anonymize) {
233 buf = anonymize_blob(&size);
234 object = (struct object *)lookup_blob(sha1);
235 eaten = 0;
236 } else {
237 buf = read_sha1_file(sha1, &type, &size);
238 if (!buf)
239 die ("Could not read blob %s", sha1_to_hex(sha1));
240 if (check_sha1_signature(sha1, buf, size, typename(type)) < 0)
241 die("sha1 mismatch in blob %s", sha1_to_hex(sha1));
242 object = parse_object_buffer(sha1, type, size, buf, &eaten);
243 }
244
30b939c3
JK
245 if (!object)
246 die("Could not read blob %s", sha1_to_hex(sha1));
f2dc849e 247
df6a7ff7 248 mark_next_object(object);
f2dc849e 249
6e1c2344 250 printf("blob\nmark :%"PRIu32"\ndata %lu\n", last_idnum, size);
b0fe0d72 251 if (size && fwrite(buf, size, 1, stdout) != 1)
0721c314 252 die_errno ("Could not write blob '%s'", sha1_to_hex(sha1));
f2dc849e
JS
253 printf("\n");
254
255 show_progress();
256
257 object->flags |= SHOWN;
30b939c3
JK
258 if (!eaten)
259 free(buf);
f2dc849e
JS
260}
261
060df624
EN
262static int depth_first(const void *a_, const void *b_)
263{
264 const struct diff_filepair *a = *((const struct diff_filepair **)a_);
265 const struct diff_filepair *b = *((const struct diff_filepair **)b_);
266 const char *name_a, *name_b;
267 int len_a, len_b, len;
268 int cmp;
269
270 name_a = a->one ? a->one->path : a->two->path;
271 name_b = b->one ? b->one->path : b->two->path;
272
273 len_a = strlen(name_a);
274 len_b = strlen(name_b);
275 len = (len_a < len_b) ? len_a : len_b;
276
277 /* strcmp will sort 'd' before 'd/e', we want 'd/e' before 'd' */
278 cmp = memcmp(name_a, name_b, len);
279 if (cmp)
280 return cmp;
4ce6fb80
JS
281 cmp = len_b - len_a;
282 if (cmp)
283 return cmp;
284 /*
285 * Move 'R'ename entries last so that all references of the file
286 * appear in the output before it is renamed (e.g., when a file
287 * was copied and renamed in the same commit).
288 */
289 return (a->status == 'R') - (b->status == 'R');
060df624
EN
290}
291
a8722750 292static void print_path_1(const char *path)
6280dfdc
JK
293{
294 int need_quote = quote_c_style(path, NULL, NULL, 0);
295 if (need_quote)
296 quote_c_style(path, NULL, stdout, 0);
ff59f6da
JS
297 else if (strchr(path, ' '))
298 printf("\"%s\"", path);
6280dfdc
JK
299 else
300 printf("%s", path);
301}
302
a8722750
JK
303static void *anonymize_path_component(const void *path, size_t *len)
304{
305 static int counter;
306 struct strbuf out = STRBUF_INIT;
307 strbuf_addf(&out, "path%d", counter++);
308 return strbuf_detach(&out, len);
309}
310
311static void print_path(const char *path)
312{
313 if (!anonymize)
314 print_path_1(path);
315 else {
316 static struct hashmap paths;
317 static struct strbuf anon = STRBUF_INIT;
318
319 anonymize_path(&anon, path, &paths, anonymize_path_component);
320 print_path_1(anon.buf);
321 strbuf_reset(&anon);
322 }
323}
324
325static void *generate_fake_sha1(const void *old, size_t *len)
326{
327 static uint32_t counter = 1; /* avoid null sha1 */
328 unsigned char *out = xcalloc(20, 1);
329 put_be32(out + 16, counter++);
330 return out;
331}
332
333static const unsigned char *anonymize_sha1(const unsigned char *sha1)
334{
335 static struct hashmap sha1s;
336 size_t len = 20;
337 return anonymize_mem(&sha1s, generate_fake_sha1, sha1, &len);
338}
339
f2dc849e
JS
340static void show_filemodify(struct diff_queue_struct *q,
341 struct diff_options *options, void *data)
342{
343 int i;
060df624
EN
344
345 /*
346 * Handle files below a directory first, in case they are all deleted
347 * and the directory changes to a file or symlink.
348 */
349 qsort(q->queue, q->nr, sizeof(q->queue[0]), depth_first);
350
f2dc849e 351 for (i = 0; i < q->nr; i++) {
ae7c5dce 352 struct diff_filespec *ospec = q->queue[i]->one;
f2dc849e 353 struct diff_filespec *spec = q->queue[i]->two;
ae7c5dce
AG
354
355 switch (q->queue[i]->status) {
356 case DIFF_STATUS_DELETED:
6280dfdc
JK
357 printf("D ");
358 print_path(spec->path);
359 putchar('\n');
ae7c5dce
AG
360 break;
361
362 case DIFF_STATUS_COPIED:
363 case DIFF_STATUS_RENAMED:
6280dfdc
JK
364 printf("%c ", q->queue[i]->status);
365 print_path(ospec->path);
366 putchar(' ');
367 print_path(spec->path);
368 putchar('\n');
ae7c5dce
AG
369
370 if (!hashcmp(ospec->sha1, spec->sha1) &&
371 ospec->mode == spec->mode)
372 break;
373 /* fallthrough */
374
375 case DIFF_STATUS_TYPE_CHANGED:
376 case DIFF_STATUS_MODIFIED:
377 case DIFF_STATUS_ADDED:
03db4525
AG
378 /*
379 * Links refer to objects in another repositories;
380 * output the SHA-1 verbatim.
381 */
79559f27 382 if (no_data || S_ISGITLINK(spec->mode))
6280dfdc 383 printf("M %06o %s ", spec->mode,
a8722750
JK
384 sha1_to_hex(anonymize ?
385 anonymize_sha1(spec->sha1) :
386 spec->sha1));
03db4525
AG
387 else {
388 struct object *object = lookup_object(spec->sha1);
6280dfdc
JK
389 printf("M %06o :%d ", spec->mode,
390 get_object_mark(object));
03db4525 391 }
6280dfdc
JK
392 print_path(spec->path);
393 putchar('\n');
ae7c5dce
AG
394 break;
395
396 default:
397 die("Unexpected comparison status '%c' for %s, %s",
398 q->queue[i]->status,
399 ospec->path ? ospec->path : "none",
400 spec->path ? spec->path : "none");
f2dc849e
JS
401 }
402 }
403}
404
405static const char *find_encoding(const char *begin, const char *end)
406{
407 const char *needle = "\nencoding ";
408 char *bol, *eol;
409
410 bol = memmem(begin, end ? end - begin : strlen(begin),
411 needle, strlen(needle));
412 if (!bol)
413 return git_commit_encoding;
414 bol += strlen(needle);
415 eol = strchrnul(bol, '\n');
416 *eol = '\0';
417 return bol;
418}
419
a8722750
JK
420static void *anonymize_ref_component(const void *old, size_t *len)
421{
422 static int counter;
423 struct strbuf out = STRBUF_INIT;
424 strbuf_addf(&out, "ref%d", counter++);
425 return strbuf_detach(&out, len);
426}
427
428static const char *anonymize_refname(const char *refname)
429{
430 /*
431 * If any of these prefixes is found, we will leave it intact
432 * so that tags remain tags and so forth.
433 */
434 static const char *prefixes[] = {
435 "refs/heads/",
436 "refs/tags/",
437 "refs/remotes/",
438 "refs/"
439 };
440 static struct hashmap refs;
441 static struct strbuf anon = STRBUF_INIT;
442 int i;
443
444 /*
445 * We also leave "master" as a special case, since it does not reveal
446 * anything interesting.
447 */
448 if (!strcmp(refname, "refs/heads/master"))
449 return refname;
450
451 strbuf_reset(&anon);
452 for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
453 if (skip_prefix(refname, prefixes[i], &refname)) {
454 strbuf_addstr(&anon, prefixes[i]);
455 break;
456 }
457 }
458
459 anonymize_path(&anon, refname, &refs, anonymize_ref_component);
460 return anon.buf;
461}
462
463/*
464 * We do not even bother to cache commit messages, as they are unlikely
465 * to be repeated verbatim, and it is not that interesting when they are.
466 */
467static char *anonymize_commit_message(const char *old)
468{
469 static int counter;
470 return xstrfmt("subject %d\n\nbody\n", counter++);
471}
472
473static struct hashmap idents;
474static void *anonymize_ident(const void *old, size_t *len)
475{
476 static int counter;
477 struct strbuf out = STRBUF_INIT;
478 strbuf_addf(&out, "User %d <user%d@example.com>", counter, counter);
479 counter++;
480 return strbuf_detach(&out, len);
481}
482
483/*
484 * Our strategy here is to anonymize the names and email addresses,
485 * but keep timestamps intact, as they influence things like traversal
486 * order (and by themselves should not be too revealing).
487 */
488static void anonymize_ident_line(const char **beg, const char **end)
489{
490 static struct strbuf buffers[] = { STRBUF_INIT, STRBUF_INIT };
491 static unsigned which_buffer;
492
493 struct strbuf *out;
494 struct ident_split split;
495 const char *end_of_header;
496
497 out = &buffers[which_buffer++];
498 which_buffer %= ARRAY_SIZE(buffers);
499 strbuf_reset(out);
500
501 /* skip "committer", "author", "tagger", etc */
502 end_of_header = strchr(*beg, ' ');
503 if (!end_of_header)
504 die("BUG: malformed line fed to anonymize_ident_line: %.*s",
505 (int)(*end - *beg), *beg);
506 end_of_header++;
507 strbuf_add(out, *beg, end_of_header - *beg);
508
509 if (!split_ident_line(&split, end_of_header, *end - end_of_header) &&
510 split.date_begin) {
511 const char *ident;
512 size_t len;
513
514 len = split.mail_end - split.name_begin;
515 ident = anonymize_mem(&idents, anonymize_ident,
516 split.name_begin, &len);
517 strbuf_add(out, ident, len);
518 strbuf_addch(out, ' ');
519 strbuf_add(out, split.date_begin, split.tz_end - split.date_begin);
520 } else {
521 strbuf_addstr(out, "Malformed Ident <malformed@example.com> 0 -0000");
522 }
523
524 *beg = out->buf;
525 *end = out->buf + out->len;
526}
527
f2dc849e
JS
528static void handle_commit(struct commit *commit, struct rev_info *rev)
529{
530 int saved_output_format = rev->diffopt.output_format;
bc6b8fc1 531 const char *commit_buffer;
f2dc849e
JS
532 const char *author, *author_end, *committer, *committer_end;
533 const char *encoding, *message;
534 char *reencoded = NULL;
535 struct commit_list *p;
a8722750 536 const char *refname;
f2dc849e
JS
537 int i;
538
539 rev->diffopt.output_format = DIFF_FORMAT_CALLBACK;
540
683ff884 541 parse_commit_or_die(commit);
8597ea3a 542 commit_buffer = get_commit_buffer(commit, NULL);
bc6b8fc1 543 author = strstr(commit_buffer, "\nauthor ");
f2dc849e
JS
544 if (!author)
545 die ("Could not find author in commit %s",
546 sha1_to_hex(commit->object.sha1));
547 author++;
548 author_end = strchrnul(author, '\n');
549 committer = strstr(author_end, "\ncommitter ");
550 if (!committer)
551 die ("Could not find committer in commit %s",
552 sha1_to_hex(commit->object.sha1));
553 committer++;
554 committer_end = strchrnul(committer, '\n');
555 message = strstr(committer_end, "\n\n");
556 encoding = find_encoding(committer_end, message);
557 if (message)
558 message += 2;
559
ebeec7db 560 if (commit->parents &&
4087a02e
EN
561 get_object_mark(&commit->parents->item->object) != 0 &&
562 !full_tree) {
683ff884 563 parse_commit_or_die(commit->parents->item);
f2dc849e
JS
564 diff_tree_sha1(commit->parents->item->tree->object.sha1,
565 commit->tree->object.sha1, "", &rev->diffopt);
566 }
567 else
568 diff_root_tree_sha1(commit->tree->object.sha1,
569 "", &rev->diffopt);
570
03db4525 571 /* Export the referenced blobs, and remember the marks. */
f2dc849e 572 for (i = 0; i < diff_queued_diff.nr; i++)
03db4525 573 if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
f9b54e26 574 export_blob(diff_queued_diff.queue[i]->two->sha1);
f2dc849e 575
a8722750
JK
576 refname = commit->util;
577 if (anonymize) {
578 refname = anonymize_refname(refname);
579 anonymize_ident_line(&committer, &committer_end);
580 anonymize_ident_line(&author, &author_end);
581 }
582
df6a7ff7 583 mark_next_object(&commit->object);
a8722750
JK
584 if (anonymize)
585 reencoded = anonymize_commit_message(message);
586 else if (!is_encoding_utf8(encoding))
f2dc849e 587 reencoded = reencode_string(message, "UTF-8", encoding);
d8933f01 588 if (!commit->parents)
a8722750 589 printf("reset %s\n", refname);
6e1c2344 590 printf("commit %s\nmark :%"PRIu32"\n%.*s\n%.*s\ndata %u\n%s",
a8722750 591 refname, last_idnum,
f2dc849e
JS
592 (int)(author_end - author), author,
593 (int)(committer_end - committer), committer,
594 (unsigned)(reencoded
595 ? strlen(reencoded) : message
596 ? strlen(message) : 0),
597 reencoded ? reencoded : message ? message : "");
8e0f7003 598 free(reencoded);
bc6b8fc1 599 unuse_commit_buffer(commit, commit_buffer);
f2dc849e
JS
600
601 for (i = 0, p = commit->parents; p; p = p->next) {
602 int mark = get_object_mark(&p->item->object);
603 if (!mark)
604 continue;
605 if (i == 0)
606 printf("from :%d\n", mark);
f2dc849e 607 else
5070b49e 608 printf("merge :%d\n", mark);
f2dc849e
JS
609 i++;
610 }
f2dc849e 611
4087a02e
EN
612 if (full_tree)
613 printf("deleteall\n");
f2dc849e
JS
614 log_tree_diff_flush(rev);
615 rev->diffopt.output_format = saved_output_format;
616
617 printf("\n");
618
619 show_progress();
620}
621
a8722750
JK
622static void *anonymize_tag(const void *old, size_t *len)
623{
624 static int counter;
625 struct strbuf out = STRBUF_INIT;
626 strbuf_addf(&out, "tag message %d", counter++);
627 return strbuf_detach(&out, len);
628}
629
f2dc849e
JS
630static void handle_tail(struct object_array *commits, struct rev_info *revs)
631{
632 struct commit *commit;
633 while (commits->nr) {
634 commit = (struct commit *)commits->objects[commits->nr - 1].item;
635 if (has_unshown_parent(commit))
636 return;
637 handle_commit(commit, revs);
638 commits->nr--;
639 }
640}
641
642static void handle_tag(const char *name, struct tag *tag)
643{
644 unsigned long size;
645 enum object_type type;
646 char *buf;
647 const char *tagger, *tagger_end, *message;
648 size_t message_size = 0;
02c48cd6 649 struct object *tagged;
2d8ad469
EN
650 int tagged_mark;
651 struct commit *p;
02c48cd6 652
98e023de 653 /* Trees have no identifier in fast-export output, thus we have no way
02c48cd6
EN
654 * to output tags of trees, tags of tags of trees, etc. Simply omit
655 * such tags.
656 */
657 tagged = tag->tagged;
658 while (tagged->type == OBJ_TAG) {
659 tagged = ((struct tag *)tagged)->tagged;
660 }
661 if (tagged->type == OBJ_TREE) {
662 warning("Omitting tag %s,\nsince tags of trees (or tags of tags of trees, etc.) are not supported.",
663 sha1_to_hex(tag->object.sha1));
664 return;
665 }
f2dc849e
JS
666
667 buf = read_sha1_file(tag->object.sha1, &type, &size);
668 if (!buf)
669 die ("Could not read tag %s", sha1_to_hex(tag->object.sha1));
670 message = memmem(buf, size, "\n\n", 2);
671 if (message) {
672 message += 2;
673 message_size = strlen(message);
674 }
675 tagger = memmem(buf, message ? message - buf : size, "\ntagger ", 8);
4e46a8d6
JS
676 if (!tagger) {
677 if (fake_missing_tagger)
678 tagger = "tagger Unspecified Tagger "
679 "<unspecified-tagger> 0 +0000";
680 else
681 tagger = "";
682 tagger_end = tagger + strlen(tagger);
683 } else {
684 tagger++;
685 tagger_end = strchrnul(tagger, '\n');
a8722750
JK
686 if (anonymize)
687 anonymize_ident_line(&tagger, &tagger_end);
688 }
689
690 if (anonymize) {
691 name = anonymize_refname(name);
692 if (message) {
693 static struct hashmap tags;
694 message = anonymize_mem(&tags, anonymize_tag,
695 message, &message_size);
696 }
4e46a8d6 697 }
f2dc849e
JS
698
699 /* handle signed tags */
700 if (message) {
701 const char *signature = strstr(message,
702 "\n-----BEGIN PGP SIGNATURE-----\n");
703 if (signature)
704 switch(signed_tag_mode) {
705 case ABORT:
706 die ("Encountered signed tag %s; use "
04a74b6c 707 "--signed-tags=<mode> to handle it.",
f2dc849e
JS
708 sha1_to_hex(tag->object.sha1));
709 case WARN:
710 warning ("Exporting signed tag %s",
711 sha1_to_hex(tag->object.sha1));
712 /* fallthru */
ee4bc371 713 case VERBATIM:
f2dc849e 714 break;
cd16c59b
JK
715 case WARN_STRIP:
716 warning ("Stripping signature from tag %s",
717 sha1_to_hex(tag->object.sha1));
718 /* fallthru */
f2dc849e
JS
719 case STRIP:
720 message_size = signature + 1 - message;
721 break;
722 }
723 }
724
2d8ad469
EN
725 /* handle tag->tagged having been filtered out due to paths specified */
726 tagged = tag->tagged;
727 tagged_mark = get_object_mark(tagged);
728 if (!tagged_mark) {
729 switch(tag_of_filtered_mode) {
730 case ABORT:
731 die ("Tag %s tags unexported object; use "
732 "--tag-of-filtered-object=<mode> to handle it.",
733 sha1_to_hex(tag->object.sha1));
734 case DROP:
735 /* Ignore this tag altogether */
736 return;
737 case REWRITE:
738 if (tagged->type != OBJ_COMMIT) {
739 die ("Tag %s tags unexported %s!",
740 sha1_to_hex(tag->object.sha1),
741 typename(tagged->type));
742 }
743 p = (struct commit *)tagged;
744 for (;;) {
745 if (p->parents && p->parents->next)
746 break;
747 if (p->object.flags & UNINTERESTING)
748 break;
749 if (!(p->object.flags & TREESAME))
750 break;
751 if (!p->parents)
752 die ("Can't find replacement commit for tag %s\n",
753 sha1_to_hex(tag->object.sha1));
754 p = p->parents->item;
755 }
756 tagged_mark = get_object_mark(&p->object);
757 }
758 }
759
59556548 760 if (starts_with(name, "refs/tags/"))
f2dc849e 761 name += 10;
4e46a8d6 762 printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
2d8ad469 763 name, tagged_mark,
f2dc849e 764 (int)(tagger_end - tagger), tagger,
4e46a8d6 765 tagger == tagger_end ? "" : "\n",
f2dc849e
JS
766 (int)message_size, (int)message_size, message ? message : "");
767}
768
3e9b9cb1
FC
769static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)
770{
771 switch (e->item->type) {
772 case OBJ_COMMIT:
773 return (struct commit *)e->item;
774 case OBJ_TAG: {
775 struct tag *tag = (struct tag *)e->item;
776
777 /* handle nested tags */
778 while (tag && tag->object.type == OBJ_TAG) {
779 parse_object(tag->object.sha1);
780 string_list_append(&extra_refs, full_name)->util = tag;
781 tag = (struct tag *)tag->tagged;
782 }
783 if (!tag)
784 die("Tag %s points nowhere?", e->name);
785 return (struct commit *)tag;
786 break;
787 }
788 default:
789 return NULL;
790 }
791}
792
1d844ee7 793static void get_tags_and_duplicates(struct rev_cmdline_info *info)
f2dc849e 794{
f2dc849e
JS
795 int i;
796
49266e8a
FC
797 for (i = 0; i < info->nr; i++) {
798 struct rev_cmdline_entry *e = info->rev + i;
f2dc849e 799 unsigned char sha1[20];
2d242de4 800 struct commit *commit;
f2dc849e
JS
801 char *full_name;
802
49266e8a
FC
803 if (e->flags & UNINTERESTING)
804 continue;
805
f2dc849e
JS
806 if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1)
807 continue;
808
03e9010c
FC
809 if (refspecs) {
810 char *private;
811 private = apply_refspecs(refspecs, refspecs_nr, full_name);
812 if (private) {
813 free(full_name);
814 full_name = private;
815 }
816 }
817
3e9b9cb1
FC
818 commit = get_commit(e, full_name);
819 if (!commit) {
2d07f6d4
EFL
820 warning("%s: Unexpected object of type %s, skipping.",
821 e->name,
822 typename(e->item->type));
823 continue;
f2dc849e 824 }
f28e7c90 825
3e9b9cb1
FC
826 switch(commit->object.type) {
827 case OBJ_COMMIT:
828 break;
829 case OBJ_BLOB:
830 export_blob(commit->object.sha1);
831 continue;
832 default: /* OBJ_TAG (nested tags) is already handled */
833 warning("Tag points to object of unexpected type %s, skipping.",
834 typename(commit->object.type));
835 continue;
836 }
837
f28e7c90
FC
838 /*
839 * This ref will not be updated through a commit, lets make
840 * sure it gets properly updated eventually.
841 */
842 if (commit->util || commit->object.flags & SHOWN)
1d844ee7 843 string_list_append(&extra_refs, full_name)->util = commit;
f28e7c90 844 if (!commit->util)
f2dc849e
JS
845 commit->util = full_name;
846 }
847}
848
1d844ee7 849static void handle_tags_and_duplicates(void)
f2dc849e
JS
850{
851 struct commit *commit;
852 int i;
853
1d844ee7
FC
854 for (i = extra_refs.nr - 1; i >= 0; i--) {
855 const char *name = extra_refs.items[i].string;
856 struct object *object = extra_refs.items[i].util;
f2dc849e
JS
857 switch (object->type) {
858 case OBJ_TAG:
859 handle_tag(name, (struct tag *)object);
860 break;
861 case OBJ_COMMIT:
a8722750
JK
862 if (anonymize)
863 name = anonymize_refname(name);
f2dc849e
JS
864 /* create refs pointing to already seen commits */
865 commit = (struct commit *)object;
866 printf("reset %s\nfrom :%d\n\n", name,
867 get_object_mark(&commit->object));
868 show_progress();
869 break;
870 }
871 }
872}
873
df6a7ff7
PB
874static void export_marks(char *file)
875{
876 unsigned int i;
877 uint32_t mark;
878 struct object_decoration *deco = idnums.hash;
879 FILE *f;
96d69b55 880 int e = 0;
df6a7ff7
PB
881
882 f = fopen(file, "w");
883 if (!f)
bb6ad28c 884 die_errno("Unable to open marks file %s for writing.", file);
df6a7ff7 885
69913575
JH
886 for (i = 0; i < idnums.size; i++) {
887 if (deco->base && deco->base->type == 1) {
df6a7ff7 888 mark = ptr_to_mark(deco->decoration);
96d69b55
MA
889 if (fprintf(f, ":%"PRIu32" %s\n", mark,
890 sha1_to_hex(deco->base->sha1)) < 0) {
891 e = 1;
892 break;
893 }
df6a7ff7 894 }
69913575 895 deco++;
df6a7ff7
PB
896 }
897
96d69b55
MA
898 e |= ferror(f);
899 e |= fclose(f);
900 if (e)
df6a7ff7
PB
901 error("Unable to write marks file %s.", file);
902}
903
69913575 904static void import_marks(char *input_file)
df6a7ff7
PB
905{
906 char line[512];
907 FILE *f = fopen(input_file, "r");
908 if (!f)
d824cbba 909 die_errno("cannot read '%s'", input_file);
df6a7ff7
PB
910
911 while (fgets(line, sizeof(line), f)) {
912 uint32_t mark;
913 char *line_end, *mark_end;
914 unsigned char sha1[20];
915 struct object *object;
47bd9bf8 916 struct commit *commit;
e6812cfa 917 enum object_type type;
df6a7ff7
PB
918
919 line_end = strchr(line, '\n');
920 if (line[0] != ':' || !line_end)
921 die("corrupt mark line: %s", line);
69913575 922 *line_end = '\0';
df6a7ff7
PB
923
924 mark = strtoumax(line + 1, &mark_end, 10);
925 if (!mark || mark_end == line + 1
45c5d4a5 926 || *mark_end != ' ' || get_sha1_hex(mark_end + 1, sha1))
df6a7ff7
PB
927 die("corrupt mark line: %s", line);
928
c4458ecd
AP
929 if (last_idnum < mark)
930 last_idnum = mark;
931
e6812cfa
FC
932 type = sha1_object_info(sha1, NULL);
933 if (type < 0)
934 die("object not found: %s", sha1_to_hex(sha1));
935
936 if (type != OBJ_COMMIT)
937 /* only commits */
c4458ecd 938 continue;
df6a7ff7 939
47bd9bf8
FC
940 commit = lookup_commit(sha1);
941 if (!commit)
942 die("not a commit? can't happen: %s", sha1_to_hex(sha1));
943
944 object = &commit->object;
e6812cfa 945
df6a7ff7 946 if (object->flags & SHOWN)
43bc2302 947 error("Object %s already has a mark", sha1_to_hex(sha1));
df6a7ff7
PB
948
949 mark_object(object, mark);
df6a7ff7
PB
950
951 object->flags |= SHOWN;
952 }
953 fclose(f);
954}
955
60ed2643
FC
956static void handle_deletes(void)
957{
958 int i;
959 for (i = 0; i < refspecs_nr; i++) {
960 struct refspec *refspec = &refspecs[i];
961 if (*refspec->src)
962 continue;
963
964 printf("reset %s\nfrom %s\n\n",
965 refspec->dst, sha1_to_hex(null_sha1));
966 }
967}
968
f2dc849e
JS
969int cmd_fast_export(int argc, const char **argv, const char *prefix)
970{
971 struct rev_info revs;
3cd47459 972 struct object_array commits = OBJECT_ARRAY_INIT;
f2dc849e 973 struct commit *commit;
df6a7ff7 974 char *export_filename = NULL, *import_filename = NULL;
c4458ecd 975 uint32_t lastimportid;
03e9010c 976 struct string_list refspecs_list = STRING_LIST_INIT_NODUP;
f2dc849e
JS
977 struct option options[] = {
978 OPT_INTEGER(0, "progress", &progress,
3b787b96
NTND
979 N_("show progress after <n> objects")),
980 OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, N_("mode"),
981 N_("select handling of signed tags"),
f2dc849e 982 parse_opt_signed_tag_mode),
3b787b96
NTND
983 OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, N_("mode"),
984 N_("select handling of tags that tag filtered objects"),
2d8ad469 985 parse_opt_tag_of_filtered_mode),
3b787b96
NTND
986 OPT_STRING(0, "export-marks", &export_filename, N_("file"),
987 N_("Dump marks to this file")),
988 OPT_STRING(0, "import-marks", &import_filename, N_("file"),
989 N_("Import marks from this file")),
d5d09d47
SB
990 OPT_BOOL(0, "fake-missing-tagger", &fake_missing_tagger,
991 N_("Fake a tagger when tags lack one")),
992 OPT_BOOL(0, "full-tree", &full_tree,
993 N_("Output full tree for each commit")),
994 OPT_BOOL(0, "use-done-feature", &use_done_feature,
3b787b96
NTND
995 N_("Use the done feature to terminate the stream")),
996 OPT_BOOL(0, "no-data", &no_data, N_("Skip output of blob data")),
03e9010c
FC
997 OPT_STRING_LIST(0, "refspec", &refspecs_list, N_("refspec"),
998 N_("Apply refspec to exported refs")),
a8722750 999 OPT_BOOL(0, "anonymize", &anonymize, N_("anonymize output")),
f2dc849e
JS
1000 OPT_END()
1001 };
1002
dcfdbdf0
MV
1003 if (argc == 1)
1004 usage_with_options (fast_export_usage, options);
1005
f2dc849e 1006 /* we handle encodings */
ef90d6d4 1007 git_config(git_default_config, NULL);
f2dc849e
JS
1008
1009 init_revisions(&revs, prefix);
668f3aa7 1010 revs.topo_order = 1;
2374502c 1011 revs.show_source = 1;
32164131 1012 revs.rewrite_parents = 1;
8b2f86a7
FC
1013 argc = parse_options(argc, argv, prefix, options, fast_export_usage,
1014 PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
f2dc849e 1015 argc = setup_revisions(argc, argv, &revs, NULL);
f2dc849e
JS
1016 if (argc > 1)
1017 usage_with_options (fast_export_usage, options);
1018
03e9010c
FC
1019 if (refspecs_list.nr) {
1020 const char **refspecs_str;
1021 int i;
1022
1023 refspecs_str = xmalloc(sizeof(*refspecs_str) * refspecs_list.nr);
1024 for (i = 0; i < refspecs_list.nr; i++)
1025 refspecs_str[i] = refspecs_list.items[i].string;
1026
1027 refspecs_nr = refspecs_list.nr;
1028 refspecs = parse_fetch_refspec(refspecs_nr, refspecs_str);
1029
1030 string_list_clear(&refspecs_list, 1);
1031 free(refspecs_str);
1032 }
1033
82670a5c
SR
1034 if (use_done_feature)
1035 printf("feature done\n");
1036
df6a7ff7
PB
1037 if (import_filename)
1038 import_marks(import_filename);
c4458ecd 1039 lastimportid = last_idnum;
df6a7ff7 1040
afe069d1 1041 if (import_filename && revs.prune_data.nr)
4087a02e
EN
1042 full_tree = 1;
1043
1d844ee7 1044 get_tags_and_duplicates(&revs.cmdline);
f2dc849e 1045
3d51e1b5
MK
1046 if (prepare_revision_walk(&revs))
1047 die("revision walk setup failed");
f2dc849e
JS
1048 revs.diffopt.format_callback = show_filemodify;
1049 DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
1050 while ((commit = get_revision(&revs))) {
1051 if (has_unshown_parent(commit)) {
f2dc849e 1052 add_object_array(&commit->object, NULL, &commits);
f2dc849e
JS
1053 }
1054 else {
1055 handle_commit(commit, &revs);
1056 handle_tail(&commits, &revs);
1057 }
1058 }
1059
1d844ee7 1060 handle_tags_and_duplicates();
60ed2643 1061 handle_deletes();
f2dc849e 1062
c4458ecd 1063 if (export_filename && lastimportid != last_idnum)
df6a7ff7
PB
1064 export_marks(export_filename);
1065
82670a5c
SR
1066 if (use_done_feature)
1067 printf("done\n");
1068
03e9010c
FC
1069 free_refspec(refspecs_nr, refspecs);
1070
f2dc849e
JS
1071 return 0;
1072}