2 * "git fast-export" builtin command
4 * Copyright (C) 2007 Johannes E. Schindelin
17 #include "string-list.h"
19 #include "parse-options.h"
24 static const char *fast_export_usage[] = {
25 N_("git fast-export [rev-list-opts]"),
30 static enum { ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = ABORT;
31 static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ERROR;
32 static int fake_missing_tagger;
33 static int use_done_feature;
36 static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
37 static struct refspec *refspecs;
38 static int refspecs_nr;
41 static int parse_opt_signed_tag_mode(const struct option *opt,
42 const char *arg, int unset)
44 if (unset || !strcmp(arg, "abort"))
45 signed_tag_mode = ABORT;
46 else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore"))
47 signed_tag_mode = VERBATIM;
48 else if (!strcmp(arg, "warn"))
49 signed_tag_mode = WARN;
50 else if (!strcmp(arg, "warn-strip"))
51 signed_tag_mode = WARN_STRIP;
52 else if (!strcmp(arg, "strip"))
53 signed_tag_mode = STRIP;
55 return error("Unknown signed-tags mode: %s", arg);
59 static int parse_opt_tag_of_filtered_mode(const struct option *opt,
60 const char *arg, int unset)
62 if (unset || !strcmp(arg, "abort"))
63 tag_of_filtered_mode = ERROR;
64 else if (!strcmp(arg, "drop"))
65 tag_of_filtered_mode = DROP;
66 else if (!strcmp(arg, "rewrite"))
67 tag_of_filtered_mode = REWRITE;
69 return error("Unknown tag-of-filtered mode: %s", arg);
73 static struct decoration idnums;
74 static uint32_t last_idnum;
76 static int has_unshown_parent(struct commit *commit)
78 struct commit_list *parent;
80 for (parent = commit->parents; parent; parent = parent->next)
81 if (!(parent->item->object.flags & SHOWN) &&
82 !(parent->item->object.flags & UNINTERESTING))
87 struct anonymized_entry {
88 struct hashmap_entry hash;
95 static int anonymized_entry_cmp(const void *va, const void *vb,
98 const struct anonymized_entry *a = va, *b = vb;
99 return a->orig_len != b->orig_len ||
100 memcmp(a->orig, b->orig, a->orig_len);
104 * Basically keep a cache of X->Y so that we can repeatedly replace
105 * the same anonymized string with another. The actual generation
106 * is farmed out to the generate function.
108 static const void *anonymize_mem(struct hashmap *map,
109 void *(*generate)(const void *, size_t *),
110 const void *orig, size_t *len)
112 struct anonymized_entry key, *ret;
115 hashmap_init(map, anonymized_entry_cmp, 0);
117 hashmap_entry_init(&key, memhash(orig, *len));
120 ret = hashmap_get(map, &key, NULL);
123 ret = xmalloc(sizeof(*ret));
124 hashmap_entry_init(&ret->hash, key.hash.hash);
125 ret->orig = xstrdup(orig);
126 ret->orig_len = *len;
127 ret->anon = generate(orig, len);
128 ret->anon_len = *len;
129 hashmap_put(map, ret);
132 *len = ret->anon_len;
137 * We anonymize each component of a path individually,
138 * so that paths a/b and a/c will share a common root.
139 * The paths are cached via anonymize_mem so that repeated
140 * lookups for "a" will yield the same value.
142 static void anonymize_path(struct strbuf *out, const char *path,
144 void *(*generate)(const void *, size_t *))
147 const char *end_of_component = strchrnul(path, '/');
148 size_t len = end_of_component - path;
149 const char *c = anonymize_mem(map, generate, path, &len);
150 strbuf_add(out, c, len);
151 path = end_of_component;
153 strbuf_addch(out, *path++);
157 /* Since intptr_t is C99, we do not use it here */
158 static inline uint32_t *mark_to_ptr(uint32_t mark)
160 return ((uint32_t *)NULL) + mark;
163 static inline uint32_t ptr_to_mark(void * mark)
165 return (uint32_t *)mark - (uint32_t *)NULL;
168 static inline void mark_object(struct object *object, uint32_t mark)
170 add_decoration(&idnums, object, mark_to_ptr(mark));
173 static inline void mark_next_object(struct object *object)
175 mark_object(object, ++last_idnum);
178 static int get_object_mark(struct object *object)
180 void *decoration = lookup_decoration(&idnums, object);
183 return ptr_to_mark(decoration);
186 static void show_progress(void)
188 static int counter = 0;
191 if ((++counter % progress) == 0)
192 printf("progress %d objects\n", counter);
196 * Ideally we would want some transformation of the blob data here
197 * that is unreversible, but would still be the same size and have
198 * the same data relationship to other blobs (so that we get the same
199 * delta and packing behavior as the original). But the first and last
200 * requirements there are probably mutually exclusive, so let's take
201 * the easy way out for now, and just generate arbitrary content.
203 * There's no need to cache this result with anonymize_mem, since
204 * we already handle blob content caching with marks.
206 static char *anonymize_blob(unsigned long *size)
209 struct strbuf out = STRBUF_INIT;
210 strbuf_addf(&out, "anonymous blob %d", counter++);
212 return strbuf_detach(&out, NULL);
215 static void export_blob(const struct object_id *oid)
218 enum object_type type;
220 struct object *object;
226 if (is_null_oid(oid))
229 object = lookup_object(oid->hash);
230 if (object && object->flags & SHOWN)
234 buf = anonymize_blob(&size);
235 object = (struct object *)lookup_blob(oid->hash);
238 buf = read_sha1_file(oid->hash, &type, &size);
240 die ("Could not read blob %s", oid_to_hex(oid));
241 if (check_sha1_signature(oid->hash, buf, size, typename(type)) < 0)
242 die("sha1 mismatch in blob %s", oid_to_hex(oid));
243 object = parse_object_buffer(oid->hash, type, size, buf, &eaten);
247 die("Could not read blob %s", oid_to_hex(oid));
249 mark_next_object(object);
251 printf("blob\nmark :%"PRIu32"\ndata %lu\n", last_idnum, size);
252 if (size && fwrite(buf, size, 1, stdout) != 1)
253 die_errno ("Could not write blob '%s'", oid_to_hex(oid));
258 object->flags |= SHOWN;
263 static int depth_first(const void *a_, const void *b_)
265 const struct diff_filepair *a = *((const struct diff_filepair **)a_);
266 const struct diff_filepair *b = *((const struct diff_filepair **)b_);
267 const char *name_a, *name_b;
268 int len_a, len_b, len;
271 name_a = a->one ? a->one->path : a->two->path;
272 name_b = b->one ? b->one->path : b->two->path;
274 len_a = strlen(name_a);
275 len_b = strlen(name_b);
276 len = (len_a < len_b) ? len_a : len_b;
278 /* strcmp will sort 'd' before 'd/e', we want 'd/e' before 'd' */
279 cmp = memcmp(name_a, name_b, len);
286 * Move 'R'ename entries last so that all references of the file
287 * appear in the output before it is renamed (e.g., when a file
288 * was copied and renamed in the same commit).
290 return (a->status == 'R') - (b->status == 'R');
293 static void print_path_1(const char *path)
295 int need_quote = quote_c_style(path, NULL, NULL, 0);
297 quote_c_style(path, NULL, stdout, 0);
298 else if (strchr(path, ' '))
299 printf("\"%s\"", path);
304 static void *anonymize_path_component(const void *path, size_t *len)
307 struct strbuf out = STRBUF_INIT;
308 strbuf_addf(&out, "path%d", counter++);
309 return strbuf_detach(&out, len);
312 static void print_path(const char *path)
317 static struct hashmap paths;
318 static struct strbuf anon = STRBUF_INIT;
320 anonymize_path(&anon, path, &paths, anonymize_path_component);
321 print_path_1(anon.buf);
326 static void *generate_fake_oid(const void *old, size_t *len)
328 static uint32_t counter = 1; /* avoid null sha1 */
329 unsigned char *out = xcalloc(GIT_SHA1_RAWSZ, 1);
330 put_be32(out + GIT_SHA1_RAWSZ - 4, counter++);
334 static const unsigned char *anonymize_sha1(const struct object_id *oid)
336 static struct hashmap sha1s;
337 size_t len = GIT_SHA1_RAWSZ;
338 return anonymize_mem(&sha1s, generate_fake_oid, oid, &len);
341 static void show_filemodify(struct diff_queue_struct *q,
342 struct diff_options *options, void *data)
347 * Handle files below a directory first, in case they are all deleted
348 * and the directory changes to a file or symlink.
350 QSORT(q->queue, q->nr, depth_first);
352 for (i = 0; i < q->nr; i++) {
353 struct diff_filespec *ospec = q->queue[i]->one;
354 struct diff_filespec *spec = q->queue[i]->two;
356 switch (q->queue[i]->status) {
357 case DIFF_STATUS_DELETED:
359 print_path(spec->path);
363 case DIFF_STATUS_COPIED:
364 case DIFF_STATUS_RENAMED:
365 printf("%c ", q->queue[i]->status);
366 print_path(ospec->path);
368 print_path(spec->path);
371 if (!oidcmp(&ospec->oid, &spec->oid) &&
372 ospec->mode == spec->mode)
376 case DIFF_STATUS_TYPE_CHANGED:
377 case DIFF_STATUS_MODIFIED:
378 case DIFF_STATUS_ADDED:
380 * Links refer to objects in another repositories;
381 * output the SHA-1 verbatim.
383 if (no_data || S_ISGITLINK(spec->mode))
384 printf("M %06o %s ", spec->mode,
385 sha1_to_hex(anonymize ?
386 anonymize_sha1(&spec->oid) :
389 struct object *object = lookup_object(spec->oid.hash);
390 printf("M %06o :%d ", spec->mode,
391 get_object_mark(object));
393 print_path(spec->path);
398 die("Unexpected comparison status '%c' for %s, %s",
400 ospec->path ? ospec->path : "none",
401 spec->path ? spec->path : "none");
406 static const char *find_encoding(const char *begin, const char *end)
408 const char *needle = "\nencoding ";
411 bol = memmem(begin, end ? end - begin : strlen(begin),
412 needle, strlen(needle));
414 return git_commit_encoding;
415 bol += strlen(needle);
416 eol = strchrnul(bol, '\n');
421 static void *anonymize_ref_component(const void *old, size_t *len)
424 struct strbuf out = STRBUF_INIT;
425 strbuf_addf(&out, "ref%d", counter++);
426 return strbuf_detach(&out, len);
429 static const char *anonymize_refname(const char *refname)
432 * If any of these prefixes is found, we will leave it intact
433 * so that tags remain tags and so forth.
435 static const char *prefixes[] = {
441 static struct hashmap refs;
442 static struct strbuf anon = STRBUF_INIT;
446 * We also leave "master" as a special case, since it does not reveal
447 * anything interesting.
449 if (!strcmp(refname, "refs/heads/master"))
453 for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
454 if (skip_prefix(refname, prefixes[i], &refname)) {
455 strbuf_addstr(&anon, prefixes[i]);
460 anonymize_path(&anon, refname, &refs, anonymize_ref_component);
465 * We do not even bother to cache commit messages, as they are unlikely
466 * to be repeated verbatim, and it is not that interesting when they are.
468 static char *anonymize_commit_message(const char *old)
471 return xstrfmt("subject %d\n\nbody\n", counter++);
474 static struct hashmap idents;
475 static void *anonymize_ident(const void *old, size_t *len)
478 struct strbuf out = STRBUF_INIT;
479 strbuf_addf(&out, "User %d <user%d@example.com>", counter, counter);
481 return strbuf_detach(&out, len);
485 * Our strategy here is to anonymize the names and email addresses,
486 * but keep timestamps intact, as they influence things like traversal
487 * order (and by themselves should not be too revealing).
489 static void anonymize_ident_line(const char **beg, const char **end)
491 static struct strbuf buffers[] = { STRBUF_INIT, STRBUF_INIT };
492 static unsigned which_buffer;
495 struct ident_split split;
496 const char *end_of_header;
498 out = &buffers[which_buffer++];
499 which_buffer %= ARRAY_SIZE(buffers);
502 /* skip "committer", "author", "tagger", etc */
503 end_of_header = strchr(*beg, ' ');
505 die("BUG: malformed line fed to anonymize_ident_line: %.*s",
506 (int)(*end - *beg), *beg);
508 strbuf_add(out, *beg, end_of_header - *beg);
510 if (!split_ident_line(&split, end_of_header, *end - end_of_header) &&
515 len = split.mail_end - split.name_begin;
516 ident = anonymize_mem(&idents, anonymize_ident,
517 split.name_begin, &len);
518 strbuf_add(out, ident, len);
519 strbuf_addch(out, ' ');
520 strbuf_add(out, split.date_begin, split.tz_end - split.date_begin);
522 strbuf_addstr(out, "Malformed Ident <malformed@example.com> 0 -0000");
526 *end = out->buf + out->len;
529 static void handle_commit(struct commit *commit, struct rev_info *rev)
531 int saved_output_format = rev->diffopt.output_format;
532 const char *commit_buffer;
533 const char *author, *author_end, *committer, *committer_end;
534 const char *encoding, *message;
535 char *reencoded = NULL;
536 struct commit_list *p;
540 rev->diffopt.output_format = DIFF_FORMAT_CALLBACK;
542 parse_commit_or_die(commit);
543 commit_buffer = get_commit_buffer(commit, NULL);
544 author = strstr(commit_buffer, "\nauthor ");
546 die ("Could not find author in commit %s",
547 oid_to_hex(&commit->object.oid));
549 author_end = strchrnul(author, '\n');
550 committer = strstr(author_end, "\ncommitter ");
552 die ("Could not find committer in commit %s",
553 oid_to_hex(&commit->object.oid));
555 committer_end = strchrnul(committer, '\n');
556 message = strstr(committer_end, "\n\n");
557 encoding = find_encoding(committer_end, message);
561 if (commit->parents &&
562 get_object_mark(&commit->parents->item->object) != 0 &&
564 parse_commit_or_die(commit->parents->item);
565 diff_tree_sha1(commit->parents->item->tree->object.oid.hash,
566 commit->tree->object.oid.hash, "", &rev->diffopt);
569 diff_root_tree_sha1(commit->tree->object.oid.hash,
572 /* Export the referenced blobs, and remember the marks. */
573 for (i = 0; i < diff_queued_diff.nr; i++)
574 if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
575 export_blob(&diff_queued_diff.queue[i]->two->oid);
577 refname = commit->util;
579 refname = anonymize_refname(refname);
580 anonymize_ident_line(&committer, &committer_end);
581 anonymize_ident_line(&author, &author_end);
584 mark_next_object(&commit->object);
586 reencoded = anonymize_commit_message(message);
587 else if (!is_encoding_utf8(encoding))
588 reencoded = reencode_string(message, "UTF-8", encoding);
589 if (!commit->parents)
590 printf("reset %s\n", refname);
591 printf("commit %s\nmark :%"PRIu32"\n%.*s\n%.*s\ndata %u\n%s",
593 (int)(author_end - author), author,
594 (int)(committer_end - committer), committer,
596 ? strlen(reencoded) : message
597 ? strlen(message) : 0),
598 reencoded ? reencoded : message ? message : "");
600 unuse_commit_buffer(commit, commit_buffer);
602 for (i = 0, p = commit->parents; p; p = p->next) {
603 int mark = get_object_mark(&p->item->object);
607 printf("from :%d\n", mark);
609 printf("merge :%d\n", mark);
614 printf("deleteall\n");
615 log_tree_diff_flush(rev);
616 rev->diffopt.output_format = saved_output_format;
623 static void *anonymize_tag(const void *old, size_t *len)
626 struct strbuf out = STRBUF_INIT;
627 strbuf_addf(&out, "tag message %d", counter++);
628 return strbuf_detach(&out, len);
631 static void handle_tail(struct object_array *commits, struct rev_info *revs)
633 struct commit *commit;
634 while (commits->nr) {
635 commit = (struct commit *)commits->objects[commits->nr - 1].item;
636 if (has_unshown_parent(commit))
638 handle_commit(commit, revs);
643 static void handle_tag(const char *name, struct tag *tag)
646 enum object_type type;
648 const char *tagger, *tagger_end, *message;
649 size_t message_size = 0;
650 struct object *tagged;
654 /* Trees have no identifier in fast-export output, thus we have no way
655 * to output tags of trees, tags of tags of trees, etc. Simply omit
658 tagged = tag->tagged;
659 while (tagged->type == OBJ_TAG) {
660 tagged = ((struct tag *)tagged)->tagged;
662 if (tagged->type == OBJ_TREE) {
663 warning("Omitting tag %s,\nsince tags of trees (or tags of tags of trees, etc.) are not supported.",
664 oid_to_hex(&tag->object.oid));
668 buf = read_sha1_file(tag->object.oid.hash, &type, &size);
670 die ("Could not read tag %s", oid_to_hex(&tag->object.oid));
671 message = memmem(buf, size, "\n\n", 2);
674 message_size = strlen(message);
676 tagger = memmem(buf, message ? message - buf : size, "\ntagger ", 8);
678 if (fake_missing_tagger)
679 tagger = "tagger Unspecified Tagger "
680 "<unspecified-tagger> 0 +0000";
683 tagger_end = tagger + strlen(tagger);
686 tagger_end = strchrnul(tagger, '\n');
688 anonymize_ident_line(&tagger, &tagger_end);
692 name = anonymize_refname(name);
694 static struct hashmap tags;
695 message = anonymize_mem(&tags, anonymize_tag,
696 message, &message_size);
700 /* handle signed tags */
702 const char *signature = strstr(message,
703 "\n-----BEGIN PGP SIGNATURE-----\n");
705 switch(signed_tag_mode) {
707 die ("Encountered signed tag %s; use "
708 "--signed-tags=<mode> to handle it.",
709 oid_to_hex(&tag->object.oid));
711 warning ("Exporting signed tag %s",
712 oid_to_hex(&tag->object.oid));
717 warning ("Stripping signature from tag %s",
718 oid_to_hex(&tag->object.oid));
721 message_size = signature + 1 - message;
726 /* handle tag->tagged having been filtered out due to paths specified */
727 tagged = tag->tagged;
728 tagged_mark = get_object_mark(tagged);
730 switch(tag_of_filtered_mode) {
732 die ("Tag %s tags unexported object; use "
733 "--tag-of-filtered-object=<mode> to handle it.",
734 oid_to_hex(&tag->object.oid));
736 /* Ignore this tag altogether */
740 if (tagged->type != OBJ_COMMIT) {
741 die ("Tag %s tags unexported %s!",
742 oid_to_hex(&tag->object.oid),
743 typename(tagged->type));
745 p = (struct commit *)tagged;
747 if (p->parents && p->parents->next)
749 if (p->object.flags & UNINTERESTING)
751 if (!(p->object.flags & TREESAME))
754 die ("Can't find replacement commit for tag %s\n",
755 oid_to_hex(&tag->object.oid));
756 p = p->parents->item;
758 tagged_mark = get_object_mark(&p->object);
762 if (starts_with(name, "refs/tags/"))
764 printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
766 (int)(tagger_end - tagger), tagger,
767 tagger == tagger_end ? "" : "\n",
768 (int)message_size, (int)message_size, message ? message : "");
772 static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)
774 switch (e->item->type) {
776 return (struct commit *)e->item;
778 struct tag *tag = (struct tag *)e->item;
780 /* handle nested tags */
781 while (tag && tag->object.type == OBJ_TAG) {
782 parse_object(tag->object.oid.hash);
783 string_list_append(&extra_refs, full_name)->util = tag;
784 tag = (struct tag *)tag->tagged;
787 die("Tag %s points nowhere?", e->name);
788 return (struct commit *)tag;
796 static void get_tags_and_duplicates(struct rev_cmdline_info *info)
800 for (i = 0; i < info->nr; i++) {
801 struct rev_cmdline_entry *e = info->rev + i;
802 struct object_id oid;
803 struct commit *commit;
806 if (e->flags & UNINTERESTING)
809 if (dwim_ref(e->name, strlen(e->name), oid.hash, &full_name) != 1)
814 private = apply_refspecs(refspecs, refspecs_nr, full_name);
821 commit = get_commit(e, full_name);
823 warning("%s: Unexpected object of type %s, skipping.",
825 typename(e->item->type));
829 switch(commit->object.type) {
833 export_blob(&commit->object.oid);
835 default: /* OBJ_TAG (nested tags) is already handled */
836 warning("Tag points to object of unexpected type %s, skipping.",
837 typename(commit->object.type));
842 * This ref will not be updated through a commit, lets make
843 * sure it gets properly updated eventually.
845 if (commit->util || commit->object.flags & SHOWN)
846 string_list_append(&extra_refs, full_name)->util = commit;
848 commit->util = full_name;
852 static void handle_tags_and_duplicates(void)
854 struct commit *commit;
857 for (i = extra_refs.nr - 1; i >= 0; i--) {
858 const char *name = extra_refs.items[i].string;
859 struct object *object = extra_refs.items[i].util;
860 switch (object->type) {
862 handle_tag(name, (struct tag *)object);
866 name = anonymize_refname(name);
867 /* create refs pointing to already seen commits */
868 commit = (struct commit *)object;
869 printf("reset %s\nfrom :%d\n\n", name,
870 get_object_mark(&commit->object));
877 static void export_marks(char *file)
881 struct object_decoration *deco = idnums.hash;
885 f = fopen_for_writing(file);
887 die_errno("Unable to open marks file %s for writing.", file);
889 for (i = 0; i < idnums.size; i++) {
890 if (deco->base && deco->base->type == 1) {
891 mark = ptr_to_mark(deco->decoration);
892 if (fprintf(f, ":%"PRIu32" %s\n", mark,
893 oid_to_hex(&deco->base->oid)) < 0) {
904 error("Unable to write marks file %s.", file);
907 static void import_marks(char *input_file)
910 FILE *f = fopen(input_file, "r");
912 die_errno("cannot read '%s'", input_file);
914 while (fgets(line, sizeof(line), f)) {
916 char *line_end, *mark_end;
917 struct object_id oid;
918 struct object *object;
919 struct commit *commit;
920 enum object_type type;
922 line_end = strchr(line, '\n');
923 if (line[0] != ':' || !line_end)
924 die("corrupt mark line: %s", line);
927 mark = strtoumax(line + 1, &mark_end, 10);
928 if (!mark || mark_end == line + 1
929 || *mark_end != ' ' || get_oid_hex(mark_end + 1, &oid))
930 die("corrupt mark line: %s", line);
932 if (last_idnum < mark)
935 type = sha1_object_info(oid.hash, NULL);
937 die("object not found: %s", oid_to_hex(&oid));
939 if (type != OBJ_COMMIT)
943 commit = lookup_commit(oid.hash);
945 die("not a commit? can't happen: %s", oid_to_hex(&oid));
947 object = &commit->object;
949 if (object->flags & SHOWN)
950 error("Object %s already has a mark", oid_to_hex(&oid));
952 mark_object(object, mark);
954 object->flags |= SHOWN;
959 static void handle_deletes(void)
962 for (i = 0; i < refspecs_nr; i++) {
963 struct refspec *refspec = &refspecs[i];
967 printf("reset %s\nfrom %s\n\n",
968 refspec->dst, sha1_to_hex(null_sha1));
972 int cmd_fast_export(int argc, const char **argv, const char *prefix)
974 struct rev_info revs;
975 struct object_array commits = OBJECT_ARRAY_INIT;
976 struct commit *commit;
977 char *export_filename = NULL, *import_filename = NULL;
978 uint32_t lastimportid;
979 struct string_list refspecs_list = STRING_LIST_INIT_NODUP;
980 struct option options[] = {
981 OPT_INTEGER(0, "progress", &progress,
982 N_("show progress after <n> objects")),
983 OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, N_("mode"),
984 N_("select handling of signed tags"),
985 parse_opt_signed_tag_mode),
986 OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, N_("mode"),
987 N_("select handling of tags that tag filtered objects"),
988 parse_opt_tag_of_filtered_mode),
989 OPT_STRING(0, "export-marks", &export_filename, N_("file"),
990 N_("Dump marks to this file")),
991 OPT_STRING(0, "import-marks", &import_filename, N_("file"),
992 N_("Import marks from this file")),
993 OPT_BOOL(0, "fake-missing-tagger", &fake_missing_tagger,
994 N_("Fake a tagger when tags lack one")),
995 OPT_BOOL(0, "full-tree", &full_tree,
996 N_("Output full tree for each commit")),
997 OPT_BOOL(0, "use-done-feature", &use_done_feature,
998 N_("Use the done feature to terminate the stream")),
999 OPT_BOOL(0, "no-data", &no_data, N_("Skip output of blob data")),
1000 OPT_STRING_LIST(0, "refspec", &refspecs_list, N_("refspec"),
1001 N_("Apply refspec to exported refs")),
1002 OPT_BOOL(0, "anonymize", &anonymize, N_("anonymize output")),
1007 usage_with_options (fast_export_usage, options);
1009 /* we handle encodings */
1010 git_config(git_default_config, NULL);
1012 init_revisions(&revs, prefix);
1013 revs.topo_order = 1;
1014 revs.show_source = 1;
1015 revs.rewrite_parents = 1;
1016 argc = parse_options(argc, argv, prefix, options, fast_export_usage,
1017 PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
1018 argc = setup_revisions(argc, argv, &revs, NULL);
1020 usage_with_options (fast_export_usage, options);
1022 if (refspecs_list.nr) {
1023 const char **refspecs_str;
1026 ALLOC_ARRAY(refspecs_str, refspecs_list.nr);
1027 for (i = 0; i < refspecs_list.nr; i++)
1028 refspecs_str[i] = refspecs_list.items[i].string;
1030 refspecs_nr = refspecs_list.nr;
1031 refspecs = parse_fetch_refspec(refspecs_nr, refspecs_str);
1033 string_list_clear(&refspecs_list, 1);
1037 if (use_done_feature)
1038 printf("feature done\n");
1040 if (import_filename)
1041 import_marks(import_filename);
1042 lastimportid = last_idnum;
1044 if (import_filename && revs.prune_data.nr)
1047 get_tags_and_duplicates(&revs.cmdline);
1049 if (prepare_revision_walk(&revs))
1050 die("revision walk setup failed");
1051 revs.diffopt.format_callback = show_filemodify;
1052 DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
1053 while ((commit = get_revision(&revs))) {
1054 if (has_unshown_parent(commit)) {
1055 add_object_array(&commit->object, NULL, &commits);
1058 handle_commit(commit, &revs);
1059 handle_tail(&commits, &revs);
1063 handle_tags_and_duplicates();
1066 if (export_filename && lastimportid != last_idnum)
1067 export_marks(export_filename);
1069 if (use_done_feature)
1072 free_refspec(refspecs_nr, refspecs);