refspec: make hash size independent
[gitweb.git] / pretty.c
index 610837e43949f7587433fab50c932c48bfa9ae3f..f496f0f1284db4ea7c6a20022311381bd9dc1b64 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -98,6 +98,10 @@ static void setup_commit_formats(void)
                { "fuller",     CMIT_FMT_FULLER,        0,      8 },
                { "full",       CMIT_FMT_FULL,          0,      8 },
                { "oneline",    CMIT_FMT_ONELINE,       1,      0 }
+               /*
+                * Please update $__git_log_pretty_formats in
+                * git-completion.bash when you add new formats.
+                */
        };
        commit_formats_len = ARRAY_SIZE(builtin_formats);
        builtin_formats_len = commit_formats_len;
@@ -595,14 +599,15 @@ static char *replace_encoding_header(char *buf, const char *encoding)
        return strbuf_detach(&tmp, NULL);
 }
 
-const char *logmsg_reencode(const struct commit *commit,
-                           char **commit_encoding,
-                           const char *output_encoding)
+const char *repo_logmsg_reencode(struct repository *r,
+                                const struct commit *commit,
+                                char **commit_encoding,
+                                const char *output_encoding)
 {
        static const char *utf8 = "UTF-8";
        const char *use_encoding;
        char *encoding;
-       const char *msg = get_commit_buffer(commit, NULL);
+       const char *msg = repo_get_commit_buffer(r, commit, NULL);
        char *out;
 
        if (!output_encoding || !*output_encoding) {
@@ -630,7 +635,7 @@ const char *logmsg_reencode(const struct commit *commit,
                 * the cached copy from get_commit_buffer, we need to duplicate it
                 * to avoid munging the cached copy.
                 */
-               if (msg == get_cached_commit_buffer(the_repository, commit, NULL))
+               if (msg == get_cached_commit_buffer(r, commit, NULL))
                        out = xstrdup(msg);
                else
                        out = (char *)msg;
@@ -644,7 +649,7 @@ const char *logmsg_reencode(const struct commit *commit,
                 */
                out = reencode_string(msg, output_encoding, use_encoding);
                if (out)
-                       unuse_commit_buffer(commit, msg);
+                       repo_unuse_commit_buffer(r, commit, msg);
        }
 
        /*
@@ -1115,6 +1120,19 @@ static int match_placeholder_bool_arg(const char *to_parse, const char *candidat
        return 1;
 }
 
+static int format_trailer_match_cb(const struct strbuf *key, void *ud)
+{
+       const struct string_list *list = ud;
+       const struct string_list_item *item;
+
+       for_each_string_list_item (item, list) {
+               if (key->len == (uintptr_t)item->util &&
+                   !strncasecmp(item->string, key->buf, key->len))
+                       return 1;
+       }
+       return 0;
+}
+
 static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                                const char *placeholder,
                                void *context)
@@ -1124,9 +1142,14 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
        const char *msg = c->message;
        struct commit_list *p;
        const char *arg;
-       int ch;
+       size_t res;
+       char **slot;
 
        /* these are independent of the commit */
+       res = strbuf_expand_literal_cb(sb, placeholder, NULL);
+       if (res)
+               return res;
+
        switch (placeholder[0]) {
        case 'C':
                if (starts_with(placeholder + 1, "(auto)")) {
@@ -1145,16 +1168,6 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                         */
                        return ret;
                }
-       case 'n':               /* newline */
-               strbuf_addch(sb, '\n');
-               return 1;
-       case 'x':
-               /* %x00 == NUL, %x0a == LF, etc. */
-               ch = hex2chr(placeholder + 1);
-               if (ch < 0)
-                       return 0;
-               strbuf_addch(sb, ch);
-               return 3;
        case 'w':
                if (placeholder[1] == '(') {
                        unsigned long width = 0, indent1 = 0, indent2 = 0;
@@ -1235,6 +1248,14 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                load_ref_decorations(NULL, DECORATE_SHORT_REFS);
                format_decorations_extended(sb, commit, c->auto_color, "", ", ", "");
                return 1;
+       case 'S':               /* tag/branch like --source */
+               if (!(c->pretty_ctx->rev && c->pretty_ctx->rev->sources))
+                       return 0;
+               slot = revision_sources_at(c->pretty_ctx->rev->sources, commit);
+               if (!(slot && *slot))
+                       return 0;
+               strbuf_addstr(sb, *slot);
+               return 1;
        case 'g':               /* reflog info */
                switch(placeholder[1]) {
                case 'd':       /* reflog selector */
@@ -1353,6 +1374,8 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
 
        if (skip_prefix(placeholder, "(trailers", &arg)) {
                struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
+               struct string_list filter_list = STRING_LIST_INIT_NODUP;
+               struct strbuf sepbuf = STRBUF_INIT;
                size_t ret = 0;
 
                opts.no_divider = 1;
@@ -1360,8 +1383,33 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                if (*arg == ':') {
                        arg++;
                        for (;;) {
-                               if (!match_placeholder_bool_arg(arg, "only", &arg, &opts.only_trailers) &&
-                                   !match_placeholder_bool_arg(arg, "unfold", &arg, &opts.unfold))
+                               const char *argval;
+                               size_t arglen;
+
+                               if (match_placeholder_arg_value(arg, "key", &arg, &argval, &arglen)) {
+                                       uintptr_t len = arglen;
+
+                                       if (!argval)
+                                               goto trailer_out;
+
+                                       if (len && argval[len - 1] == ':')
+                                               len--;
+                                       string_list_append(&filter_list, argval)->util = (char *)len;
+
+                                       opts.filter = format_trailer_match_cb;
+                                       opts.filter_data = &filter_list;
+                                       opts.only_trailers = 1;
+                               } else if (match_placeholder_arg_value(arg, "separator", &arg, &argval, &arglen)) {
+                                       char *fmt;
+
+                                       strbuf_reset(&sepbuf);
+                                       fmt = xstrndup(argval, arglen);
+                                       strbuf_expand(&sepbuf, fmt, strbuf_expand_literal_cb, NULL);
+                                       free(fmt);
+                                       opts.separator = &sepbuf;
+                               } else if (!match_placeholder_bool_arg(arg, "only", &arg, &opts.only_trailers) &&
+                                          !match_placeholder_bool_arg(arg, "unfold", &arg, &opts.unfold) &&
+                                          !match_placeholder_bool_arg(arg, "valueonly", &arg, &opts.value_only))
                                        break;
                        }
                }
@@ -1369,6 +1417,9 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                        format_trailers_from_commit(sb, msg + c->subject_off, &opts);
                        ret = arg - placeholder + 1;
                }
+       trailer_out:
+               string_list_clear(&filter_list, 0);
+               strbuf_release(&sepbuf);
                return ret;
        }
 
@@ -1538,6 +1589,9 @@ static size_t userformat_want_item(struct strbuf *sb, const char *placeholder,
        case 'N':
                w->notes = 1;
                break;
+       case 'S':
+               w->source = 1;
+               break;
        }
        return 0;
 }
@@ -1555,9 +1609,10 @@ void userformat_find_requirements(const char *fmt, struct userformat_want *w)
        strbuf_release(&dummy);
 }
 
-void format_commit_message(const struct commit *commit,
-                          const char *format, struct strbuf *sb,
-                          const struct pretty_print_context *pretty_ctx)
+void repo_format_commit_message(struct repository *r,
+                               const struct commit *commit,
+                               const char *format, struct strbuf *sb,
+                               const struct pretty_print_context *pretty_ctx)
 {
        struct format_commit_context context;
        const char *output_enc = pretty_ctx->output_encoding;
@@ -1571,9 +1626,9 @@ void format_commit_message(const struct commit *commit,
         * convert a commit message to UTF-8 first
         * as far as 'format_commit_item' assumes it in UTF-8
         */
-       context.message = logmsg_reencode(commit,
-                                         &context.commit_encoding,
-                                         utf8);
+       context.message = repo_logmsg_reencode(r, commit,
+                                              &context.commit_encoding,
+                                              utf8);
 
        strbuf_expand(sb, format, format_commit_item, &context);
        rewrap_message_tail(sb, &context, 0, 0, 0);
@@ -1597,7 +1652,7 @@ void format_commit_message(const struct commit *commit,
        }
 
        free(context.commit_encoding);
-       unuse_commit_buffer(commit, context.message);
+       repo_unuse_commit_buffer(r, commit, context.message);
 }
 
 static void pp_header(struct pretty_print_context *pp,