tree.c: update read_tree_recursive callback to pass strbuf as base
[gitweb.git] / builtin / log.c
index 39e883635279ad21f3ddd7b224f484b9b04700b0..f2a9f0156d8a8b15c7c879355b137b669dea8cf2 100644 (file)
@@ -63,6 +63,8 @@ static int parse_decoration_style(const char *var, const char *value)
                return DECORATE_FULL_REFS;
        else if (!strcmp(value, "short"))
                return DECORATE_SHORT_REFS;
+       else if (!strcmp(value, "auto"))
+               return (isatty(1) || pager_in_use()) ? DECORATE_SHORT_REFS : 0;
        return -1;
 }
 
@@ -76,7 +78,7 @@ static int decorate_callback(const struct option *opt, const char *arg, int unse
                decoration_style = DECORATE_SHORT_REFS;
 
        if (decoration_style < 0)
-               die("invalid --decorate option: %s", arg);
+               die(_("invalid --decorate option: %s"), arg);
 
        decoration_given = 1;
 
@@ -128,7 +130,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
                { OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
                  PARSE_OPT_OPTARG, decorate_callback},
                OPT_CALLBACK('L', NULL, &line_cb, "n,m:file",
-                            "Process line range n,m in file, counting from 1",
+                            N_("Process line range n,m in file, counting from 1"),
                             log_line_range_callback),
                OPT_END()
        };
@@ -148,7 +150,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
 
        /* Any arguments at this point are not recognized */
        if (argc > 1)
-               die("unrecognized argument: %s", argv[1]);
+               die(_("unrecognized argument: %s"), argv[1]);
 
        memset(&w, 0, sizeof(w));
        userformat_find_requirements(NULL, &w);
@@ -158,13 +160,9 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
        if (rev->show_notes)
                init_display_notes(&rev->notes_opt);
 
-       if (rev->diffopt.pickaxe || rev->diffopt.filter)
+       if (rev->diffopt.pickaxe || rev->diffopt.filter ||
+           DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES))
                rev->always_show_header = 0;
-       if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) {
-               rev->always_show_header = 0;
-               if (rev->diffopt.pathspec.nr != 1)
-                       usage("git logs can only follow renames on one pathname at a time");
-       }
 
        if (source)
                rev->show_source = 1;
@@ -349,8 +347,7 @@ static int cmd_log_walk(struct rev_info *rev)
                        rev->max_count++;
                if (!rev->reflog_info) {
                        /* we allow cycles in reflog ancestry */
-                       free(commit->buffer);
-                       commit->buffer = NULL;
+                       free_commit_buffer(commit);
                }
                free_commit_list(commit->parents);
                commit->parents = NULL;
@@ -371,6 +368,8 @@ static int cmd_log_walk(struct rev_info *rev)
 
 static int git_log_config(const char *var, const char *value, void *cb)
 {
+       const char *slot_name;
+
        if (!strcmp(var, "format.pretty"))
                return git_config_string(&fmt_pretty, var, value);
        if (!strcmp(var, "format.subjectprefix"))
@@ -391,8 +390,8 @@ static int git_log_config(const char *var, const char *value, void *cb)
                default_show_root = git_config_bool(var, value);
                return 0;
        }
-       if (starts_with(var, "color.decorate."))
-               return parse_decorate_color_config(var, 15, value);
+       if (skip_prefix(var, "color.decorate.", &slot_name))
+               return parse_decorate_color_config(var, slot_name, value);
        if (!strcmp(var, "log.mailmap")) {
                use_mailmap_config = git_config_bool(var, value);
                return 0;
@@ -450,13 +449,13 @@ static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, con
                return stream_blob_to_fd(1, sha1, NULL, 0);
 
        if (get_sha1_with_context(obj_name, 0, sha1c, &obj_context))
-               die("Not a valid object name %s", obj_name);
+               die(_("Not a valid object name %s"), obj_name);
        if (!obj_context.path[0] ||
            !textconv_object(obj_context.path, obj_context.mode, sha1c, 1, &buf, &size))
                return stream_blob_to_fd(1, sha1, NULL, 0);
 
        if (!buf)
-               die("git show %s: bad file", obj_name);
+               die(_("git show %s: bad file"), obj_name);
 
        write_or_die(1, buf, size);
        return 0;
@@ -490,7 +489,7 @@ static int show_tag_object(const unsigned char *sha1, struct rev_info *rev)
 }
 
 static int show_tree_object(const unsigned char *sha1,
-               const char *base, int baselen,
+               struct strbuf *base,
                const char *pathname, unsigned mode, int stage, void *context)
 {
        printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
@@ -673,6 +672,7 @@ static void add_header(const char *value)
 static int thread;
 static int do_signoff;
 static const char *signature = git_version_string;
+static const char *signature_file;
 static int config_cover_letter;
 
 enum {
@@ -742,6 +742,8 @@ static int git_format_config(const char *var, const char *value, void *cb)
        }
        if (!strcmp(var, "format.signature"))
                return git_config_string(&signature, var, value);
+       if (!strcmp(var, "format.signaturefile"))
+               return git_config_pathname(&signature_file, var, value);
        if (!strcmp(var, "format.coverletter")) {
                if (value && !strcasecmp(value, "auto")) {
                        config_cover_letter = COVER_AUTO;
@@ -844,8 +846,13 @@ static void gen_message_id(struct rev_info *info, char *base)
 
 static void print_signature(void)
 {
-       if (signature && *signature)
-               printf("-- \n%s\n\n", signature);
+       if (!signature || !*signature)
+               return;
+
+       printf("-- \n%s", signature);
+       if (signature[strlen(signature)-1] != '\n')
+               putchar('\n');
+       putchar('\n');
 }
 
 static void add_branch_description(struct strbuf *buf, const char *branch_name)
@@ -856,9 +863,10 @@ static void add_branch_description(struct strbuf *buf, const char *branch_name)
        read_branch_desc(&desc, branch_name);
        if (desc.len) {
                strbuf_addch(buf, '\n');
-               strbuf_add(buf, desc.buf, desc.len);
+               strbuf_addbuf(buf, &desc);
                strbuf_addch(buf, '\n');
        }
+       strbuf_release(&desc);
 }
 
 static char *find_branch_name(struct rev_info *rev)
@@ -866,7 +874,7 @@ static char *find_branch_name(struct rev_info *rev)
        int i, positive = -1;
        unsigned char branch_sha1[20];
        const unsigned char *tip_sha1;
-       const char *ref;
+       const char *ref, *v;
        char *full_ref, *branch = NULL;
 
        for (i = 0; i < rev->cmdline.nr; i++) {
@@ -882,9 +890,9 @@ static char *find_branch_name(struct rev_info *rev)
        ref = rev->cmdline.rev[positive].name;
        tip_sha1 = rev->cmdline.rev[positive].item->sha1;
        if (dwim_ref(ref, strlen(ref), branch_sha1, &full_ref) &&
-           starts_with(full_ref, "refs/heads/") &&
+           skip_prefix(full_ref, "refs/heads/", &v) &&
            !hashcmp(tip_sha1, branch_sha1))
-               branch = xstrdup(full_ref + strlen("refs/heads/"));
+               branch = xstrdup(v);
        free(full_ref);
        return branch;
 }
@@ -919,9 +927,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
        log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
                                &need_8bit_cte);
 
-       for (i = 0; !need_8bit_cte && i < nr; i++)
-               if (has_non_ascii(list[i]->buffer))
+       for (i = 0; !need_8bit_cte && i < nr; i++) {
+               const char *buf = get_commit_buffer(list[i], NULL);
+               if (has_non_ascii(buf))
                        need_8bit_cte = 1;
+               unuse_commit_buffer(list[i], buf);
+       }
 
        if (!branch_name)
                branch_name = find_branch_name(rev);
@@ -1230,6 +1241,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                            PARSE_OPT_OPTARG, thread_callback },
                OPT_STRING(0, "signature", &signature, N_("signature"),
                            N_("add a signature")),
+               OPT_FILENAME(0, "signature-file", &signature_file,
+                               N_("add a signature from a file")),
                OPT__QUIET(&quiet, N_("don't print the patch filenames")),
                OPT_END()
        };
@@ -1386,10 +1399,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 
                if (check_head) {
                        unsigned char sha1[20];
-                       const char *ref;
-                       ref = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
-                       if (ref && starts_with(ref, "refs/heads/"))
-                               branch_name = xstrdup(ref + strlen("refs/heads/"));
+                       const char *ref, *v;
+                       ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
+                                                sha1, NULL);
+                       if (ref && skip_prefix(ref, "refs/heads/", &v))
+                               branch_name = xstrdup(v);
                        else
                                branch_name = xstrdup(""); /* no branch */
                }
@@ -1429,7 +1443,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                        continue;
 
                nr++;
-               list = xrealloc(list, nr * sizeof(list[0]));
+               REALLOC_ARRAY(list, nr);
                list[nr - 1] = commit;
        }
        if (nr == 0)
@@ -1447,6 +1461,18 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                        cover_letter = (config_cover_letter == COVER_ON);
        }
 
+       if (!signature) {
+               ; /* --no-signature inhibits all signatures */
+       } else if (signature && signature != git_version_string) {
+               ; /* non-default signature already set */
+       } else if (signature_file) {
+               struct strbuf buf = STRBUF_INIT;
+
+               if (strbuf_read_file(&buf, signature_file, 128) < 0)
+                       die_errno(_("unable to read signature file '%s'"), signature_file);
+               signature = strbuf_detach(&buf, NULL);
+       }
+
        if (in_reply_to || thread || cover_letter)
                rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
        if (in_reply_to) {
@@ -1508,8 +1534,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                    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);
-               commit->buffer = NULL;
+               free_commit_buffer(commit);
 
                /* We put one extra blank line between formatted
                 * patches and this flag is used by log-tree code