match-trees: compute buffer offset correctly when splicing
[gitweb.git] / builtin / fast-export.c
index d71e0333d4839336fbe3fa5b2d5e4fc9dd726ddf..9e283482efcfa6de0376cc9306061cea149b12df 100644 (file)
@@ -37,6 +37,8 @@ static int fake_missing_tagger;
 static int use_done_feature;
 static int no_data;
 static int full_tree;
+static int reference_excluded_commits;
+static int show_original_ids;
 static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
 static struct string_list tag_refs = STRING_LIST_INIT_NODUP;
 static struct refspec refspecs = REFSPEC_INIT_FETCH;
@@ -270,7 +272,10 @@ static void export_blob(const struct object_id *oid)
 
        mark_next_object(object);
 
-       printf("blob\nmark :%"PRIu32"\ndata %lu\n", last_idnum, size);
+       printf("blob\nmark :%"PRIu32"\n", last_idnum);
+       if (show_original_ids)
+               printf("original-oid %s\n", oid_to_hex(oid));
+       printf("data %"PRIuMAX"\n", (uintmax_t)size);
        if (size && fwrite(buf, size, 1, stdout) != 1)
                die_errno("could not write blob '%s'", oid_to_hex(oid));
        printf("\n");
@@ -597,7 +602,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
                message += 2;
 
        if (commit->parents &&
-           get_object_mark(&commit->parents->item->object) != 0 &&
+           (get_object_mark(&commit->parents->item->object) != 0 ||
+            reference_excluded_commits) &&
            !full_tree) {
                parse_commit_or_die(commit->parents->item);
                diff_tree_oid(get_commit_tree_oid(commit->parents->item),
@@ -633,8 +639,10 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
                reencoded = reencode_string(message, "UTF-8", encoding);
        if (!commit->parents)
                printf("reset %s\n", refname);
-       printf("commit %s\nmark :%"PRIu32"\n%.*s\n%.*s\ndata %u\n%s",
-              refname, last_idnum,
+       printf("commit %s\nmark :%"PRIu32"\n", refname, last_idnum);
+       if (show_original_ids)
+               printf("original-oid %s\n", oid_to_hex(&commit->object.oid));
+       printf("%.*s\n%.*s\ndata %u\n%s",
               (int)(author_end - author), author,
               (int)(committer_end - committer), committer,
               (unsigned)(reencoded
@@ -645,13 +653,21 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
        unuse_commit_buffer(commit, commit_buffer);
 
        for (i = 0, p = commit->parents; p; p = p->next) {
-               int mark = get_object_mark(&p->item->object);
-               if (!mark)
+               struct object *obj = &p->item->object;
+               int mark = get_object_mark(obj);
+
+               if (!mark && !reference_excluded_commits)
                        continue;
                if (i == 0)
-                       printf("from :%d\n", mark);
+                       printf("from ");
+               else
+                       printf("merge ");
+               if (mark)
+                       printf(":%d\n", mark);
                else
-                       printf("merge :%d\n", mark);
+                       printf("%s\n", oid_to_hex(anonymize ?
+                                                 anonymize_oid(&obj->oid) :
+                                                 &obj->oid));
                i++;
        }
 
@@ -804,8 +820,10 @@ static void handle_tag(const char *name, struct tag *tag)
 
        if (starts_with(name, "refs/tags/"))
                name += 10;
-       printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
-              name, tagged_mark,
+       printf("tag %s\nfrom :%d\n", name, tagged_mark);
+       if (show_original_ids)
+               printf("original-oid %s\n", oid_to_hex(&tag->object.oid));
+       printf("%.*s%sdata %d\n%.*s\n",
               (int)(tagger_end - tagger), tagger,
               tagger == tagger_end ? "" : "\n",
               (int)message_size, (int)message_size, message ? message : "");
@@ -932,13 +950,22 @@ static void handle_tags_and_duplicates(struct string_list *extras)
                                /*
                                 * Getting here means we have a commit which
                                 * was excluded by a negative refspec (e.g.
-                                * fast-export ^master master).  If the user
+                                * fast-export ^master master).  If we are
+                                * referencing excluded commits, set the ref
+                                * to the exact commit.  Otherwise, the user
                                 * wants the branch exported but every commit
-                                * in its history to be deleted, that sounds
-                                * like a ref deletion to me.
+                                * in its history to be deleted, which basically
+                                * just means deletion of the ref.
                                 */
-                               printf("reset %s\nfrom %s\n\n",
-                                      name, oid_to_hex(&null_oid));
+                               if (!reference_excluded_commits) {
+                                       /* delete the ref */
+                                       printf("reset %s\nfrom %s\n\n",
+                                              name, oid_to_hex(&null_oid));
+                                       continue;
+                               }
+                               /* set ref to commit using oid, not mark */
+                               printf("reset %s\nfrom %s\n\n", name,
+                                      oid_to_hex(&commit->object.oid));
                                continue;
                        }
 
@@ -1075,6 +1102,11 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
                OPT_STRING_LIST(0, "refspec", &refspecs_list, N_("refspec"),
                             N_("Apply refspec to exported refs")),
                OPT_BOOL(0, "anonymize", &anonymize, N_("anonymize output")),
+               OPT_BOOL(0, "reference-excluded-parents",
+                        &reference_excluded_commits, N_("Reference parents which are not in fast-export stream by object id")),
+               OPT_BOOL(0, "show-original-ids", &show_original_ids,
+                           N_("Show original object ids of blobs/commits")),
+
                OPT_END()
        };