Merge branch 'jk/haves-from-alternate-odb'
[gitweb.git] / builtin / log.c
index c6dce9b8950410b08e13c11aa940404a7fcd2b78..27849dc91de03a46d4c9357ca0d7b3f79188cc98 100644 (file)
 /* Set a default date-time format for git log ("log.date" config variable) */
 static const char *default_date_mode = NULL;
 
+static int default_abbrev_commit;
 static int default_show_root = 1;
 static int decoration_style;
+static int decoration_given;
 static const char *fmt_patch_subject_prefix = "PATCH";
 static const char *fmt_pretty;
 
-static const char * const builtin_log_usage =
+static const char * const builtin_log_usage[] = {
        "git log [<options>] [<since>..<until>] [[--] <path>...]\n"
-       "   or: git show [options] <object>...";
+       "   or: git show [options] <object>...",
+       NULL
+};
 
 static int parse_decoration_style(const char *var, const char *value)
 {
@@ -49,6 +53,23 @@ static int parse_decoration_style(const char *var, const char *value)
        return -1;
 }
 
+static int decorate_callback(const struct option *opt, const char *arg, int unset)
+{
+       if (unset)
+               decoration_style = 0;
+       else if (arg)
+               decoration_style = parse_decoration_style("command line", arg);
+       else
+               decoration_style = DECORATE_SHORT_REFS;
+
+       if (decoration_style < 0)
+               die("invalid --decorate option: %s", arg);
+
+       decoration_given = 1;
+
+       return 0;
+}
+
 static void cmd_log_init_defaults(struct rev_info *rev)
 {
        rev->abbrev = DEFAULT_ABBREV;
@@ -57,6 +78,7 @@ static void cmd_log_init_defaults(struct rev_info *rev)
                get_commit_format(fmt_pretty, rev);
        rev->verbose_header = 1;
        DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
+       rev->abbrev_commit = default_abbrev_commit;
        rev->show_root_diff = default_show_root;
        rev->subject_prefix = fmt_patch_subject_prefix;
        DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);
@@ -68,17 +90,28 @@ static void cmd_log_init_defaults(struct rev_info *rev)
 static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
                         struct rev_info *rev, struct setup_revision_opt *opt)
 {
-       int i;
-       int decoration_given = 0;
        struct userformat_want w;
-       /*
-        * Check for -h before setup_revisions(), or "git log -h" will
-        * fail when run without a git directory.
-        */
-       if (argc == 2 && !strcmp(argv[1], "-h"))
-               usage(builtin_log_usage);
+       int quiet = 0, source = 0;
+
+       const struct option builtin_log_options[] = {
+               OPT_BOOLEAN(0, "quiet", &quiet, "suppress diff output"),
+               OPT_BOOLEAN(0, "source", &source, "show source"),
+               { OPTION_CALLBACK, 0, "decorate", NULL, NULL, "decorate options",
+                 PARSE_OPT_OPTARG, decorate_callback},
+               OPT_END()
+       };
+
+       argc = parse_options(argc, argv, prefix,
+                            builtin_log_options, builtin_log_usage,
+                            PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
+                            PARSE_OPT_KEEP_DASHDASH);
+
        argc = setup_revisions(argc, argv, rev, opt);
 
+       /* Any arguments at this point are not recognized */
+       if (argc > 1)
+               die("unrecognized argument: %s", argv[1]);
+
        memset(&w, 0, sizeof(w));
        userformat_find_requirements(NULL, &w);
 
@@ -94,35 +127,21 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
                if (rev->diffopt.pathspec.nr != 1)
                        usage("git logs can only follow renames on one pathname at a time");
        }
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
-               if (!strcmp(arg, "--decorate")) {
-                       decoration_style = DECORATE_SHORT_REFS;
-                       decoration_given = 1;
-               } else if (!prefixcmp(arg, "--decorate=")) {
-                       const char *v = skip_prefix(arg, "--decorate=");
-                       decoration_style = parse_decoration_style(arg, v);
-                       if (decoration_style < 0)
-                               die(_("invalid --decorate option: %s"), arg);
-                       decoration_given = 1;
-               } else if (!strcmp(arg, "--no-decorate")) {
+
+       if (source)
+               rev->show_source = 1;
+
+       if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {
+               /*
+                * "log --pretty=raw" is special; ignore UI oriented
+                * configuration variables such as decoration.
+                */
+               if (!decoration_given)
                        decoration_style = 0;
-               } else if (!strcmp(arg, "--source")) {
-                       rev->show_source = 1;
-               } else if (!strcmp(arg, "-h")) {
-                       usage(builtin_log_usage);
-               } else
-                       die(_("unrecognized argument: %s"), arg);
+               if (!rev->abbrev_commit_given)
+                       rev->abbrev_commit = 0;
        }
 
-       /*
-        * defeat log.decorate configuration interacting with --pretty=raw
-        * from the command line.
-        */
-       if (!decoration_given && rev->pretty_given
-           && rev->commit_format == CMIT_FMT_RAW)
-               decoration_style = 0;
-
        if (decoration_style) {
                rev->show_decorations = 1;
                load_ref_decorations(decoration_style);
@@ -256,6 +275,8 @@ static void finish_early_output(struct rev_info *rev)
 static int cmd_log_walk(struct rev_info *rev)
 {
        struct commit *commit;
+       int saved_nrl = 0;
+       int saved_dcctc = 0;
 
        if (rev->early_output)
                setup_early_output(rev);
@@ -286,7 +307,14 @@ static int cmd_log_walk(struct rev_info *rev)
                }
                free_commit_list(commit->parents);
                commit->parents = NULL;
+               if (saved_nrl < rev->diffopt.needed_rename_limit)
+                       saved_nrl = rev->diffopt.needed_rename_limit;
+               if (rev->diffopt.degraded_cc_to_c)
+                       saved_dcctc = 1;
        }
+       rev->diffopt.degraded_cc_to_c = saved_dcctc;
+       rev->diffopt.needed_rename_limit = saved_nrl;
+
        if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
            DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) {
                return 02;
@@ -300,6 +328,10 @@ static int git_log_config(const char *var, const char *value, void *cb)
                return git_config_string(&fmt_pretty, var, value);
        if (!strcmp(var, "format.subjectprefix"))
                return git_config_string(&fmt_patch_subject_prefix, var, value);
+       if (!strcmp(var, "log.abbrevcommit")) {
+               default_abbrev_commit = git_config_bool(var, value);
+               return 0;
+       }
        if (!strcmp(var, "log.date"))
                return git_config_string(&default_date_mode, var, value);
        if (!strcmp(var, "log.decorate")) {
@@ -405,6 +437,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
        struct rev_info rev;
        struct object_array_entry *objects;
        struct setup_revision_opt opt;
+       struct pathspec match_all;
        int i, count, ret = 0;
 
        git_config(git_log_config, NULL);
@@ -412,6 +445,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
        if (diff_use_color_default == -1)
                diff_use_color_default = git_use_color_default;
 
+       init_pathspec(&match_all, NULL);
        init_revisions(&rev, prefix);
        rev.diff = 1;
        rev.always_show_header = 1;
@@ -458,7 +492,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
                                        diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
                                        name,
                                        diff_get_color_opt(&rev.diffopt, DIFF_RESET));
-                       read_tree_recursive((struct tree *)o, "", 0, 0, NULL,
+                       read_tree_recursive((struct tree *)o, "", 0, 0, &match_all,
                                        show_tree_object, NULL);
                        rev.shown_one = 1;
                        break;
@@ -491,11 +525,11 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix)
 
        init_revisions(&rev, prefix);
        init_reflog_walk(&rev.reflog_info);
-       rev.abbrev_commit = 1;
        rev.verbose_header = 1;
        memset(&opt, 0, sizeof(opt));
        opt.def = "HEAD";
        cmd_log_init_defaults(&rev);
+       rev.abbrev_commit = 1;
        rev.commit_format = CMIT_FMT_ONELINE;
        rev.use_terminator = 1;
        rev.always_show_header = 1;