upload/receive-pack: allow hiding ref hierarchies
[gitweb.git] / builtin / log.c
index e7b7db1cacf1934a9bb0b96beb98ddda15a66074..5a4055eb0b0d4965785b6f69dbe92efe251c54dd 100644 (file)
@@ -678,7 +678,7 @@ static int reopen_stdout(struct commit *commit, const char *subject,
                         struct rev_info *rev, int quiet)
 {
        struct strbuf filename = STRBUF_INIT;
-       int suffix_len = strlen(fmt_patch_suffix) + 1;
+       int suffix_len = strlen(rev->patch_suffix) + 1;
 
        if (output_directory) {
                strbuf_addstr(&filename, output_directory);
@@ -689,7 +689,12 @@ static int reopen_stdout(struct commit *commit, const char *subject,
                        strbuf_addch(&filename, '/');
        }
 
-       get_patch_filename(commit, subject, rev->nr, fmt_patch_suffix, &filename);
+       if (rev->numbered_files)
+               strbuf_addf(&filename, "%d", rev->nr);
+       else if (commit)
+               fmt_output_commit(&filename, commit, rev);
+       else
+               fmt_output_subject(&filename, subject, rev);
 
        if (!quiet)
                fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
@@ -773,7 +778,6 @@ static void add_branch_description(struct strbuf *buf, const char *branch_name)
 }
 
 static void make_cover_letter(struct rev_info *rev, int use_stdout,
-                             int numbered, int numbered_files,
                              struct commit *origin,
                              int nr, struct commit **list, struct commit *head,
                              const char *branch_name,
@@ -796,7 +800,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
        committer = git_committer_info(0);
 
        if (!use_stdout &&
-           reopen_stdout(NULL, numbered_files ? NULL : "cover-letter", rev, quiet))
+           reopen_stdout(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
                return;
 
        log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
@@ -1016,8 +1020,9 @@ static char *find_branch_name(struct rev_info *rev)
 {
        int i, positive = -1;
        unsigned char branch_sha1[20];
-       struct strbuf buf = STRBUF_INIT;
-       const char *branch;
+       const unsigned char *tip_sha1;
+       const char *ref;
+       char *full_ref, *branch = NULL;
 
        for (i = 0; i < rev->cmdline.nr; i++) {
                if (rev->cmdline.rev[i].flags & UNINTERESTING)
@@ -1027,18 +1032,27 @@ static char *find_branch_name(struct rev_info *rev)
                else
                        return NULL;
        }
-       if (positive < 0)
+       if (0 <= positive) {
+               ref = rev->cmdline.rev[positive].name;
+               tip_sha1 = rev->cmdline.rev[positive].item->sha1;
+       } else if (!rev->cmdline.nr && rev->pending.nr == 1 &&
+                  !strcmp(rev->pending.objects[0].name, "HEAD")) {
+               /*
+                * No actual ref from command line, but "HEAD" from
+                * rev->def was added in setup_revisions()
+                * e.g. format-patch --cover-letter -12
+                */
+               ref = "HEAD";
+               tip_sha1 = rev->pending.objects[0].item->sha1;
+       } else {
                return NULL;
-       strbuf_addf(&buf, "refs/heads/%s", rev->cmdline.rev[positive].name);
-       branch = resolve_ref_unsafe(buf.buf, branch_sha1, 1, NULL);
-       if (!branch ||
-           prefixcmp(branch, "refs/heads/") ||
-           hashcmp(rev->cmdline.rev[positive].item->sha1, branch_sha1))
-               branch = NULL;
-       strbuf_release(&buf);
-       if (branch)
-               return xstrdup(rev->cmdline.rev[positive].name);
-       return NULL;
+       }
+       if (dwim_ref(ref, strlen(ref), branch_sha1, &full_ref) &&
+           !prefixcmp(full_ref, "refs/heads/") &&
+           !hashcmp(tip_sha1, branch_sha1))
+               branch = xstrdup(full_ref + strlen("refs/heads/"));
+       free(full_ref);
+       return branch;
 }
 
 int cmd_format_patch(int argc, const char **argv, const char *prefix)
@@ -1050,7 +1064,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        int nr = 0, total, i;
        int use_stdout = 0;
        int start_number = -1;
-       int numbered_files = 0;         /* _just_ numbers */
+       int just_numbers = 0;
        int ignore_if_in_upstream = 0;
        int cover_letter = 0;
        int boundary_count = 0;
@@ -1062,6 +1076,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        struct strbuf buf = STRBUF_INIT;
        int use_patch_format = 0;
        int quiet = 0;
+       int reroll_count = -1;
        char *branch_name = NULL;
        const struct option builtin_format_patch_options[] = {
                { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
@@ -1075,12 +1090,14 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                            N_("print patches to standard out")),
                OPT_BOOLEAN(0, "cover-letter", &cover_letter,
                            N_("generate a cover letter")),
-               OPT_BOOLEAN(0, "numbered-files", &numbered_files,
+               OPT_BOOLEAN(0, "numbered-files", &just_numbers,
                            N_("use simple number sequence for output file names")),
                OPT_STRING(0, "suffix", &fmt_patch_suffix, N_("sfx"),
                            N_("use <sfx> instead of '.patch'")),
                OPT_INTEGER(0, "start-number", &start_number,
                            N_("start numbering patches at <n> instead of 1")),
+               OPT_INTEGER('v', "reroll-count", &reroll_count,
+                           N_("mark the series as Nth re-roll")),
                { OPTION_CALLBACK, 0, "subject-prefix", &rev, N_("prefix"),
                            N_("Use [<prefix>] instead of [PATCH]"),
                            PARSE_OPT_NONEG, subject_prefix_callback },
@@ -1154,6 +1171,14 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                             PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
                             PARSE_OPT_KEEP_DASHDASH);
 
+       if (0 < reroll_count) {
+               struct strbuf sprefix = STRBUF_INIT;
+               strbuf_addf(&sprefix, "%s v%d",
+                           rev.subject_prefix, reroll_count);
+               rev.reroll_count = reroll_count;
+               rev.subject_prefix = strbuf_detach(&sprefix, NULL);
+       }
+
        if (do_signoff) {
                const char *committer;
                const char *endpos;
@@ -1344,12 +1369,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                const char *msgid = clean_message_id(in_reply_to);
                string_list_append(rev.ref_message_ids, msgid);
        }
-       rev.numbered_files = numbered_files;
+       rev.numbered_files = just_numbers;
        rev.patch_suffix = fmt_patch_suffix;
        if (cover_letter) {
                if (thread)
                        gen_message_id(&rev, "cover");
-               make_cover_letter(&rev, use_stdout, numbered, numbered_files,
+               make_cover_letter(&rev, use_stdout,
                                  origin, nr, list, head, branch_name, quiet);
                total++;
                start_number--;
@@ -1396,7 +1421,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                }
 
                if (!use_stdout &&
-                   reopen_stdout(numbered_files ? NULL : commit, NULL, &rev, quiet))
+                   reopen_stdout(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
                        die(_("Failed to create output files"));
                shown = log_tree_commit(&rev, commit);
                free(commit->buffer);