From 8420ccd8b884e1edceca9ea5824f3ff300c0c4ba Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 16 Feb 2010 23:59:46 -0800 Subject: [PATCH 1/6] git_config_maybe_bool() Some configuration variables can take boolean values in addition to enumeration specific to them. Introduce git_config_maybe_bool() that returns 0 or 1 if the given value is boolean, or -1 if not, so that a parser for such a variable can check for boolean first and then parse other kinds of values as a fallback. Signed-off-by: Junio C Hamano --- cache.h | 1 + config.c | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/cache.h b/cache.h index d478eff1f3..dd3be0a065 100644 --- a/cache.h +++ b/cache.h @@ -924,6 +924,7 @@ extern int git_config_int(const char *, const char *); extern unsigned long git_config_ulong(const char *, const char *); extern int git_config_bool_or_int(const char *, const char *, int *); extern int git_config_bool(const char *, const char *); +extern int git_config_maybe_bool(const char *, const char *); extern int git_config_string(const char **, const char *, const char *); extern int git_config_pathname(const char **, const char *, const char *); extern int git_config_set(const char *, const char *); diff --git a/config.c b/config.c index 6963fbea43..64e41bea22 100644 --- a/config.c +++ b/config.c @@ -322,17 +322,30 @@ unsigned long git_config_ulong(const char *name, const char *value) return ret; } -int git_config_bool_or_int(const char *name, const char *value, int *is_bool) +int git_config_maybe_bool(const char *name, const char *value) { - *is_bool = 1; if (!value) return 1; if (!*value) return 0; - if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on")) + if (!strcasecmp(value, "true") + || !strcasecmp(value, "yes") + || !strcasecmp(value, "on")) return 1; - if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off")) + if (!strcasecmp(value, "false") + || !strcasecmp(value, "no") + || !strcasecmp(value, "off")) return 0; + return -1; +} + +int git_config_bool_or_int(const char *name, const char *value, int *is_bool) +{ + int v = git_config_maybe_bool(name, value); + if (0 <= v) { + *is_bool = 1; + return v; + } *is_bool = 0; return git_config_int(name, value); } From eb734454098fb68af1fb0e157dd5e67bb15a602d Mon Sep 17 00:00:00 2001 From: Steven Drake Date: Wed, 17 Feb 2010 12:39:52 +1300 Subject: [PATCH 2/6] Add `log.decorate' configuration variable. This alows the 'git-log --decorate' to be enabled by default so that normal log outout contains ant ref names of commits that are shown. Signed-off-by: Steven Drake Signed-off-by: Junio C Hamano --- Documentation/config.txt | 7 +++++++ builtin-log.c | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 4c36aa95b7..db280326de 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1232,6 +1232,13 @@ log.date:: following alternatives: {relative,local,default,iso,rfc,short}. See linkgit:git-log[1]. +log.decorate:: + Print out the ref names of any commits that are shown by the log + command. If 'short' is specified, the ref name prefixes 'refs/heads/', + 'refs/tags/' and 'refs/remotes/' will not be printed. If 'full' is + specified, the full ref name (including prefix) will be printed. + This is the same as the log commands '--decorate' option. + log.showroot:: If true, the initial commit will be shown as a big creation event. This is equivalent to a diff against an empty tree. diff --git a/builtin-log.c b/builtin-log.c index 8d16832f7e..3100dc00a8 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -24,6 +24,7 @@ static const char *default_date_mode = NULL; static int default_show_root = 1; +static int decoration_style = 0; static const char *fmt_patch_subject_prefix = "PATCH"; static const char *fmt_pretty; @@ -35,7 +36,6 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { int i; - int decoration_style = 0; rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; @@ -252,6 +252,13 @@ static int git_log_config(const char *var, const char *value, void *cb) return git_config_string(&fmt_patch_subject_prefix, var, value); if (!strcmp(var, "log.date")) return git_config_string(&default_date_mode, var, value); + if (!strcmp(var, "log.decorate")) { + if (!strcmp(value, "full")) + decoration_style = DECORATE_FULL_REFS; + else if (!strcmp(value, "short")) + decoration_style = DECORATE_SHORT_REFS; + return 0; + } if (!strcmp(var, "log.showroot")) { default_show_root = git_config_bool(var, value); return 0; From 8a3d203bd02bec48a02557961899d81da172fa23 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 17 Feb 2010 10:20:49 -0800 Subject: [PATCH 3/6] log.decorate: usability fixes The configuration is meant to suppliment --decorate command line option that can be used as a boolean to turn the feature on, so it is natural to expect [log] decorate decorate = yes to work. The original commit would segfault with the first one, and would not understand the second one. Once a user has this configuration in ~/.gitconfig, there needs to be a way to override it from the command line. Add --no-decorate option to log family and also allow --decorate=no to mean the same thing. Since we allow setting log.decorate to 'true', the command line also should accept --decorate=yes and behave accordingly. New tests in t4202 are designed to exercise the interaction between the configuration variable and the command line option that overrides it. Signed-off-by: Junio C Hamano --- Documentation/git-log.txt | 3 ++- builtin-log.c | 35 ++++++++++++++++++++-------- t/t4202-log.sh | 49 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 0e39bb61ee..64bb879fed 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -37,7 +37,8 @@ include::diff-options.txt[] and , see "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1]. ---decorate[=short|full]:: +--no-decorate:: +--decorate[=short|full|no]:: Print out the ref names of any commits that are shown. If 'short' is specified, the ref name prefixes 'refs/heads/', 'refs/tags/' and 'refs/remotes/' will not be printed. If 'full' is specified, the diff --git a/builtin-log.c b/builtin-log.c index 3100dc00a8..0afba31c1f 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -24,7 +24,7 @@ static const char *default_date_mode = NULL; static int default_show_root = 1; -static int decoration_style = 0; +static int decoration_style; static const char *fmt_patch_subject_prefix = "PATCH"; static const char *fmt_pretty; @@ -32,6 +32,23 @@ static const char * const builtin_log_usage = "git log [] [..] [[--] ...]\n" " or: git show [options] ..."; +static int parse_decoration_style(const char *var, const char *value) +{ + switch (git_config_maybe_bool(var, value)) { + case 1: + return DECORATE_SHORT_REFS; + case 0: + return 0; + default: + break; + } + if (!strcmp(value, "full")) + return DECORATE_FULL_REFS; + else if (!strcmp(value, "short")) + return DECORATE_SHORT_REFS; + return -1; +} + static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { @@ -74,12 +91,11 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, decoration_style = DECORATE_SHORT_REFS; } else if (!prefixcmp(arg, "--decorate=")) { const char *v = skip_prefix(arg, "--decorate="); - if (!strcmp(v, "full")) - decoration_style = DECORATE_FULL_REFS; - else if (!strcmp(v, "short")) - decoration_style = DECORATE_SHORT_REFS; - else + decoration_style = parse_decoration_style(arg, v); + if (decoration_style < 0) die("invalid --decorate option: %s", arg); + } else if (!strcmp(arg, "--no-decorate")) { + decoration_style = 0; } else if (!strcmp(arg, "--source")) { rev->show_source = 1; } else if (!strcmp(arg, "-h")) { @@ -253,10 +269,9 @@ static int git_log_config(const char *var, const char *value, void *cb) if (!strcmp(var, "log.date")) return git_config_string(&default_date_mode, var, value); if (!strcmp(var, "log.decorate")) { - if (!strcmp(value, "full")) - decoration_style = DECORATE_FULL_REFS; - else if (!strcmp(value, "short")) - decoration_style = DECORATE_SHORT_REFS; + decoration_style = parse_decoration_style(var, value); + if (decoration_style < 0) + decoration_style = 0; /* maybe warn? */ return 0; } if (!strcmp(var, "log.showroot")) { diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 1dc224f6fb..2230e606ed 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -387,5 +387,54 @@ test_expect_success 'log --graph with merge' ' test_cmp expect actual ' +test_expect_success 'log.decorate configuration' ' + git config --unset-all log.decorate || : + + git log --oneline >expect.none && + git log --oneline --decorate >expect.short && + git log --oneline --decorate=full >expect.full && + + echo "[log] decorate" >>.git/config && + git log --oneline >actual && + test_cmp expect.short actual && + + git config --unset-all log.decorate && + git config log.decorate true && + git log --oneline >actual && + test_cmp expect.short actual && + git log --oneline --decorate=full >actual && + test_cmp expect.full actual && + git log --oneline --decorate=no >actual && + test_cmp expect.none actual && + + git config --unset-all log.decorate && + git config log.decorate no && + git log --oneline >actual && + test_cmp expect.none actual && + git log --oneline --decorate >actual && + test_cmp expect.short actual && + git log --oneline --decorate=full >actual && + test_cmp expect.full actual && + + git config --unset-all log.decorate && + git config log.decorate short && + git log --oneline >actual && + test_cmp expect.short actual && + git log --oneline --no-decorate >actual && + test_cmp expect.none actual && + git log --oneline --decorate=full >actual && + test_cmp expect.full actual && + + git config --unset-all log.decorate && + git config log.decorate full && + git log --oneline >actual && + test_cmp expect.full actual && + git log --oneline --no-decorate >actual && + test_cmp expect.none actual && + git log --oneline --decorate >actual && + test_cmp expect.short actual + +' + test_done From 635530a2fcd4bb3714452403f341f1317ae9c9f6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 6 Apr 2010 14:48:55 -0700 Subject: [PATCH 4/6] log --pretty/--oneline: ignore log.decorate Many scripts, most notably gitk, rely on output from the log family of command not to be molested by random user configuration. This is especially true when --pretty=raw is given. Just like we disable notes output unless the command line explicitly asks for --show-notes, disable the decoration code unless --decorate is given explicitly from the command line and --pretty or --oneline is given. Signed-off-by: Junio C Hamano --- builtin-log.c | 11 +++++++++++ t/t4202-log.sh | 44 ++++++++++++++++++++++++++++---------------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/builtin-log.c b/builtin-log.c index 0afba31c1f..7f4186f19e 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -53,6 +53,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { int i; + int decoration_given = 0; rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; @@ -89,11 +90,13 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, 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")) { decoration_style = 0; } else if (!strcmp(arg, "--source")) { @@ -103,6 +106,14 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, } else die("unrecognized argument: %s", arg); } + + /* + * defeat log.decorate configuration interacting with --pretty + * from the command line. + */ + if (!decoration_given && rev->pretty_given) + decoration_style = 0; + if (decoration_style) { rev->show_decorations = 1; load_ref_decorations(decoration_style); diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 2230e606ed..166de4479c 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -390,50 +390,62 @@ test_expect_success 'log --graph with merge' ' test_expect_success 'log.decorate configuration' ' git config --unset-all log.decorate || : - git log --oneline >expect.none && - git log --oneline --decorate >expect.short && - git log --oneline --decorate=full >expect.full && + git log >expect.none && + git log --decorate >expect.short && + git log --decorate=full >expect.full && + git log --oneline >expect.oneline && echo "[log] decorate" >>.git/config && - git log --oneline >actual && + git log >actual && test_cmp expect.short actual && + git log --oneline >actual && + test_cmp expect.oneline actual && git config --unset-all log.decorate && git config log.decorate true && - git log --oneline >actual && + git log >actual && test_cmp expect.short actual && - git log --oneline --decorate=full >actual && + git log --decorate=full >actual && test_cmp expect.full actual && - git log --oneline --decorate=no >actual && + git log --decorate=no >actual && test_cmp expect.none actual && + git log --oneline >actual && + test_cmp expect.oneline actual && git config --unset-all log.decorate && git config log.decorate no && - git log --oneline >actual && + git log >actual && test_cmp expect.none actual && - git log --oneline --decorate >actual && + git log --decorate >actual && test_cmp expect.short actual && - git log --oneline --decorate=full >actual && + git log --decorate=full >actual && test_cmp expect.full actual && + git log --oneline >actual && + test_cmp expect.oneline actual && git config --unset-all log.decorate && git config log.decorate short && - git log --oneline >actual && + git log >actual && test_cmp expect.short actual && - git log --oneline --no-decorate >actual && + git log --no-decorate >actual && test_cmp expect.none actual && - git log --oneline --decorate=full >actual && + git log --decorate=full >actual && test_cmp expect.full actual && + git log --oneline >actual && + test_cmp expect.oneline actual && git config --unset-all log.decorate && git config log.decorate full && - git log --oneline >actual && + git log >actual && test_cmp expect.full actual && - git log --oneline --no-decorate >actual && + git log --no-decorate >actual && test_cmp expect.none actual && - git log --oneline --decorate >actual && + git log --decorate >actual && test_cmp expect.short actual + git log --oneline >actual && + test_cmp expect.oneline actual && + : ' test_done From b0e621adfd5a60b7cbe95e59f09c87f0870321cb Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 8 Apr 2010 15:42:37 -0400 Subject: [PATCH 5/6] script with rev-list instead of log Because log.decorate now shows decorations for --pretty=oneline, we must explicitly turn it off when scripting. Otherwise, users with log.decorate set will get cruft like: $ git stash Saved working directory and index state WIP on master: 2c1f7f5 (HEAD, master) commit subject Instead of adding --no-decorate to the log command line, let's just use the rev-list plumbing interface instead, which does the right thing. git-submodule has a similar call. Since it just counts the commit lines, nothing is broken, but let's switch it, too, for the sake of consistency and cleanliness. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- git-stash.sh | 2 +- git-submodule.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/git-stash.sh b/git-stash.sh index 3a0685f189..0726a4a725 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -57,7 +57,7 @@ create_stash () { # state of the base commit if b_commit=$(git rev-parse --verify HEAD) then - head=$(git log --no-color --abbrev-commit --pretty=oneline -n 1 HEAD --) + head=$(git rev-list --oneline -n 1 HEAD --) else die "You do not have the initial commit yet" fi diff --git a/git-submodule.sh b/git-submodule.sh index 664f21721c..c8d80822c2 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -643,7 +643,7 @@ cmd_summary() { range=$sha1_dst fi GIT_DIR="$name/.git" \ - git log --pretty=oneline --first-parent $range | wc -l + git rev-list --first-parent $range -- | wc -l ) total_commits=" ($(($total_commits + 0)))" ;; From 4f62c2bc577bbb85b65f3261c7fab7ef74def4cd Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 8 Apr 2010 10:17:17 -0700 Subject: [PATCH 6/6] log.decorate: only ignore it under "log --pretty=raw" Unlike notes that are often multi-line and disrupting to be placed in many output formats, a decoration is designed to be a small token that can be tacked after an existing line of the output where a commit object name sits. Disabling log.decorate for something like "log --oneline" would defeat the purpose of the configuration. We _might_ want to change it further in the future to force scripts that do not want to be broken by random end user configurations to explicitly say "log --no-decorate", but that would be an incompatible change that needs the usual multi-release-cycle deprecation process. Signed-off-by: Junio C Hamano --- builtin-log.c | 5 +++-- t/t4202-log.sh | 60 ++++++++++++++++++++------------------------------ 2 files changed, 27 insertions(+), 38 deletions(-) diff --git a/builtin-log.c b/builtin-log.c index 7f4186f19e..017fcf82ce 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -108,10 +108,11 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, } /* - * defeat log.decorate configuration interacting with --pretty + * defeat log.decorate configuration interacting with --pretty=raw * from the command line. */ - if (!decoration_given && rev->pretty_given) + if (!decoration_given && rev->pretty_given + && rev->commit_format == CMIT_FMT_RAW) decoration_style = 0; if (decoration_style) { diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 166de4479c..2230e606ed 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -390,62 +390,50 @@ test_expect_success 'log --graph with merge' ' test_expect_success 'log.decorate configuration' ' git config --unset-all log.decorate || : - git log >expect.none && - git log --decorate >expect.short && - git log --decorate=full >expect.full && - git log --oneline >expect.oneline && + git log --oneline >expect.none && + git log --oneline --decorate >expect.short && + git log --oneline --decorate=full >expect.full && echo "[log] decorate" >>.git/config && - git log >actual && - test_cmp expect.short actual && git log --oneline >actual && - test_cmp expect.oneline actual && + test_cmp expect.short actual && git config --unset-all log.decorate && git config log.decorate true && - git log >actual && - test_cmp expect.short actual && - git log --decorate=full >actual && - test_cmp expect.full actual && - git log --decorate=no >actual && - test_cmp expect.none actual && git log --oneline >actual && - test_cmp expect.oneline actual && + test_cmp expect.short actual && + git log --oneline --decorate=full >actual && + test_cmp expect.full actual && + git log --oneline --decorate=no >actual && + test_cmp expect.none actual && git config --unset-all log.decorate && git config log.decorate no && - git log >actual && - test_cmp expect.none actual && - git log --decorate >actual && - test_cmp expect.short actual && - git log --decorate=full >actual && - test_cmp expect.full actual && git log --oneline >actual && - test_cmp expect.oneline actual && + test_cmp expect.none actual && + git log --oneline --decorate >actual && + test_cmp expect.short actual && + git log --oneline --decorate=full >actual && + test_cmp expect.full actual && git config --unset-all log.decorate && git config log.decorate short && - git log >actual && - test_cmp expect.short actual && - git log --no-decorate >actual && - test_cmp expect.none actual && - git log --decorate=full >actual && - test_cmp expect.full actual && git log --oneline >actual && - test_cmp expect.oneline actual && + test_cmp expect.short actual && + git log --oneline --no-decorate >actual && + test_cmp expect.none actual && + git log --oneline --decorate=full >actual && + test_cmp expect.full actual && git config --unset-all log.decorate && git config log.decorate full && - git log >actual && - test_cmp expect.full actual && - git log --no-decorate >actual && - test_cmp expect.none actual && - git log --decorate >actual && - test_cmp expect.short actual git log --oneline >actual && - test_cmp expect.oneline actual && + test_cmp expect.full actual && + git log --oneline --no-decorate >actual && + test_cmp expect.none actual && + git log --oneline --decorate >actual && + test_cmp expect.short actual - : ' test_done