From 36daaaca0046542f4d5576ad5766ac55f43e3fc3 Mon Sep 17 00:00:00 2001 From: Jehan Bing Date: Thu, 16 Feb 2012 17:19:03 -0800 Subject: Add a setting to require a filter to be successful By default, a missing filter driver or a failure from the filter driver is not an error, but merely makes the filter operation a no-op pass through. This is useful to massage the content into a shape that is more convenient for the platform, filesystem, and the user to use, and the content filter mechanism is not used to turn something unusable into usable. However, we could also use of the content filtering mechanism and store the content that cannot be directly used in the repository (e.g. a UUID that refers to the true content stored outside git, or an encrypted content) and turn it into a usable form upon checkout (e.g. download the external content, or decrypt the encrypted content). For such a use case, the content cannot be used when filter driver fails, and we need a way to tell Git to abort the whole operation for such a failing or missing filter driver. Add a new "filter..required" configuration variable to mark the second use case. When it is set, git will abort the operation when the filter driver does not exist or exits with a non-zero status code. Signed-off-by: Jehan Bing Signed-off-by: Junio C Hamano diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index a85b187..80120ea 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -294,16 +294,27 @@ output is used to update the worktree file. Similarly, the `clean` command is used to convert the contents of worktree file upon checkin. -A missing filter driver definition in the config is not an error -but makes the filter a no-op passthru. - -The content filtering is done to massage the content into a -shape that is more convenient for the platform, filesystem, and -the user to use. The key phrase here is "more convenient" and not -"turning something unusable into usable". In other words, the -intent is that if someone unsets the filter driver definition, -or does not have the appropriate filter program, the project -should still be usable. +One use of the content filtering is to massage the content into a shape +that is more convenient for the platform, filesystem, and the user to use. +For this mode of operation, the key phrase here is "more convenient" and +not "turning something unusable into usable". In other words, the intent +is that if someone unsets the filter driver definition, or does not have +the appropriate filter program, the project should still be usable. + +Another use of the content filtering is to store the content that cannot +be directly used in the repository (e.g. a UUID that refers to the true +content stored outside git, or an encrypted content) and turn it into a +usable form upon checkout (e.g. download the external content, or decrypt +the encrypted content). + +These two filters behave differently, and by default, a filter is taken as +the former, massaging the contents into more convenient shape. A missing +filter driver definition in the config, or a filter driver that exits with +a non-zero status, is not an error but makes the filter a no-op passthru. + +You can declare that a filter turns a content that by itself is unusable +into a usable content by setting the filter..required configuration +variable to `true`. For example, in .gitattributes, you would assign the `filter` attribute for paths. @@ -335,6 +346,16 @@ input that is already correctly indented. In this case, the lack of a smudge filter means that the clean filter _must_ accept its own output without modifying it. +If a filter _must_ succeed in order to make the stored contents usable, +you can declare that the filter is `required`, in the configuration: + +------------------------ +[filter "crypt"] + clean = openssl enc ... + smudge = openssl enc -d ... + required +------------------------ + Sequence "%f" on the filter command line is replaced with the name of the file the filter is working on. A filter might use this in keyword substitution. For example: diff --git a/convert.c b/convert.c index 12868ed..c06309f 100644 --- a/convert.c +++ b/convert.c @@ -429,6 +429,7 @@ static struct convert_driver { struct convert_driver *next; const char *smudge; const char *clean; + int required; } *user_convert, **user_convert_tail; static int read_convert_config(const char *var, const char *value, void *cb) @@ -472,6 +473,11 @@ static int read_convert_config(const char *var, const char *value, void *cb) if (!strcmp("clean", ep)) return git_config_string(&drv->clean, var, value); + if (!strcmp("required", ep)) { + drv->required = git_config_bool(var, value); + return 0; + } + return 0; } @@ -747,13 +753,19 @@ int convert_to_git(const char *path, const char *src, size_t len, { int ret = 0; const char *filter = NULL; + int required = 0; struct conv_attrs ca; convert_attrs(&ca, path); - if (ca.drv) + if (ca.drv) { filter = ca.drv->clean; + required = ca.drv->required; + } ret |= apply_filter(path, src, len, dst, filter); + if (!ret && required) + die("%s: clean filter '%s' failed", path, ca.drv->name); + if (ret) { src = dst->buf; len = dst->len; @@ -771,13 +783,16 @@ static int convert_to_working_tree_internal(const char *path, const char *src, size_t len, struct strbuf *dst, int normalizing) { - int ret = 0; + int ret = 0, ret_filter = 0; const char *filter = NULL; + int required = 0; struct conv_attrs ca; convert_attrs(&ca, path); - if (ca.drv) + if (ca.drv) { filter = ca.drv->smudge; + required = ca.drv->required; + } ret |= ident_to_worktree(path, src, len, dst, ca.ident); if (ret) { @@ -796,7 +811,12 @@ static int convert_to_working_tree_internal(const char *path, const char *src, len = dst->len; } } - return ret | apply_filter(path, src, len, dst, filter); + + ret_filter = apply_filter(path, src, len, dst, filter); + if (!ret_filter && required) + die("%s: smudge filter %s failed", path, ca.drv->name); + + return ret | ret_filter; } int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst) diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index f19e651..e50f0f7 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -153,4 +153,41 @@ test_expect_success 'filter shell-escaped filenames' ' : ' +test_expect_success 'required filter success' ' + git config filter.required.smudge cat && + git config filter.required.clean cat && + git config filter.required.required true && + + echo "*.r filter=required" >.gitattributes && + + echo test >test.r && + git add test.r && + rm -f test.r && + git checkout -- test.r +' + +test_expect_success 'required filter smudge failure' ' + git config filter.failsmudge.smudge false && + git config filter.failsmudge.clean cat && + git config filter.failsmudge.required true && + + echo "*.fs filter=failsmudge" >.gitattributes && + + echo test >test.fs && + git add test.fs && + rm -f test.fs && + test_must_fail git checkout -- test.fs +' + +test_expect_success 'required filter clean failure' ' + git config filter.failclean.smudge cat && + git config filter.failclean.clean false && + git config filter.failclean.required true && + + echo "*.fc filter=failclean" >.gitattributes && + + echo test >test.fc && + test_must_fail git add test.fc +' + test_done -- cgit v0.10.2-6-g49f6 From ed727b192bb3506ee7904c1c9e8370d6b4ecaf5d Mon Sep 17 00:00:00 2001 From: Phil Hord Date: Tue, 21 Feb 2012 19:44:17 -0500 Subject: cherry-pick: No advice to commit if --no-commit When cherry-pick fails it offers a helpful hint about how to proceed. The hint tells the user how to do the cleanup needed by the conflicted cherry-pick and finish the job after conflict resolution. In case of cherry-pick --no-commit, the hint goes too far. It tells the user to finish up with 'git commit'. That is not what this git-cherry-pick was trying to do in the first place. Restrict the hint in case of --no-commit to avoid giving this extra advice. Also, add a test verifying the reduced hint for the --no-commit version of cherry-pick. Signed-off-by: Phil Hord Acked-by: Jonathan Nieder Signed-off-by: Junio C Hamano diff --git a/sequencer.c b/sequencer.c index 5fcbcb8..a37846a 100644 --- a/sequencer.c +++ b/sequencer.c @@ -123,7 +123,7 @@ static void write_cherry_pick_head(struct commit *commit, const char *pseudoref) strbuf_release(&buf); } -static void print_advice(int show_hint) +static void print_advice(int show_hint, struct replay_opts *opts) { char *msg = getenv("GIT_CHERRY_PICK_HELP"); @@ -138,10 +138,15 @@ static void print_advice(int show_hint) return; } - if (show_hint) - advise(_("after resolving the conflicts, mark the corrected paths\n" - "with 'git add ' or 'git rm '\n" - "and commit the result with 'git commit'")); + if (show_hint) { + if (opts->no_commit) + advise(_("after resolving the conflicts, mark the corrected paths\n" + "with 'git add ' or 'git rm '")); + else + advise(_("after resolving the conflicts, mark the corrected paths\n" + "with 'git add ' or 'git rm '\n" + "and commit the result with 'git commit'")); + } } static void write_message(struct strbuf *msgbuf, const char *filename) @@ -423,7 +428,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts) : _("could not apply %s... %s"), find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV), msg.subject); - print_advice(res == 1); + print_advice(res == 1, opts); rerere(opts->allow_rerere_auto); } else { if (!opts->no_commit) diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index ee1659c..0c81b3c 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -59,6 +59,20 @@ test_expect_success 'advice from failed cherry-pick' " test_i18ncmp expected actual " +test_expect_success 'advice from failed cherry-pick --no-commit' " + pristine_detach initial && + + picked=\$(git rev-parse --short picked) && + cat <<-EOF >expected && + error: could not apply \$picked... picked + hint: after resolving the conflicts, mark the corrected paths + hint: with 'git add ' or 'git rm ' + EOF + test_must_fail git cherry-pick --no-commit picked 2>actual && + + test_i18ncmp expected actual +" + test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' ' pristine_detach initial && test_must_fail git cherry-pick picked && -- cgit v0.10.2-6-g49f6 From f1c6ffe684464e7f8765030b226be108cb9c2d53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20J=C3=A4genstedt?= Date: Wed, 22 Feb 2012 09:58:10 +0100 Subject: completion: remote set-* and MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Complete only for set-url. For set-branches and set-head, complete and over the network, like e.g. git pull already does. Signed-off-by: Philip Jägenstedt Signed-off-by: Junio C Hamano diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 0acbdda..c291517 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -726,6 +726,9 @@ __git_complete_remote_or_refspec () { local cur_="$cur" cmd="${words[1]}" local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0 + if [ "$cmd" = "remote" ]; then + c=$((++c)) + fi while [ $c -lt $cword ]; do i="${words[c]}" case "$i" in @@ -776,7 +779,7 @@ __git_complete_remote_or_refspec () __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" fi ;; - pull) + pull|remote) if [ $lhs = 1 ]; then __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" else @@ -2277,7 +2280,7 @@ _git_config () _git_remote () { - local subcommands="add rename rm show prune update set-head" + local subcommands="add rename rm set-head set-branches set-url show prune update" local subcommand="$(__git_find_on_cmdline "$subcommands")" if [ -z "$subcommand" ]; then __gitcomp "$subcommands" @@ -2285,9 +2288,12 @@ _git_remote () fi case "$subcommand" in - rename|rm|show|prune) + rename|rm|set-url|show|prune) __gitcomp_nl "$(__git_remotes)" ;; + set-head|set-branches) + __git_complete_remote_or_refspec + ;; update) local i c='' IFS=$'\n' for i in $(git --git-dir="$(__gitdir)" config --get-regexp "remotes\..*" 2>/dev/null); do -- cgit v0.10.2-6-g49f6 From 6e8c755fd3fd2efab0e2dcdc16c8a17a61efa760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20J=C3=A4genstedt?= Date: Wed, 22 Feb 2012 09:58:11 +0100 Subject: completion: normalize increment/decrement style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The style used for incrementing and decrementing variables was fairly inconsistenty and was normalized to use x++, or ((x++)) in contexts where the former would otherwise be interpreted as a command. This is a bash-ism, but for obvious reasons this script is already bash-specific. Signed-off-by: Philip Jägenstedt Signed-off-by: Junio C Hamano diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index c291517..03f0b8c 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -137,7 +137,7 @@ __git_ps1_show_upstream () svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]} svn_upstream=${svn_upstream%@*} local n_stop="${#svn_remote[@]}" - for ((n=1; n <= n_stop; ++n)); do + for ((n=1; n <= n_stop; n++)); do svn_upstream=${svn_upstream#${svn_remote[$n]}} done @@ -166,10 +166,8 @@ __git_ps1_show_upstream () for commit in $commits do case "$commit" in - "<"*) let ++behind - ;; - *) let ++ahead - ;; + "<"*) ((behind++)) ;; + *) ((ahead++)) ;; esac done count="$behind $ahead" @@ -727,7 +725,7 @@ __git_complete_remote_or_refspec () local cur_="$cur" cmd="${words[1]}" local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0 if [ "$cmd" = "remote" ]; then - c=$((++c)) + ((c++)) fi while [ $c -lt $cword ]; do i="${words[c]}" @@ -746,7 +744,7 @@ __git_complete_remote_or_refspec () -*) ;; *) remote="$i"; break ;; esac - c=$((++c)) + ((c++)) done if [ -z "$remote" ]; then __gitcomp_nl "$(__git_remotes)" @@ -986,7 +984,7 @@ __git_find_on_cmdline () return fi done - c=$((++c)) + ((c++)) done } @@ -997,7 +995,7 @@ __git_has_doubledash () if [ "--" = "${words[c]}" ]; then return 0 fi - c=$((++c)) + ((c++)) done return 1 } @@ -1120,7 +1118,7 @@ _git_branch () -d|-m) only_local_ref="y" ;; -r) has_r="y" ;; esac - c=$((++c)) + ((c++)) done case "$cur" in @@ -2574,7 +2572,7 @@ _git_tag () f=1 ;; esac - c=$((++c)) + ((c++)) done case "$prev" in @@ -2627,7 +2625,7 @@ _git () --help) command="help"; break ;; *) command="$i"; break ;; esac - c=$((++c)) + ((c++)) done if [ -z "$command" ]; then -- cgit v0.10.2-6-g49f6 From 4056afbcf2d3ee3e9df2788656f3197cc363a2ee Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 22 Feb 2012 21:55:06 -0800 Subject: am -3: allow nonstandard -p option When falling back to 3-way merge, we run "git apply" to synthesize the fake ancestor tree by parsing the incoming patch, and another "git apply" to apply the patch to the fake ancestor tree. Both invocation need to be aware of the custom -p setting to parse patches that were prepared with non-standard src/dst prefix. Signed-off-by: Junio C Hamano diff --git a/git-am.sh b/git-am.sh index 1c13b13..d5d168f 100755 --- a/git-am.sh +++ b/git-am.sh @@ -127,15 +127,18 @@ fall_back_3way () { mkdir "$dotest/patch-merge-tmp-dir" # First see if the patch records the index info that we can use. - git apply --build-fake-ancestor "$dotest/patch-merge-tmp-index" \ - "$dotest/patch" && + cmd="git apply $git_apply_opt --build-fake-ancestor" && + cmd="$cmd "'"$dotest/patch-merge-tmp-index" "$dotest/patch"' && + eval "$cmd" && GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ git write-tree >"$dotest/patch-merge-base+" || cannot_fallback "$(gettext "Repository lacks necessary blobs to fall back on 3-way merge.")" say Using index info to reconstruct a base tree... - if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ - git apply --cached <"$dotest/patch" + + cmd='GIT_INDEX_FILE="$dotest/patch-merge-tmp-index"' + cmd="$cmd git apply --cached $git_apply_opt"' <"$dotest/patch"' + if eval "$cmd" then mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base" mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index" -- cgit v0.10.2-6-g49f6 From b9e63ddddc8928f39db6658bf6428a9b646e5ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sat, 25 Feb 2012 20:11:16 +0100 Subject: test-parse-options: convert to OPT_BOOL() Introduce OPT_BOOL() to test-parse-options and add some tests for these "true" boolean options. Rename OPT_BOOLEAN to OPT_COUNTUP and OPTION_BOOLEAN to OPTION_COUNTUP as well. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index a1e4616..ca25e58 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -10,7 +10,10 @@ test_description='our own option parser' cat > expect << EOF usage: test-parse-options - -b, --boolean get a boolean + --yes get a boolean + -D, --no-doubt begins with 'no-' + -B, --no-fear be brave + -b, --boolean increment by one -4, --or4 bitwise-or boolean with ...0100 --neg-or4 same as --no-or4 @@ -53,6 +56,59 @@ test_expect_success 'test help' ' mv expect expect.err +cat >expect.template <expect && + test-parse-options $* >output 2>output.err && + test ! -s output.err && + test_cmp expect output +} + +check_unknown() { + case "$1" in + --*) + echo error: unknown option \`${1#--}\' >expect ;; + -*) + echo error: unknown switch \`${1#-}\' >expect ;; + esac && + cat expect.err >>expect && + test_must_fail test-parse-options $* >output 2>output.err && + test ! -s output && + test_cmp expect output.err +} + +test_expect_success 'OPT_BOOL() #1' 'check boolean: 1 --yes' +test_expect_success 'OPT_BOOL() #2' 'check boolean: 1 --no-doubt' +test_expect_success 'OPT_BOOL() #3' 'check boolean: 1 -D' +test_expect_success 'OPT_BOOL() #4' 'check boolean: 1 --no-fear' +test_expect_success 'OPT_BOOL() #5' 'check boolean: 1 -B' + +test_expect_success 'OPT_BOOL() is idempotent #1' 'check boolean: 1 --yes --yes' +test_expect_success 'OPT_BOOL() is idempotent #2' 'check boolean: 1 -DB' + +test_expect_success 'OPT_BOOL() negation #1' 'check boolean: 0 -D --no-yes' +test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt' + +test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown --fear' +test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown --no-no-fear' + +test_expect_failure 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt' + cat > expect << EOF boolean: 2 integer: 1729 @@ -296,7 +352,7 @@ test_expect_success 'OPT_NEGBIT() works' ' test_cmp expect output ' -test_expect_success 'OPT_BOOLEAN() with PARSE_OPT_NODASH works' ' +test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' ' test-parse-options + + + + + + > output 2> output.err && test ! -s output.err && test_cmp expect output diff --git a/test-parse-options.c b/test-parse-options.c index 36487c4..3c9510a 100644 --- a/test-parse-options.c +++ b/test-parse-options.c @@ -37,7 +37,11 @@ int main(int argc, const char **argv) NULL }; struct option options[] = { - OPT_BOOLEAN('b', "boolean", &boolean, "get a boolean"), + OPT_BOOL(0, "yes", &boolean, "get a boolean"), + OPT_BOOL('D', "no-doubt", &boolean, "begins with 'no-'"), + { OPTION_SET_INT, 'B', "no-fear", &boolean, NULL, + "be brave", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 }, + OPT_COUNTUP('b', "boolean", &boolean, "increment by one"), OPT_BIT('4', "or4", &boolean, "bitwise-or boolean with ...0100", 4), OPT_NEGBIT(0, "neg-or4", &boolean, "same as --no-or4", 4), @@ -62,11 +66,11 @@ int main(int argc, const char **argv) OPT_ARGUMENT("quux", "means --quux"), OPT_NUMBER_CALLBACK(&integer, "set integer to NUM", number_callback), - { OPTION_BOOLEAN, '+', NULL, &boolean, NULL, "same as -b", + { OPTION_COUNTUP, '+', NULL, &boolean, NULL, "same as -b", PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH }, - { OPTION_BOOLEAN, 0, "ambiguous", &ambiguous, NULL, + { OPTION_COUNTUP, 0, "ambiguous", &ambiguous, NULL, "positive ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG }, - { OPTION_BOOLEAN, 0, "no-ambiguous", &ambiguous, NULL, + { OPTION_COUNTUP, 0, "no-ambiguous", &ambiguous, NULL, "negative ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG }, OPT_GROUP("Standard options"), OPT__ABBREV(&abbrev), -- cgit v0.10.2-6-g49f6 From 0f1930c58754a821bd51087ca4676e6a69cd4d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sat, 25 Feb 2012 20:14:54 +0100 Subject: parse-options: allow positivation of options starting, with no- Long options can be negated by adding no- right after the leading two dashes. This is useful e.g. to override options set by aliases. For options that are defined to start with no- already, this looks a bit funny. Allow such options to also be negated by removing the prefix. The following thirteen options are affected: apply --no-add bisect--helper --no-checkout checkout-index --no-create clone --no-checkout --no-hardlinks commit --no-verify --no-post-rewrite format-patch --no-binary hash-object --no-filters read-tree --no-sparse-checkout revert --no-commit show-branch --no-name update-ref --no-deref The following five are NOT affected because they are defined with PARSE_OPT_NONEG or the non-negated version is defined as well: branch --no-merged format-patch --no-stat --no-numbered update-index --no-assume-unchanged --no-skip-worktree Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt index 4b92514..2527b7e 100644 --- a/Documentation/technical/api-parse-options.txt +++ b/Documentation/technical/api-parse-options.txt @@ -39,7 +39,8 @@ The parse-options API allows: * Short options may be bundled, e.g. `-a -b` can be specified as `-ab`. * Boolean long options can be 'negated' (or 'unset') by prepending - `no-`, e.g. `\--no-abbrev` instead of `\--abbrev`. + `no-`, e.g. `\--no-abbrev` instead of `\--abbrev`. Conversely, + options that begin with `no-` can be 'negated' by removing it. * Options and non-option arguments can clearly be separated using the `\--` option, e.g. `-a -b \--option \-- \--this-is-a-file` indicates that diff --git a/parse-options.c b/parse-options.c index f0098eb..8906841 100644 --- a/parse-options.c +++ b/parse-options.c @@ -193,13 +193,14 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, arg_end = arg + strlen(arg); for (; options->type != OPTION_END; options++) { - const char *rest; - int flags = 0; + const char *rest, *long_name = options->long_name; + int flags = 0, opt_flags = 0; - if (!options->long_name) + if (!long_name) continue; - rest = skip_prefix(arg, options->long_name); +again: + rest = skip_prefix(arg, long_name); if (options->type == OPTION_ARGUMENT) { if (!rest) continue; @@ -212,7 +213,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, } if (!rest) { /* abbreviated? */ - if (!strncmp(options->long_name, arg, arg_end - arg)) { + if (!strncmp(long_name, arg, arg_end - arg)) { is_abbreviated: if (abbrev_option) { /* @@ -227,7 +228,7 @@ is_abbreviated: if (!(flags & OPT_UNSET) && *arg_end) p->opt = arg_end + 1; abbrev_option = options; - abbrev_flags = flags; + abbrev_flags = flags ^ opt_flags; continue; } /* negation allowed? */ @@ -239,12 +240,18 @@ is_abbreviated: goto is_abbreviated; } /* negated? */ - if (strncmp(arg, "no-", 3)) + if (prefixcmp(arg, "no-")) { + if (!prefixcmp(long_name, "no-")) { + long_name += 3; + opt_flags |= OPT_UNSET; + goto again; + } continue; + } flags |= OPT_UNSET; - rest = skip_prefix(arg + 3, options->long_name); + rest = skip_prefix(arg + 3, long_name); /* abbreviated and negated? */ - if (!rest && !prefixcmp(options->long_name, arg + 3)) + if (!rest && !prefixcmp(long_name, arg + 3)) goto is_abbreviated; if (!rest) continue; @@ -254,7 +261,7 @@ is_abbreviated: continue; p->opt = rest + 1; } - return get_value(p, options, flags); + return get_value(p, options, flags ^ opt_flags); } if (ambiguous_option) diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index ca25e58..a44bcb9 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -107,7 +107,7 @@ test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt' test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown --fear' test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown --no-no-fear' -test_expect_failure 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt' +test_expect_success 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt' cat > expect << EOF boolean: 2 -- cgit v0.10.2-6-g49f6 From 337da8d2b0b8a8a86f0aa969bba2756126d6c090 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 27 Feb 2012 02:55:19 +0100 Subject: gitweb: Introduce esc_html_match_hl and esc_html_hl_regions The esc_html_match_hl() subroutine added in this commit will be used to highlight *all* matches of given regexp, using 'match' class. Ultimately it is to be used in all match highlighting, starting with project search, which does not have it yet. It uses the esc_html_hl_regions() subroutine, which is meant to highlight in a given string a list of regions (given as a list of [ beg, end ] pairs of positions in string), using HTML element with given class. It could probably be used in other places that do highlighting of part of ready line, like highlighting of changes in a diff (diff refinement highlighting). Implementation and enhancement notes: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Currently esc_html_hl_regions() subroutine doesn't accept any parameters, like esc_html() does. We might want for example to pass nbsp=>1 to it. It can easily be done with the following code: my %opts = grep { ref($_) ne "ARRAY" } @sel; @sel = grep { ref($_) eq "ARRAY" } @sel; This allow adding parameters after or before regions, e.g.: esc_html_hl_regions("foo bar", "mark", [ 0, 3 ], -nbsp => 1); * esc_html_hl_regions() escapes like esc_html(); if we wanted to highlight with esc_path(), we could pass subroutine reference to now named esc_gen_hl_regions(). esc_html_hl_regions("foo bar", "mark", \&esc_path, [ 0, 3 ]); Note that this way we can handle -nbsp=>1 case automatically, e.g. esc_html_hl_regions("foo bar", "mark", sub { esc_html(@_, -nbsp=>1) }, [ 0, 3 ]); * Alternate solution for highlighting region of a string would be to use the idea that strings are to be HTML-escaped, and references to scalars are HTML (like in the idea for generic committags). This would require modifying gitweb code or esc_html to get list of fragments, e.g.: esc_html(\'', 'foo', \'', ' bar', { -nbsp => 1 }); or esc_html([\'', 'foo', \'', ' bar'], -nbsp=>1); esc_html_match_hl() could be then simple wrapper around "match formatter", e.g. esc_html([ render_match_hl($str, $regexp) ], -nbsp=>1); Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 568b077..f8c5b6a 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1715,6 +1715,47 @@ sub chop_and_escape_str { } } +# Highlight selected fragments of string, using given CSS class, +# and escape HTML. It is assumed that fragments do not overlap. +# Regions are passed as list of pairs (array references). +# +# Example: esc_html_hl_regions("foobar", "mark", [ 0, 3 ]) returns +# 'foobar' +sub esc_html_hl_regions { + my ($str, $css_class, @sel) = @_; + return esc_html($str) unless @sel; + + my $out = ''; + my $pos = 0; + + for my $s (@sel) { + $out .= esc_html(substr($str, $pos, $s->[0] - $pos)) + if ($s->[0] - $pos > 0); + $out .= $cgi->span({-class => $css_class}, + esc_html(substr($str, $s->[0], $s->[1] - $s->[0]))); + + $pos = $s->[1]; + } + $out .= esc_html(substr($str, $pos)) + if ($pos < length($str)); + + return $out; +} + +# highlight match (if any), and escape HTML +sub esc_html_match_hl { + my ($str, $regexp) = @_; + return esc_html($str) unless defined $regexp; + + my @matches; + while ($str =~ /$regexp/g) { + push @matches, [$-[0], $+[0]]; + } + return esc_html($str) unless @matches; + + return esc_html_hl_regions($str, 'match', @matches); +} + ## ---------------------------------------------------------------------- ## functions returning short strings -- cgit v0.10.2-6-g49f6 From 07a40062aebc184f5aa1d6750fe80ab6fe120cc8 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 27 Feb 2012 02:55:20 +0100 Subject: gitweb: Highlight matched part of project name when searching projects Use esc_html_match_hl() introduced in previous commit to escape HTML and mark match, using span element with 'match' class. Currently only the 'path' part (i.e. the project name) is highlighted; match might be on the project description. Highlighting match in description is left for next commit. The code makes use of the fact that defined $search_regexp means that there was search going on. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index f8c5b6a..a0c6a9b 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5400,7 +5400,9 @@ sub git_project_list_rows { print "\n"; } print "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), - -class => "list"}, esc_html($pr->{'path'})) . "\n" . + -class => "list"}, + esc_html_match_hl($pr->{'path'}, $search_regexp)) . + "\n" . "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), -class => "list", -title => $pr->{'descr_long'}}, esc_html($pr->{'descr'})) . "\n" . -- cgit v0.10.2-6-g49f6 From 5fb3cf23170f7dc43568d0234c338d67372c97cc Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 27 Feb 2012 02:55:21 +0100 Subject: gitweb: Highlight matched part of project description when searching projects Use esc_html_match_hl() from earlier commit to mark match in the _whole_ description when searching projects. Currently, with this commit, when searching projects there is always shown full description of a project, and not a shortened one (like for ordinary projects list view), even if the match is on project name and not project description. Because we always show full description of a project, and not possibly shortened name, there is no need for having full description on mouseover via title attribute. Showing full description when there is match on it is useful to avoid situation where match is in shortened, invisible part. On the other hand that makes project search different than projects list view; also there can be problems with overly-long project descriptions. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index a0c6a9b..724f06f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5404,8 +5404,12 @@ sub git_project_list_rows { esc_html_match_hl($pr->{'path'}, $search_regexp)) . "\n" . "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), - -class => "list", -title => $pr->{'descr_long'}}, - esc_html($pr->{'descr'})) . "\n" . + -class => "list", + $search_regexp ? () : -title => $pr->{'descr_long'}}, + $search_regexp + ? esc_html_match_hl($pr->{'descr_long'}, $search_regexp) + : esc_html($pr->{'descr'})) . + "\n" . "" . chop_and_escape_str($pr->{'owner'}, 15) . "\n"; print "{'age'}) . "\">" . (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "\n" . -- cgit v0.10.2-6-g49f6 From e607b79fb14f2196f7ea46d2115f21c548972e78 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 27 Feb 2012 02:55:22 +0100 Subject: gitweb: Highlight matched part of shortened project description Previous commit make gitweb use esc_html_match_hl() to mark match in the _whole_ description of a project when searching projects. This commit makes gitweb highlight match in _shortened_ description, based on match in whole description, using esc_html_match_hl_chopped() subroutine. If match is in removed (chopped) part, even partially, then trailing "... " is highlighted. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 724f06f..01c1318 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1742,20 +1742,61 @@ sub esc_html_hl_regions { return $out; } -# highlight match (if any), and escape HTML -sub esc_html_match_hl { +# return positions of beginning and end of each match +sub matchpos_list { my ($str, $regexp) = @_; - return esc_html($str) unless defined $regexp; + return unless (defined $str && defined $regexp); my @matches; while ($str =~ /$regexp/g) { push @matches, [$-[0], $+[0]]; } + return @matches; +} + +# highlight match (if any), and escape HTML +sub esc_html_match_hl { + my ($str, $regexp) = @_; + return esc_html($str) unless defined $regexp; + + my @matches = matchpos_list($str, $regexp); return esc_html($str) unless @matches; return esc_html_hl_regions($str, 'match', @matches); } + +# highlight match (if any) of shortened string, and escape HTML +sub esc_html_match_hl_chopped { + my ($str, $chopped, $regexp) = @_; + return esc_html_match_hl($str, $regexp) unless defined $chopped; + + my @matches = matchpos_list($str, $regexp); + return esc_html($chopped) unless @matches; + + # filter matches so that we mark chopped string + my $tail = "... "; # see chop_str + unless ($chopped =~ s/\Q$tail\E$//) { + $tail = ''; + } + my $chop_len = length($chopped); + my $tail_len = length($tail); + my @filtered; + + for my $m (@matches) { + if ($m->[0] > $chop_len) { + push @filtered, [ $chop_len, $chop_len + $tail_len ] if ($tail_len > 0); + last; + } elsif ($m->[1] > $chop_len) { + push @filtered, [ $m->[0], $chop_len + $tail_len ]; + last; + } + push @filtered, $m; + } + + return esc_html_hl_regions($chopped . $tail, 'match', @filtered); +} + ## ---------------------------------------------------------------------- ## functions returning short strings @@ -5405,9 +5446,10 @@ sub git_project_list_rows { "\n" . "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), -class => "list", - $search_regexp ? () : -title => $pr->{'descr_long'}}, + -title => $pr->{'descr_long'}}, $search_regexp - ? esc_html_match_hl($pr->{'descr_long'}, $search_regexp) + ? esc_html_match_hl_chopped($pr->{'descr_long'}, + $pr->{'descr'}, $search_regexp) : esc_html($pr->{'descr'})) . "\n" . "" . chop_and_escape_str($pr->{'owner'}, 15) . "\n"; -- cgit v0.10.2-6-g49f6 From a61ba26a4725d4a93297305315587b92324baf0b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 26 Feb 2012 23:00:47 -0800 Subject: test: "am -3" can accept non-standard -p This adds a test for the previous one to make sure that "am -3 -p0" can read patches created with the --no-prefix option. Signed-off-by: Junio C Hamano diff --git a/t/t4150-am.sh b/t/t4150-am.sh index d7d9ccc..e1d381c 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -123,6 +123,7 @@ test_expect_success setup ' git commit -m "added another file" && git format-patch --stdout master >lorem-move.patch && + git format-patch --no-prefix --stdout master >lorem-zero.patch && git checkout -b rename && git mv file renamed && @@ -276,6 +277,20 @@ test_expect_success 'am -3 falls back to 3-way merge' ' git diff --exit-code lorem ' +test_expect_success 'am -3 -p0 can read --no-prefix patch' ' + rm -fr .git/rebase-apply && + git reset --hard && + git checkout -b lorem3 master2 && + sed -n -e "3,\$p" msg >file && + head -n 9 msg >>file && + git add file && + test_tick && + git commit -m "copied stuff" && + git am -3 -p0 lorem-zero.patch && + ! test -d .git/rebase-apply && + git diff --exit-code lorem +' + test_expect_success 'am can rename a file' ' grep "^rename from" rename.patch && rm -fr .git/rebase-apply && -- cgit v0.10.2-6-g49f6 From 6c41e97557d94df7085e3c0cff247305c9401968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 27 Feb 2012 16:11:53 +0100 Subject: branch: don't assume the merge filter ref exists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit print_ref_list looks up the merge_filter_ref and assumes that a valid pointer is returned. When the object doesn't exist, it tries to dereference a NULL pointer. This can be the case when git branch --merged is given an argument that isn't a valid commit name. Check whether the lookup returns a NULL pointer and die with an error if it does. Add a test, while we're at it. Signed-off-by: Carlos Martín Nieto Signed-off-by: Junio C Hamano diff --git a/builtin/branch.c b/builtin/branch.c index df908ed..d6691af 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -528,6 +528,10 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru if (merge_filter != NO_FILTER) { struct commit *filter; filter = lookup_commit_reference_gently(merge_filter_ref, 0); + if (!filter) + die("object '%s' does not point to a commit", + sha1_to_hex(merge_filter_ref)); + filter->object.flags |= UNINTERESTING; add_pending_object(&ref_list.revs, (struct object *) filter, ""); diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 7690332..6ad1763 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -620,4 +620,8 @@ test_expect_success 'use set-upstream on the current branch' ' ' +test_expect_success '--merged catches invalid object names' ' + test_must_fail git branch --merged 0000000000000000000000000000000000000000 +' + test_done -- cgit v0.10.2-6-g49f6 From 1252bbe1c685450ec76ac750e8b0c2e0b762f93f Mon Sep 17 00:00:00 2001 From: Tim Henigan Date: Fri, 24 Feb 2012 14:48:57 -0500 Subject: contrib: add git-diffall script The 'git difftool' allows the user to view diffs using an external tool. It runs a separate instance of the tool for each file in the diff. This makes it tedious to review changes spanning multiple files. The 'git-diffall' script instead prepares temporary directories with the files to be compared and launches a single instance of the external diff tool to view them (i.e. a directory diff). The 'diff.tool' or 'merge.tool' configuration variable is used to specify which external tool is used. Signed-off-by: Tim Henigan Signed-off-by: Junio C Hamano diff --git a/contrib/diffall/README b/contrib/diffall/README new file mode 100644 index 0000000..507f17d --- /dev/null +++ b/contrib/diffall/README @@ -0,0 +1,31 @@ +The git-diffall script provides a directory based diff mechanism +for git. + +To determine what diff viewer is used, the script requires either +the 'diff.tool' or 'merge.tool' configuration option to be set. + +This script is compatible with most common forms used to specify a +range of revisions to diff: + + 1. git diffall: shows diff between working tree and staged changes + 2. git diffall --cached []: shows diff between staged + changes and HEAD (or other named commit) + 3. git diffall : shows diff between working tree and named + commit + 4. git diffall : show diff between two named commits + 5. git diffall ..: same as above + 6. git diffall ...: show the changes on the branch + containing and up to the second, starting at a common ancestor + of both + +Note: all forms take an optional path limiter [-- *] + +The '--extcmd=' option allows the user to specify a custom +command for viewing diffs. When given, configured defaults are +ignored and the script runs $command $LOCAL $REMOTE. Additionally, +$BASE is set in the environment. + +This script is based on an example provided by Thomas Rast on the +Git list [1]: + +[1] http://thread.gmane.org/gmane.comp.version-control.git/124807 diff --git a/contrib/diffall/git-diffall b/contrib/diffall/git-diffall new file mode 100755 index 0000000..9bbd27f --- /dev/null +++ b/contrib/diffall/git-diffall @@ -0,0 +1,261 @@ +#!/bin/sh +# Copyright 2010 - 2012, Tim Henigan +# +# Perform a directory diff between commits in the repository using +# the external diff or merge tool specified in the user's config. + +USAGE='[--cached] [--copy-back] [-x|--extcmd=] {0,2} [-- *] + + --cached Compare to the index rather than the working tree. + + --copy-back Copy files back to the working tree when the diff + tool exits (in case they were modified by the + user). This option is only valid if the diff + compared with the working tree. + + -x= + --extcmd= Specify a custom command for viewing diffs. + git-diffall ignores the configured defaults and + runs $command $LOCAL $REMOTE when this option is + specified. Additionally, $BASE is set in the + environment. +' + +SUBDIRECTORY_OK=1 +. "$(git --exec-path)/git-sh-setup" + +TOOL_MODE=diff +. "$(git --exec-path)/git-mergetool--lib" + +merge_tool="$(get_merge_tool)" +if test -z "$merge_tool" +then + echo "Error: Either the 'diff.tool' or 'merge.tool' option must be set." + usage +fi + +start_dir=$(pwd) + +# needed to access tar utility +cdup=$(git rev-parse --show-cdup) && +cd "$cdup" || { + echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree" + exit 1 +} + +# mktemp is not available on all platforms (missing from msysgit) +# Use a hard-coded tmp dir if it is not available +tmp="$(mktemp -d -t tmp.XXXXXX 2>/dev/null)" || { + tmp=/tmp/git-diffall-tmp.$$ + mkdir "$tmp" || exit 1 +} + +trap 'rm -rf "$tmp" 2>/dev/null' EXIT + +left= +right= +paths= +dashdash_seen= +compare_staged= +merge_base= +left_dir= +right_dir= +diff_tool= +copy_back= + +while test $# != 0 +do + case "$1" in + -h|--h|--he|--hel|--help) + usage + ;; + --cached) + compare_staged=1 + ;; + --copy-back) + copy_back=1 + ;; + -x|--e|--ex|--ext|--extc|--extcm|--extcmd) + if test $# = 1 + then + echo You must specify the tool for use with --extcmd + usage + else + diff_tool=$2 + shift + fi + ;; + --) + dashdash_seen=1 + ;; + -*) + echo Invalid option: "$1" + usage + ;; + *) + # could be commit, commit range or path limiter + case "$1" in + *...*) + left=${1%...*} + right=${1#*...} + merge_base=1 + ;; + *..*) + left=${1%..*} + right=${1#*..} + ;; + *) + if test -n "$dashdash_seen" + then + paths="$paths$1 " + elif test -z "$left" + then + left=$1 + elif test -z "$right" + then + right=$1 + else + paths="$paths$1 " + fi + ;; + esac + ;; + esac + shift +done + +# Determine the set of files which changed +if test -n "$left" && test -n "$right" +then + left_dir="cmt-$(git rev-parse --short $left)" + right_dir="cmt-$(git rev-parse --short $right)" + + if test -n "$compare_staged" + then + usage + elif test -n "$merge_base" + then + git diff --name-only "$left"..."$right" -- $paths >"$tmp/filelist" + else + git diff --name-only "$left" "$right" -- $paths >"$tmp/filelist" + fi +elif test -n "$left" +then + left_dir="cmt-$(git rev-parse --short $left)" + + if test -n "$compare_staged" + then + right_dir="staged" + git diff --name-only --cached "$left" -- $paths >"$tmp/filelist" + else + right_dir="working_tree" + git diff --name-only "$left" -- $paths >"$tmp/filelist" + fi +else + left_dir="HEAD" + + if test -n "$compare_staged" + then + right_dir="staged" + git diff --name-only --cached -- $paths >"$tmp/filelist" + else + right_dir="working_tree" + git diff --name-only -- $paths >"$tmp/filelist" + fi +fi + +# Exit immediately if there are no diffs +if test ! -s "$tmp/filelist" +then + exit 0 +fi + +if test -n "$copy_back" && test "$right_dir" != "working_tree" +then + echo "--copy-back is only valid when diff includes the working tree." + exit 1 +fi + +# Create the named tmp directories that will hold the files to be compared +mkdir -p "$tmp/$left_dir" "$tmp/$right_dir" + +# Populate the tmp/right_dir directory with the files to be compared +if test -n "$right" +then + while read name + do + ls_list=$(git ls-tree $right "$name") + if test -n "$ls_list" + then + mkdir -p "$tmp/$right_dir/$(dirname "$name")" + git show "$right":"$name" >"$tmp/$right_dir/$name" || true + fi + done < "$tmp/filelist" +elif test -n "$compare_staged" +then + while read name + do + ls_list=$(git ls-files -- "$name") + if test -n "$ls_list" + then + mkdir -p "$tmp/$right_dir/$(dirname "$name")" + git show :"$name" >"$tmp/$right_dir/$name" + fi + done < "$tmp/filelist" +else + # Mac users have gnutar rather than tar + (tar --ignore-failed-read -c -T "$tmp/filelist" | (cd "$tmp/$right_dir" && tar -x)) || { + gnutar --ignore-failed-read -c -T "$tmp/filelist" | (cd "$tmp/$right_dir" && gnutar -x) + } +fi + +# Populate the tmp/left_dir directory with the files to be compared +while read name +do + if test -n "$left" + then + ls_list=$(git ls-tree $left "$name") + if test -n "$ls_list" + then + mkdir -p "$tmp/$left_dir/$(dirname "$name")" + git show "$left":"$name" >"$tmp/$left_dir/$name" || true + fi + else + if test -n "$compare_staged" + then + ls_list=$(git ls-tree HEAD "$name") + if test -n "$ls_list" + then + mkdir -p "$tmp/$left_dir/$(dirname "$name")" + git show HEAD:"$name" >"$tmp/$left_dir/$name" + fi + else + mkdir -p "$tmp/$left_dir/$(dirname "$name")" + git show :"$name" >"$tmp/$left_dir/$name" + fi + fi +done < "$tmp/filelist" + +cd "$tmp" +LOCAL="$left_dir" +REMOTE="$right_dir" + +if test -n "$diff_tool" +then + export BASE + eval $diff_tool '"$LOCAL"' '"$REMOTE"' +else + run_merge_tool "$merge_tool" false +fi + +# Copy files back to the working dir, if requested +if test -n "$copy_back" && test "$right_dir" = "working_tree" +then + cd "$start_dir" + git_top_dir=$(git rev-parse --show-toplevel) + find "$tmp/$right_dir" -type f | + while read file + do + cp "$file" "$git_top_dir/${file#$tmp/$right_dir/}" + done +fi -- cgit v0.10.2-6-g49f6 From 42b00599be684e20462c431a718f86c2b6fce575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kr=C3=BCger?= Date: Mon, 27 Feb 2012 23:10:38 +0100 Subject: symbolic-ref --short: abbreviate the output unambiguously MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can be helpful to resolve a symbolic ref and output the result in a shortened form, such as for use in shell prompts. Add a "--short" option to do so. Signed-off-by: Jan Krüger Signed-off-by: Junio C Hamano diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt index a45d4c4..981d3a8 100644 --- a/Documentation/git-symbolic-ref.txt +++ b/Documentation/git-symbolic-ref.txt @@ -8,7 +8,8 @@ git-symbolic-ref - Read and modify symbolic refs SYNOPSIS -------- [verse] -'git symbolic-ref' [-q] [-m ] [] +'git symbolic-ref' [-m ] +'git symbolic-ref' [-q] [--short] DESCRIPTION ----------- @@ -33,6 +34,10 @@ OPTIONS symbolic ref but a detached HEAD; instead exit with non-zero status silently. +--short:: + When showing the value of as a symbolic ref, try to shorten the + value, e.g. from `refs/heads/master` to `master`. + -m:: Update the reflog for with . This is valid only when creating or updating a symbolic ref. diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c index 2ef5962..801d62e 100644 --- a/builtin/symbolic-ref.c +++ b/builtin/symbolic-ref.c @@ -8,13 +8,15 @@ static const char * const git_symbolic_ref_usage[] = { NULL }; +static int shorten; + static void check_symref(const char *HEAD, int quiet) { unsigned char sha1[20]; int flag; - const char *refs_heads_master = resolve_ref_unsafe(HEAD, sha1, 0, &flag); + const char *refname = resolve_ref_unsafe(HEAD, sha1, 0, &flag); - if (!refs_heads_master) + if (!refname) die("No such ref: %s", HEAD); else if (!(flag & REF_ISSYMREF)) { if (!quiet) @@ -22,7 +24,9 @@ static void check_symref(const char *HEAD, int quiet) else exit(1); } - puts(refs_heads_master); + if (shorten) + refname = shorten_unambiguous_ref(refname, 0); + puts(refname); } int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) @@ -32,6 +36,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) struct option options[] = { OPT__QUIET(&quiet, "suppress error message for non-symbolic (detached) refs"), + OPT_BOOL(0, "short", &shorten, "shorten ref output"), OPT_STRING('m', NULL, &msg, "reason", "reason of the update"), OPT_END(), }; -- cgit v0.10.2-6-g49f6 From 8ba8fe049feb9207dd3543c339da955336e5df8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Tue, 28 Feb 2012 20:59:59 +0700 Subject: rev-list: remove BISECT_SHOW_TRIED flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since c99f069 (bisect--helper: remove "--next-vars" option as it is now useless - 2009-04-21), this flag has always been off. Remove the flag and all related code. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/bisect.h b/bisect.h index 22f2e4d..b06949e 100644 --- a/bisect.h +++ b/bisect.h @@ -17,7 +17,6 @@ extern void print_commit_list(struct commit_list *list, /* bisect_show_flags flags in struct rev_list_info */ #define BISECT_SHOW_ALL (1<<0) -#define BISECT_SHOW_TRIED (1<<1) struct rev_list_info { struct rev_info *revs; diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 264e3ae..7a3f820 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -242,13 +242,6 @@ void print_commit_list(struct commit_list *list, } } -static void show_tried_revs(struct commit_list *tried) -{ - printf("bisect_tried='"); - print_commit_list(tried, "%s|", "%s"); - printf("'\n"); -} - static void print_var_str(const char *var, const char *val) { printf("%s='%s'\n", var, val); @@ -266,7 +259,7 @@ static int show_bisect_vars(struct rev_list_info *info, int reaches, int all) struct commit_list *tried; struct rev_info *revs = info->revs; - if (!revs->commits && !(flags & BISECT_SHOW_TRIED)) + if (!revs->commits) return 1; revs->commits = filter_skipped(revs->commits, &tried, @@ -294,9 +287,6 @@ static int show_bisect_vars(struct rev_list_info *info, int reaches, int all) printf("------\n"); } - if (flags & BISECT_SHOW_TRIED) - show_tried_revs(tried); - print_var_str("bisect_rev", hex); print_var_int("bisect_nr", cnt - 1); print_var_int("bisect_good", all - reaches - 1); -- cgit v0.10.2-6-g49f6 From 989937221a95cd6c3a829da043162e18e0371b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Tue, 28 Feb 2012 21:00:00 +0700 Subject: rev-list: fix --verify-objects --quiet becoming --objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When --quiet is specified, finish_object() is called instead of show_object(). The latter is in charge of --verify-objects and will be skipped if --quiet is specified. Move the code up to finish_object(). Also pass the quiet flag along and make it always call show_* functions to avoid similar problems in future. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/bisect.h b/bisect.h index b06949e..ec3c3ff 100644 --- a/bisect.h +++ b/bisect.h @@ -15,12 +15,12 @@ extern void print_commit_list(struct commit_list *list, const char *format_cur, const char *format_last); -/* bisect_show_flags flags in struct rev_list_info */ #define BISECT_SHOW_ALL (1<<0) +#define REV_LIST_QUIET (1<<1) struct rev_list_info { struct rev_info *revs; - int bisect_show_flags; + int flags; int show_timestamp; int hdr_termination; const char *header_prefix; diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 7a3f820..4c4d404 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -52,6 +52,11 @@ static void show_commit(struct commit *commit, void *data) struct rev_list_info *info = data; struct rev_info *revs = info->revs; + if (info->flags & REV_LIST_QUIET) { + finish_commit(commit, data); + return; + } + graph_show_commit(revs->graph); if (revs->count) { @@ -172,8 +177,11 @@ static void finish_object(struct object *obj, const struct name_path *path, const char *name, void *cb_data) { + struct rev_list_info *info = cb_data; if (obj->type == OBJ_BLOB && !has_sha1_file(obj->sha1)) die("missing blob object '%s'", sha1_to_hex(obj->sha1)); + if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT) + parse_object(obj->sha1); } static void show_object(struct object *obj, @@ -181,10 +189,9 @@ static void show_object(struct object *obj, void *cb_data) { struct rev_list_info *info = cb_data; - finish_object(obj, path, component, cb_data); - if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT) - parse_object(obj->sha1); + if (info->flags & REV_LIST_QUIET) + return; show_object_with_name(stdout, obj, path, component); } @@ -254,7 +261,7 @@ static void print_var_int(const char *var, int val) static int show_bisect_vars(struct rev_list_info *info, int reaches, int all) { - int cnt, flags = info->bisect_show_flags; + int cnt, flags = info->flags; char hex[41] = ""; struct commit_list *tried; struct rev_info *revs = info->revs; @@ -305,7 +312,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) int bisect_list = 0; int bisect_show_vars = 0; int bisect_find_all = 0; - int quiet = 0; git_config(git_default_config, NULL); init_revisions(&revs, prefix); @@ -318,7 +324,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (revs.bisect) bisect_list = 1; - quiet = DIFF_OPT_TST(&revs.diffopt, QUICK); + if (DIFF_OPT_TST(&revs.diffopt, QUICK)) + info.flags |= REV_LIST_QUIET; for (i = 1 ; i < argc; i++) { const char *arg = argv[i]; @@ -337,7 +344,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (!strcmp(arg, "--bisect-all")) { bisect_list = 1; bisect_find_all = 1; - info.bisect_show_flags = BISECT_SHOW_ALL; + info.flags |= BISECT_SHOW_ALL; revs.show_decorations = 1; continue; } @@ -388,10 +395,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) return show_bisect_vars(&info, reaches, all); } - traverse_commit_list(&revs, - quiet ? finish_commit : show_commit, - quiet ? finish_object : show_object, - &info); + traverse_commit_list(&revs, show_commit, show_object, &info); if (revs.count) { if (revs.left_right && revs.cherry_mark) -- cgit v0.10.2-6-g49f6 From 36612e4daf8b5b5eaf16315aa13c66925f878cd6 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 28 Feb 2012 19:41:47 +0100 Subject: gitweb: Handle invalid regexp in regexp search When using regexp search ('sr' parameter / $search_use_regexp variable is true), check first that regexp is valid. Without this patch we would get an error from Perl during search (if searching is performed by gitweb), or highlighting matches substring (if applicable), if user provided invalid regexp... which means broken HTML, with error page (including HTTP headers) generated after gitweb already produced some output. Add test that illustrates such error: for example for regexp "*\.git" we would get the following error: Quantifier follows nothing in regex; marked by <-- HERE in m/* <-- HERE \.git/ at /var/www/cgi-bin/gitweb.cgi line 3084. Reported-by: Ramsay Jones Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 50a835a..7b93698 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1054,7 +1054,16 @@ sub evaluate_and_validate_params { if (length($searchtext) < 2) { die_error(403, "At least two characters are required for search parameter"); } - $search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext; + if ($search_use_regexp) { + $search_regexp = $searchtext; + if (!eval { qr/$search_regexp/; 1; }) { + (my $error = $@) =~ s/ at \S+ line \d+.*\n?//; + die_error(400, "Invalid search regexp '$search_regexp'", + esc_html($error)); + } + } else { + $search_regexp = quotemeta $searchtext; + } } } diff --git a/t/t9501-gitweb-standalone-http-status.sh b/t/t9501-gitweb-standalone-http-status.sh index 26102ee..31076ed 100755 --- a/t/t9501-gitweb-standalone-http-status.sh +++ b/t/t9501-gitweb-standalone-http-status.sh @@ -134,4 +134,14 @@ our $maxload = undef; EOF +# ---------------------------------------------------------------------- +# invalid arguments + +test_expect_success 'invalid arguments: invalid regexp (in project search)' ' + gitweb_run "a=project_list;s=*\.git;sr=1" && + grep "Status: 400" gitweb.headers && + grep "400 - Invalid.*regexp" gitweb.body +' +test_debug 'cat gitweb.headers' + test_done -- cgit v0.10.2-6-g49f6 From cbb08c2e0b41ab162838aa1e83b959bac91151e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Tue, 28 Feb 2012 20:06:09 +0100 Subject: parse-options: remove PARSE_OPT_NEGHELP PARSE_OPT_NEGHELP is confusing because short options defined with that flag do the opposite of what the helptext says. It is also not needed anymore now that options starting with no- can be negated by removing that prefix. Convert its only two users to OPT_NEGBIT() and OPT_BOOL() and then remove support for PARSE_OPT_NEGHELP. Signed-off-by: Rene Scharfe Acked-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 9836e6b..6165346 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -647,9 +647,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) "Output full tree for each commit"), OPT_BOOLEAN(0, "use-done-feature", &use_done_feature, "Use the done feature to terminate the stream"), - { OPTION_NEGBIT, 0, "data", &no_data, NULL, - "Skip output of blob data", - PARSE_OPT_NOARG | PARSE_OPT_NEGHELP, NULL, 1 }, + OPT_BOOL(0, "no-data", &no_data, "Skip output of blob data"), OPT_END() }; diff --git a/builtin/grep.c b/builtin/grep.c index a286692..461d1c2 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -777,8 +777,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) struct option options[] = { OPT_BOOLEAN(0, "cached", &cached, "search in index instead of in the work tree"), - OPT_BOOLEAN(0, "index", &use_index, - "--no-index finds in contents not managed by git"), + OPT_NEGBIT(0, "no-index", &use_index, + "finds in contents not managed by git", 1), OPT_GROUP(""), OPT_BOOLEAN('v', "invert-match", &opt.invert, "show non-matching lines"), diff --git a/parse-options.c b/parse-options.c index 8906841..1908996 100644 --- a/parse-options.c +++ b/parse-options.c @@ -533,7 +533,7 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx, continue; pos = fprintf(outfile, " "); - if (opts->short_name && !(opts->flags & PARSE_OPT_NEGHELP)) { + if (opts->short_name) { if (opts->flags & PARSE_OPT_NODASH) pos += fprintf(outfile, "%c", opts->short_name); else @@ -542,9 +542,7 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx, if (opts->long_name && opts->short_name) pos += fprintf(outfile, ", "); if (opts->long_name) - pos += fprintf(outfile, "--%s%s", - (opts->flags & PARSE_OPT_NEGHELP) ? "no-" : "", - opts->long_name); + pos += fprintf(outfile, "--%s", opts->long_name); if (opts->type == OPTION_NUMBER) pos += fprintf(outfile, "-NUM"); diff --git a/parse-options.h b/parse-options.h index 2e811dc..def9ced 100644 --- a/parse-options.h +++ b/parse-options.h @@ -40,7 +40,6 @@ enum parse_opt_option_flags { PARSE_OPT_LASTARG_DEFAULT = 16, PARSE_OPT_NODASH = 32, PARSE_OPT_LITERAL_ARGHELP = 64, - PARSE_OPT_NEGHELP = 128, PARSE_OPT_SHELL_EVAL = 256 }; @@ -90,9 +89,6 @@ typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx, * PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets * (i.e. '') in the help message. * Useful for options with multiple parameters. - * PARSE_OPT_NEGHELP: says that the long option should always be shown with - * the --no prefix in the usage message. Sometimes - * useful for users of OPTION_NEGBIT. * * `callback`:: * pointer to the callback to use for OPTION_CALLBACK or -- cgit v0.10.2-6-g49f6 From e34bb2e7fd59b3855411123d77cdad0345a25f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 28 Feb 2012 16:35:48 +0100 Subject: Documentation: use {asterisk} in rev-list-options.txt when needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Text between two '*' is emphasized in AsciiDoc and makes explanations in rev-list-options.txt on glob-related options very confusing, as the rendered text would be missing two asterisks and the text between them would be emphasized instead. Use '{asterisk}' where needed to make them show up as asterisks in the rendered text. Signed-off-by: Carlos Martín Nieto Acked-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 39e6207..6a4b635 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -117,27 +117,27 @@ parents) and `--max-parents=-1` (negative numbers denote no upper limit). Pretend as if all the refs in `refs/heads` are listed on the command line as ''. If '' is given, limit branches to ones matching given shell glob. If pattern lacks '?', - '*', or '[', '/*' at the end is implied. + '{asterisk}', or '[', '/{asterisk}' at the end is implied. --tags[=]:: Pretend as if all the refs in `refs/tags` are listed on the command line as ''. If '' is given, limit - tags to ones matching given shell glob. If pattern lacks '?', '*', - or '[', '/*' at the end is implied. + tags to ones matching given shell glob. If pattern lacks '?', '{asterisk}', + or '[', '/{asterisk}' at the end is implied. --remotes[=]:: Pretend as if all the refs in `refs/remotes` are listed on the command line as ''. If '' is given, limit remote-tracking branches to ones matching given shell glob. - If pattern lacks '?', '*', or '[', '/*' at the end is implied. + If pattern lacks '?', '{asterisk}', or '[', '/{asterisk}' at the end is implied. --glob=:: Pretend as if all the refs matching shell glob '' are listed on the command line as ''. Leading 'refs/', - is automatically prepended if missing. If pattern lacks '?', '*', - or '[', '/*' at the end is implied. + is automatically prepended if missing. If pattern lacks '?', '{asterisk}', + or '[', '/{asterisk}' at the end is implied. --ignore-missing:: -- cgit v0.10.2-6-g49f6 From f051ad6d118aff0252beed36d20a56d1823fc90b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 28 Feb 2012 13:31:05 -0800 Subject: Update draft release notes to 1.7.10 Signed-off-by: Junio C Hamano diff --git a/Documentation/RelNotes/1.7.10.txt b/Documentation/RelNotes/1.7.10.txt index 89edfda..70d76b5 100644 --- a/Documentation/RelNotes/1.7.10.txt +++ b/Documentation/RelNotes/1.7.10.txt @@ -22,6 +22,10 @@ UI, Workflows & Features file to be included in-place when Git looks up configuration variables. + * A content filter (clean/smudge) used to be just a way to make the + recorded contents "more useful", and allowed to fail; a filter can + new optionally be marked as "required". + * "git am" learned to pass "-b" option to underlying "git mailinfo", so that bracketed string other than "PATCH" at the beginning can be kept. @@ -122,7 +126,7 @@ details). --- exec >/var/tmp/1 -O=v1.7.9.2-301-g507fba2 +O=v1.7.9.2-322-g472fdee echo O=$(git describe) git log --first-parent --oneline ^maint $O.. echo -- cgit v0.10.2-6-g49f6 From 0f871cf56e83d13116b021295688e57f26bbf93d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 28 Feb 2012 14:20:53 -0800 Subject: grep: use static trans-case table In order to prepare the kwset machinery for a case-insensitive search, we used to use a static table of 256 elements and filled it every time before calling kwsalloc(). Because the kwset machinery will never modify this table, just allocate a single instance globally and fill it at the compile time. Signed-off-by: Junio C Hamano diff --git a/cache.h b/cache.h index 79c612f..79dc305 100644 --- a/cache.h +++ b/cache.h @@ -1258,4 +1258,7 @@ extern struct startup_info *startup_info; /* builtin/merge.c */ int checkout_fast_forward(const unsigned char *from, const unsigned char *to); +/* in ctype.c, for kwset users */ +extern const char tolower_trans_tbl[256]; + #endif /* CACHE_H */ diff --git a/ctype.c b/ctype.c index b5d856f..7c14d85 100644 --- a/ctype.c +++ b/ctype.c @@ -25,3 +25,39 @@ unsigned char sane_ctype[256] = { A, A, A, A, A, A, A, A, A, A, A, R, R, 0, P, 0, /* 112..127 */ /* Nothing in the 128.. range */ }; + +/* For case-insensitive kwset */ +const char tolower_trans_tbl[256] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + ' ', '!', '"', '#', '$', '%', '&', 0x27, + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '[', 0x5c, ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +}; diff --git a/grep.c b/grep.c index b29d09c..1030f38 100644 --- a/grep.c +++ b/grep.c @@ -168,15 +168,10 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt) p->fixed = 0; if (p->fixed) { - if (opt->regflags & REG_ICASE || p->ignore_case) { - static char trans[256]; - int i; - for (i = 0; i < 256; i++) - trans[i] = tolower(i); - p->kws = kwsalloc(trans); - } else { + if (opt->regflags & REG_ICASE || p->ignore_case) + p->kws = kwsalloc(tolower_trans_tbl); + else p->kws = kwsalloc(NULL); - } kwsincr(p->kws, p->pattern, p->patternlen); kwsprep(p->kws); return; -- cgit v0.10.2-6-g49f6 From c6a13b2c86b71cb25011094ff2dee3d7769991a2 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 28 Feb 2012 14:55:39 -0800 Subject: fsck: --no-dangling omits "dangling object" information The default output from "fsck" is often overwhelmed by informational message on dangling objects, especially if you do not repack often, and a real error can easily be buried. Add "--no-dangling" option to omit them, and update the user manual to demonstrate its use. Based on a patch by Clemens Buchacher, but reverted the part to change the default to --no-dangling, which is unsuitable for the first patch. The usual three-step procedure to break the backward compatibility over time needs to happen on top of this, if we were to go in that direction. Signed-off-by: Junio C Hamano diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt index 6c47395..47e2f19 100644 --- a/Documentation/git-fsck.txt +++ b/Documentation/git-fsck.txt @@ -11,7 +11,7 @@ SYNOPSIS [verse] 'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs] [--[no-]full] [--strict] [--verbose] [--lost-found] - [--[no-]progress] [*] + [--[no-]dangling] [--[no-]progress] [*] DESCRIPTION ----------- @@ -30,6 +30,11 @@ index file, all SHA1 references in .git/refs/*, and all reflogs (unless Print out objects that exist but that aren't reachable from any of the reference nodes. +--dangling:: +--no-dangling:: + Print objects that exist but that are never 'directly' used (default). + `--no-dangling` can be used to squech this information from the output. + --root:: Report root nodes. diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index 40af321..4c1aff6 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -34,7 +34,7 @@ OPTIONS Especially useful when packing a repository that is used for private development. Use with '-d'. This will clean up the objects that `git prune` - leaves behind, but `git fsck --full` shows as + leaves behind, but `git fsck --full --dangling` shows as dangling. + Note that users fetching over dumb protocols will have to fetch the diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index f13a846..6c7fee7 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1582,7 +1582,7 @@ Checking the repository for corruption The linkgit:git-fsck[1] command runs a number of self-consistency checks on the repository, and reports on any problems. This may take some -time. The most common warning by far is about "dangling" objects: +time. ------------------------------------------------- $ git fsck @@ -1597,9 +1597,11 @@ dangling tree b24c2473f1fd3d91352a624795be026d64c8841f ... ------------------------------------------------- -Dangling objects are not a problem. At worst they may take up a little -extra disk space. They can sometimes provide a last-resort method for -recovering lost work--see <> for details. +You will see informational messages on dangling objects. They are objects +that still exist in the repository but are no longer referenced by any of +your branches, and can (and will) be removed after a while with "gc". +You can run `git fsck --no-dangling` to supress these messages, and still +view real errors. [[recovering-lost-changes]] Recovering lost changes @@ -3295,15 +3297,12 @@ it is with linkgit:git-fsck[1]; this may be time-consuming. Assume the output looks like this: ------------------------------------------------ -$ git fsck --full +$ git fsck --full --no-dangling broken link from tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8 to blob 4b9458b3786228369c63936db65827de3cc06200 missing blob 4b9458b3786228369c63936db65827de3cc06200 ------------------------------------------------ -(Typically there will be some "dangling object" messages too, but they -aren't interesting.) - Now you know that blob 4b9458b3 is missing, and that the tree 2d9263c6 points to it. If you could find just one copy of that missing blob object, possibly in some other repository, you could move it into diff --git a/builtin/fsck.c b/builtin/fsck.c index 8c479a7..67eb553 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -29,6 +29,7 @@ static int errors_found; static int write_lost_and_found; static int verbose; static int show_progress = -1; +static int show_dangling = 1; #define ERROR_OBJECT 01 #define ERROR_REACHABLE 02 #define ERROR_PACK 04 @@ -221,8 +222,9 @@ static void check_unreachable_object(struct object *obj) * start looking at, for example. */ if (!obj->used) { - printf("dangling %s %s\n", typename(obj->type), - sha1_to_hex(obj->sha1)); + if (show_dangling) + printf("dangling %s %s\n", typename(obj->type), + sha1_to_hex(obj->sha1)); if (write_lost_and_found) { char *filename = git_path("lost-found/%s/%s", obj->type == OBJ_COMMIT ? "commit" : "other", @@ -614,6 +616,7 @@ static char const * const fsck_usage[] = { static struct option fsck_opts[] = { OPT__VERBOSE(&verbose, "be verbose"), OPT_BOOLEAN(0, "unreachable", &show_unreachable, "show unreachable objects"), + OPT_BOOL(0, "dangling", &show_dangling, "show dangling objects"), OPT_BOOLEAN(0, "tags", &show_tags, "report tags"), OPT_BOOLEAN(0, "root", &show_root, "report root nodes"), OPT_BOOLEAN(0, "cache", &keep_cache_objects, "make index objects head nodes"), diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 5b8ebd8..5b79c51 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -27,12 +27,8 @@ test_expect_success 'loose objects borrowed from alternate are not missing' ' git init && echo ../../../.git/objects >.git/objects/info/alternates && test_commit C fileC one && - git fsck >../out 2>&1 + git fsck --no-dangling >../actual 2>&1 ) && - { - grep -v dangling out >actual || - : - } && test_cmp empty actual ' -- cgit v0.10.2-6-g49f6 From accccde483c3cfd55ef55037e8802ca0baaee5a1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 21 Feb 2012 01:02:46 -0800 Subject: pickaxe: allow -i to search in patch case-insensitively "git log -S" is a useful way to find the last commit in the codebase that touched the . As it was designed to be used by a porcelain script to dig the history starting from a block of text that appear in the starting commit, it never had to look for anything but an exact match. When used by an end user who wants to look for the last commit that removed a string (e.g. name of a variable) that he vaguely remembers, however, it is useful to support case insensitive match. When given the "--regexp-ignore-case" (or "-i") option, which originally was designed to affect case sensitivity of the search done in the commit log part, e.g. "log --grep", the matches made with -S/-G pickaxe search is done case insensitively now. Signed-off-by: Junio C Hamano diff --git a/diff.h b/diff.h index 0c51724..436b574 100644 --- a/diff.h +++ b/diff.h @@ -80,6 +80,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data) #define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27) #define DIFF_OPT_DIRSTAT_BY_LINE (1 << 28) #define DIFF_OPT_FUNCCONTEXT (1 << 29) +#define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c index 380a837..ed23eb4 100644 --- a/diffcore-pickaxe.c +++ b/diffcore-pickaxe.c @@ -138,8 +138,12 @@ static void diffcore_pickaxe_grep(struct diff_options *o) { int err; regex_t regex; + int cflags = REG_EXTENDED | REG_NEWLINE; - err = regcomp(®ex, o->pickaxe, REG_EXTENDED | REG_NEWLINE); + if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)) + cflags |= REG_ICASE; + + err = regcomp(®ex, o->pickaxe, cflags); if (err) { char errbuf[1024]; regerror(err, ®ex, errbuf, 1024); @@ -237,7 +241,8 @@ static void diffcore_pickaxe_count(struct diff_options *o) } regexp = ®ex; } else { - kws = kwsalloc(NULL); + kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE) + ? tolower_trans_tbl : NULL); kwsincr(kws, needle, len); kwsprep(kws); } diff --git a/revision.c b/revision.c index 8764dde..971b7dc 100644 --- a/revision.c +++ b/revision.c @@ -1559,6 +1559,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->grep_filter.regflags |= REG_EXTENDED; } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) { revs->grep_filter.regflags |= REG_ICASE; + DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE); } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) { revs->grep_filter.fixed = 1; } else if (!strcmp(arg, "--all-match")) { diff --git a/t/t4209-log-pickaxe.sh b/t/t4209-log-pickaxe.sh new file mode 100755 index 0000000..eed7273 --- /dev/null +++ b/t/t4209-log-pickaxe.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +test_description='log --grep/--author/--regexp-ignore-case/-S/-G' +. ./test-lib.sh + +test_expect_success setup ' + >file && + git add file && + test_tick && + git commit -m initial && + + echo Picked >file && + test_tick && + git commit -a --author="Another Person " -m second +' + +test_expect_success 'log --grep' ' + git log --grep=initial --format=%H >actual && + git rev-parse --verify HEAD^ >expect && + test_cmp expect actual +' + +test_expect_success 'log --grep --regexp-ignore-case' ' + git log --regexp-ignore-case --grep=InItial --format=%H >actual && + git rev-parse --verify HEAD^ >expect && + test_cmp expect actual +' + +test_expect_success 'log --grep -i' ' + git log -i --grep=InItial --format=%H >actual && + git rev-parse --verify HEAD^ >expect && + test_cmp expect actual +' + +test_expect_success 'log --author --regexp-ignore-case' ' + git log --regexp-ignore-case --author=person --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log --author -i' ' + git log -i --author=person --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -G (nomatch)' ' + git log -Gpicked --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log -G (match)' ' + git log -GPicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -G --regexp-ignore-case (nomatch)' ' + git log --regexp-ignore-case -Gpickle --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log -G -i (nomatch)' ' + git log -i -Gpickle --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log -G --regexp-ignore-case (match)' ' + git log --regexp-ignore-case -Gpicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -G -i (match)' ' + git log -i -Gpicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -S (nomatch)' ' + git log -Spicked --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log -S (match)' ' + git log -SPicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -S --regexp-ignore-case (match)' ' + git log --regexp-ignore-case -Spicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -S -i (match)' ' + git log -i -Spicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -S --regexp-ignore-case (nomatch)' ' + git log --regexp-ignore-case -Spickle --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log -S -i (nomatch)' ' + git log -i -Spickle --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_done -- cgit v0.10.2-6-g49f6 From 271ce198cd01f1e0de77bbd04cca66b0648e59bd Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 29 Feb 2012 00:10:30 -0800 Subject: Update l10n guide Signed-off-by: Junio C Hamano diff --git a/po/README b/po/README index 10b0ad2..6480882 100644 --- a/po/README +++ b/po/README @@ -1,33 +1,78 @@ Core GIT Translations ===================== -This directory holds the translations for the core of Git. This -document describes how to add to and maintain these translations, and -how to mark source strings for translation. - +This directory holds the translations for the core of Git. This document +describes how you can contribute to the effort of enhancing the language +coverage and maintaining the translation. + +The localization (l10n) coordinator, Jiang Xin , +coordinates our localization effort in his repository: + + https://github.com/gotgit/git-po/ + +As a contributor for a language XX, you would fork this repository, +prepare and/or update the translated message file po/XX.po (described +later), and ask the l10n coordinator to pull your work. + +If there are multiple contributors for the same language, please first +coordinate among yourselves and nominate the team leader for your +language, so that the l10n coordinator only needs to interact with one +person per language. + +For the list of exiting translations and language teams, see TEAMS file in +this directory. + +The overall data-flow looks like this: + + +-------------------+ +------------------+ + | Git source code | ---(1)---> | L10n coordinator | + | repository | <---(4)--- | repository | + +-------------------+ +------------------+ + | ^ + (2) (3) + V | + +------------------+ + | Language Team XX | + +------------------+ + + * Translatable strings are marked in the source file. + * L10n coordinator pulls from the source (1) + * L10n coordinator updates the message template po/git.pot + * Language team pulls from L10n coordinator (2) + * Language team updates the message file po/XX.po + * L10n coordinator pulls from Language team (3) + * L10n coordinator asks the result to be pulled (4). + + +Maintaining the po/git.pot file +------------------------------- -Generating a .pot file ----------------------- +(This is done by the l10n coordinator). The po/git.pot file contains a message catalog extracted from Git's -sources. You need to generate it to add new translations with -msginit(1), or update existing ones with msgmerge(1). +sources. The l10n coordinator maintains it by adding new translations with +msginit(1), or update existing ones with msgmerge(1). In order to update +the Git sources to extract the messages from, the l10n coordinator is +expected to pull from the main git repository at strategic point in +history (e.g. when a major release and release candidates are tagged), +and then run "make pot" at the top-level directory. -Since the file can be automatically generated it's not checked into -git.git. To generate it do, at the top-level: +Language contributors use this file to prepare translations for their +language, but they are not expected to modify it. - make pot +Initializing a XX.po file +------------------------- -Initializing a .po file ------------------------ +(This is done by the language teams). -To add a new translation first generate git.pot (see above) and then -in the po/ directory do: +If your language XX does not have translated message file po/XX.po yet, +you add a translation for the first time by running: msginit --locale=XX -Where XX is your locale, e.g. "is", "de" or "pt_BR". +in the po/ directory, where XX is the locale, e.g. "de", "is", "pt_BR", +"zh_CN", etc. Then edit the automatically generated copyright info in your new XX.po to be correct, e.g. for Icelandic: @@ -46,21 +91,36 @@ just "Git": perl -pi -e 's/(?<="Project-Id-Version: )PACKAGE VERSION/Git/' XX.po +Once you are done testing the translation (see below), commit the result +and ask the l10n coordinator to pull from you. + + +Updating a XX.po file +--------------------- -Updating a .po file -------------------- +(This is done by the language teams). -If there's an existing *.po file for your language but you need to -update the translation you first need to generate git.pot (see above) -and then in the po/ directory do: +If you are replacing translation strings in an existing XX.po file to +improve the translation, just edit the file. + +If there's an existing XX.po file for your language, but the repository +of the l10n coordinator has newer po/git.pot file, you would need to first +pull from the l10n coordinator (see the beginning of this document for its +URL), and then update the existing translation by running: msgmerge --add-location --backup=off -U XX.po git.pot -Where XX.po is the file you want to update. +in the po/ directory, where XX.po is the file you want to update. + +Once you are done testing the translation (see below), commit the result +and ask the l10n coordinator to pull from you. + Testing your changes -------------------- +(This is done by the language teams, after creating or updating XX.po file). + Before you submit your changes go back to the top-level and do: make @@ -75,6 +135,8 @@ with a newline or not. Marking strings for translation ------------------------------- +(This is done by the core developers). + Before strings can be translated they first have to be marked for translation. diff --git a/po/TEAMS b/po/TEAMS new file mode 100644 index 0000000..8ee6199 --- /dev/null +++ b/po/TEAMS @@ -0,0 +1,10 @@ +Core Git translation language teams +(please keep the list sorted alphabetically on language field) + +Language: is (Icelandic) +Leader: Ævar Arnfjörð Bjarmason + +Language: zh_CN (Simplified Chinese) +Leader: Jiang Xin +Members: Yichao Yu + Riku -- cgit v0.10.2-6-g49f6 From e0a4aae865862549c5f2a65016d4d264843e7914 Mon Sep 17 00:00:00 2001 From: Libor Pechacek Date: Thu, 1 Mar 2012 11:59:45 +0100 Subject: Documentation fixes in git-config Variable names must start with an alphabetic character, regexp config key matching has its limits, sentence grammar. Signed-off-by: Libor Pechacek Acked-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/Documentation/config.txt b/Documentation/config.txt index abeb82b..a7a6dc0 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -12,8 +12,9 @@ The configuration variables are used by both the git plumbing and the porcelains. The variables are divided into sections, wherein the fully qualified variable name of the variable itself is the last dot-separated segment and the section name is everything before the last -dot. The variable names are case-insensitive and only alphanumeric -characters are allowed. Some variables may appear multiple times. +dot. The variable names are case-insensitive, allow only alphanumeric +characters and `-`, and must start with an alphabetic character. Some +variables may appear multiple times. Syntax ~~~~~~ @@ -54,9 +55,10 @@ All the other lines (and the remainder of the line after the section header) are recognized as setting variables, in the form 'name = value'. If there is no equal sign on the line, the entire line is taken as 'name' and the variable is recognized as boolean "true". -The variable names are case-insensitive and only alphanumeric -characters and `-` are allowed. There can be more than one value -for a given variable; we say then that variable is multivalued. +The variable names are case-insensitive, allow only alphanumeric characters +and `-`, and must start with an alphabetic character. There can be more +than one value for a given variable; we say then that the variable is +multivalued. Leading and trailing whitespace in a variable value is discarded. Internal whitespace within a variable value is retained verbatim. diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index e7ecf5d..7617d9e 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -85,8 +85,11 @@ OPTIONS is not exactly one. --get-regexp:: - Like --get-all, but interprets the name as a regular expression. - Also outputs the key names. + Like --get-all, but interprets the name as a regular expression and + writes out the key names. Regular expression matching is currently + case-sensitive and done against a canonicalized version of the key + in which section and variable names are lowercased, but subsection + names are not. --global:: For writing options: write to global ~/.gitconfig file rather than -- cgit v0.10.2-6-g49f6 From 31c2373d39558f98222a1fd8b83ed74ccaa87161 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 1 Mar 2012 13:26:38 +0100 Subject: diff --stat: tests for long filenames and big change counts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for updates to the "diff --stat" that updates the logic to split the allotted columns into the name part and the graph part to make the output more readable, add a handful of tests to document the corner case behaviour in which long filenames and big changes are shown. When a pathname is so long that it cannot fit on the column, the current code truncates it to make sure that the graph part has enough room to show a meaningful graph. If the actual change is small (e.g. only one line changed), this results in the final output that is shorter than the width we aim for. Signed-off-by: Zbigniew Jędrzejewski-Szmek Signed-off-by: Junio C Hamano diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh new file mode 100755 index 0000000..f766c47 --- /dev/null +++ b/t/t4052-stat-output.sh @@ -0,0 +1,182 @@ +#!/bin/sh +# +# Copyright (c) 2012 Zbigniew Jędrzejewski-Szmek +# + +test_description='test --stat output of various commands' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-terminal.sh + +# 120 character name +name=aaaaaaaaaa +name=$name$name$name$name$name$name$name$name$name$name$name$name +test_expect_success 'preparation' ' + >"$name" && + git add "$name" && + git commit -m message && + echo a >"$name" && + git commit -m message "$name" +' + +while read cmd args +do + cat >expect <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + + EOF + test_expect_success "$cmd: a short graph bar does not extend to the full width" ' + git $cmd $args >output && + grep " | " output >actual && + test_cmp expect actual + ' + + cat >expect <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaa | 1 + + EOF + test_expect_success "$cmd --stat=width: name is chopped to leave room to the right of a short bar" ' + git $cmd $args --stat=40 >output && + grep " | " output >actual && + test_cmp expect actual + ' + + test_expect_success "$cmd --stat-width=width with long name" ' + git $cmd $args --stat-width=40 >output && + grep " | " output >actual && + test_cmp expect actual + ' + + cat >expect <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + + EOF + test_expect_success "$cmd --stat=...,name-width with long name" ' + git $cmd $args --stat=60,30 >output && + grep " | " output >actual && + test_cmp expect actual + ' + + test_expect_success "$cmd --stat-name-width with long name" ' + git $cmd $args --stat-name-width=30 >output && + grep " | " output >actual && + test_cmp expect actual + ' +done <<\EOF +format-patch -1 --stdout +diff HEAD^ HEAD --stat +show --stat +log -1 --stat +EOF + + +test_expect_success 'preparation for big change tests' ' + >abcd && + git add abcd && + git commit -m message && + i=0 && + while test $i -lt 1000 + do + echo $i && i=$(($i + 1)) + done >abcd && + git commit -m message abcd +' + +cat >expect80 <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF + +while read verb expect cmd args +do + test_expect_success "$cmd $verb COLUMNS (big change)" ' + COLUMNS=200 git $cmd $args >output + grep " | " output >actual && + test_cmp "$expect" actual + ' +done <<\EOF +ignores expect80 format-patch -1 --stdout +ignores expect80 diff HEAD^ HEAD --stat +ignores expect80 show --stat +ignores expect80 log -1 --stat +EOF + +cat >expect <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++ +EOF +while read cmd args +do + test_expect_success "$cmd --stat=width with big change" ' + git $cmd $args --stat=40 >output + grep " | " output >actual && + test_cmp expect actual + ' + + test_expect_success "$cmd --stat-width=width with big change" ' + git $cmd $args --stat-width=40 >output + grep " | " output >actual && + test_cmp expect actual + ' +done <<\EOF +format-patch -1 --stdout +diff HEAD^ HEAD --stat +show --stat +log -1 --stat +EOF + +test_expect_success 'preparation for long filename tests' ' + cp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && + git add aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && + git commit -m message +' + +cat >expect <<'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++ +EOF +while read cmd args +do + test_expect_success "$cmd --stat=width with big change and long name favors name part" ' + git $cmd $args --stat-width=60 >output && + grep " | " output >actual && + test_cmp expect actual + ' +done <<\EOF +format-patch -1 --stdout +diff HEAD^ HEAD --stat +show --stat +log -1 --stat +EOF + +cat >expect80 <<'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++ +EOF +while read verb expect cmd args +do + test_expect_success "$cmd $verb COLUMNS (long filename)" ' + COLUMNS=200 git $cmd $args >output + grep " | " output >actual && + test_cmp "$expect" actual + ' +done <<\EOF +ignores expect80 format-patch -1 --stdout +ignores expect80 diff HEAD^ HEAD --stat +ignores expect80 show --stat +ignores expect80 log -1 --stat +EOF + +cat >expect <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF +test_expect_success 'merge --stat ignores COLUMNS (big change)' ' + git checkout -b branch HEAD^^ && + COLUMNS=100 git merge --stat --no-ff master^ >output && + grep " | " output >actual + test_cmp expect actual +' + +cat >expect <<'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++ +EOF +test_expect_success 'merge --stat ignores COLUMNS (long filename)' ' + COLUMNS=100 git merge --stat --no-ff master >output && + grep " | " output >actual + test_cmp expect actual +' + +test_done -- cgit v0.10.2-6-g49f6 From af9fedc12873bf331019a502ed1fc944fa986713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 1 Mar 2012 13:26:39 +0100 Subject: diff --stat: use the full terminal width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Default to the real terminal width for diff --stat output, instead of the hard-coded 80 columns. Some projects (especially in Java), have long filename paths, with nested directories or long individual filenames. When files are renamed, the filename part in stat output can be almost useless. If the middle part between { and } is long (because the file was moved to a completely different directory), then most of the path would be truncated. It makes sense to detect and use the full terminal width and display full filenames if possible. The are commands like diff, show, and log, which can adapt the output to the terminal width. There are also commands like format-patch, whose output should be independent of the terminal width. Since it is safer to use the 80-column default, the real terminal width is only used if requested by the calling code by setting diffopts.stat_width=-1. Normally this value is 0, and can be set by the user only to a non-negative value, so -1 is safe to use internally. This patch only changes the diff builtin to use the full terminal width. Signed-off-by: Zbigniew Jędrzejewski-Szmek Signed-off-by: Junio C Hamano diff --git a/builtin/diff.c b/builtin/diff.c index 387afa7..81b6bae 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -285,6 +285,9 @@ int cmd_diff(int argc, const char **argv, const char *prefix) /* Otherwise, we are doing the usual "git" diff */ rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index; + /* Scale to real terminal size */ + rev.diffopt.stat_width = -1; + /* Default to let external and textconv be used */ DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL); DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV); diff --git a/diff.c b/diff.c index e0590a3..7478277 100644 --- a/diff.c +++ b/diff.c @@ -1343,7 +1343,10 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options) line_prefix = msg->buf; } - width = options->stat_width ? options->stat_width : 80; + if (options->stat_width == -1) + width = term_columns(); + else + width = options->stat_width ? options->stat_width : 80; name_width = options->stat_name_width ? options->stat_name_width : 50; count = options->stat_count ? options->stat_count : data->nr; diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index f766c47..29c06e5 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -83,6 +83,10 @@ cat >expect80 <<'EOF' abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ EOF +cat >expect200 <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF + while read verb expect cmd args do test_expect_success "$cmd $verb COLUMNS (big change)" ' @@ -92,7 +96,7 @@ do ' done <<\EOF ignores expect80 format-patch -1 --stdout -ignores expect80 diff HEAD^ HEAD --stat +respects expect200 diff HEAD^ HEAD --stat ignores expect80 show --stat ignores expect80 log -1 --stat EOF @@ -146,6 +150,9 @@ EOF cat >expect80 <<'EOF' ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++ EOF +cat >expect200 <<'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF while read verb expect cmd args do test_expect_success "$cmd $verb COLUMNS (long filename)" ' @@ -155,7 +162,7 @@ do ' done <<\EOF ignores expect80 format-patch -1 --stdout -ignores expect80 diff HEAD^ HEAD --stat +respects expect200 diff HEAD^ HEAD --stat ignores expect80 show --stat ignores expect80 log -1 --stat EOF -- cgit v0.10.2-6-g49f6 From 666c92a229de10f8bbfc33cf6f92aad8733f0002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 1 Mar 2012 13:26:40 +0100 Subject: show --stat: use the full terminal width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make show --stat behave like diff --stat and use the full terminal width. Signed-off-by: Zbigniew Jędrzejewski-Szmek Signed-off-by: Junio C Hamano diff --git a/builtin/log.c b/builtin/log.c index 7d1f6f8..d37ae26 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -447,6 +447,8 @@ int cmd_show(int argc, const char **argv, const char *prefix) rev.diff = 1; rev.always_show_header = 1; rev.no_walk = 1; + rev.diffopt.stat_width = -1; /* Scale to real terminal size */ + memset(&opt, 0, sizeof(opt)); opt.def = "HEAD"; opt.tweak = show_rev_tweak_rev; diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index 29c06e5..56d3899 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -97,7 +97,7 @@ do done <<\EOF ignores expect80 format-patch -1 --stdout respects expect200 diff HEAD^ HEAD --stat -ignores expect80 show --stat +respects expect200 show --stat ignores expect80 log -1 --stat EOF @@ -163,7 +163,7 @@ do done <<\EOF ignores expect80 format-patch -1 --stdout respects expect200 diff HEAD^ HEAD --stat -ignores expect80 show --stat +respects expect200 show --stat ignores expect80 log -1 --stat EOF -- cgit v0.10.2-6-g49f6 From 5e0ec15eb131075d0c3e61b33bcc7931bbc8bc08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 1 Mar 2012 13:26:41 +0100 Subject: log --stat: use the full terminal width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make log --stat behave like diff --stat and use the full terminal width. Signed-off-by: Zbigniew Jędrzejewski-Szmek Signed-off-by: Junio C Hamano diff --git a/builtin/log.c b/builtin/log.c index d37ae26..075a427 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -77,6 +77,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->diffopt.stat_width = -1; /* use full terminal width */ rev->abbrev_commit = default_abbrev_commit; rev->show_root_diff = default_show_root; rev->subject_prefix = fmt_patch_subject_prefix; diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index 56d3899..f81d427 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -98,7 +98,7 @@ done <<\EOF ignores expect80 format-patch -1 --stdout respects expect200 diff HEAD^ HEAD --stat respects expect200 show --stat -ignores expect80 log -1 --stat +respects expect200 log -1 --stat EOF cat >expect <<'EOF' @@ -164,7 +164,7 @@ done <<\EOF ignores expect80 format-patch -1 --stdout respects expect200 diff HEAD^ HEAD --stat respects expect200 show --stat -ignores expect80 log -1 --stat +respects expect200 log -1 --stat EOF cat >expect <<'EOF' -- cgit v0.10.2-6-g49f6 From 7a7159ace6c93ea6c55086dfc7ba7533a3e3c07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 1 Mar 2012 13:26:42 +0100 Subject: merge --stat: use the full terminal width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make merge --stat behave like diff --stat and use the full terminal width. Signed-off-by: Zbigniew Jędrzejewski-Szmek Signed-off-by: Junio C Hamano diff --git a/builtin/merge.c b/builtin/merge.c index b4fbc60..b1cd90c 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -399,6 +399,7 @@ static void finish(struct commit *head_commit, if (new_head && show_diffstat) { struct diff_options opts; diff_setup(&opts); + opts.stat_width = -1; /* use full terminal width */ opts.output_format |= DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; opts.detect_rename = DIFF_DETECT_RENAME; diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index f81d427..954c16f 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -168,9 +168,9 @@ respects expect200 log -1 --stat EOF cat >expect <<'EOF' - abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ EOF -test_expect_success 'merge --stat ignores COLUMNS (big change)' ' +test_expect_success 'merge --stat respects COLUMNS (big change)' ' git checkout -b branch HEAD^^ && COLUMNS=100 git merge --stat --no-ff master^ >output && grep " | " output >actual @@ -178,9 +178,9 @@ test_expect_success 'merge --stat ignores COLUMNS (big change)' ' ' cat >expect <<'EOF' - ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++ + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++++++++++++++++++++++ EOF -test_expect_success 'merge --stat ignores COLUMNS (long filename)' ' +test_expect_success 'merge --stat respects COLUMNS (long filename)' ' COLUMNS=100 git merge --stat --no-ff master >output && grep " | " output >actual test_cmp expect actual -- cgit v0.10.2-6-g49f6 From 1b058bc30df5f79fe7449cacd8ae7128944327f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 1 Mar 2012 13:26:43 +0100 Subject: diff --stat: use a maximum of 5/8 for the filename part MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The way that available columns are divided between the filename part and the graph part is modified to use as many columns as necessary for the filenames and the rest for the graph. If there isn't enough columns to print both the filename and the graph, at least 5/8 of available space is devoted to filenames. On a standard 80 column terminal, or if not connected to a terminal and using the default of 80 columns, this gives the same partition as before. The effect of this change is visible in the patch to the test vector in t4052; with a small change with long filename, it stops truncating the name part too short, and also allocates a bit more columns to the graph for larger changes. Signed-off-by: Zbigniew Jędrzejewski-Szmek Signed-off-by: Junio C Hamano diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 9f7cba2..6b9408f 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -53,13 +53,15 @@ endif::git-format-patch[] Generate a diff using the "patience diff" algorithm. --stat[=[,[,]]]:: - Generate a diffstat. You can override the default - output width for 80-column terminal by `--stat=`. - The width of the filename part can be controlled by - giving another width to it separated by a comma. + Generate a diffstat. By default, as much space as necessary + will be used for the filename part, and the rest for + the graph part. Maximum width defaults to terminal width, + or 80 columns if not connected to a terminal, and can be + overriden by ``. The width of the filename part can be + limited by giving another width `` after a comma. By giving a third parameter ``, you can limit the - output to the first `` lines, followed by - `...` if there are more. + output to the first `` lines, followed by `...` if + there are more. + These parameters can also be set individually with `--stat-width=`, `--stat-name-width=` and `--stat-count=`. diff --git a/diff.c b/diff.c index 7478277..1656310 100644 --- a/diff.c +++ b/diff.c @@ -1329,7 +1329,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options) int i, len, add, del, adds = 0, dels = 0; uintmax_t max_change = 0, max_len = 0; int total_files = data->nr; - int width, name_width, count; + int width, name_width, graph_width, number_width = 4, count; const char *reset, *add_c, *del_c; const char *line_prefix = ""; int extra_shown = 0; @@ -1343,28 +1343,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options) line_prefix = msg->buf; } - if (options->stat_width == -1) - width = term_columns(); - else - width = options->stat_width ? options->stat_width : 80; - name_width = options->stat_name_width ? options->stat_name_width : 50; count = options->stat_count ? options->stat_count : data->nr; - /* Sanity: give at least 5 columns to the graph, - * but leave at least 10 columns for the name. - */ - if (width < 25) - width = 25; - if (name_width < 10) - name_width = 10; - else if (width < name_width + 15) - name_width = width - 15; - - /* Find the longest filename and max number of changes */ reset = diff_get_color_opt(options, DIFF_RESET); add_c = diff_get_color_opt(options, DIFF_FILE_NEW); del_c = diff_get_color_opt(options, DIFF_FILE_OLD); + /* + * Find the longest filename and max number of changes + */ for (i = 0; (i < count) && (i < data->nr); i++) { struct diffstat_file *file = data->files[i]; uintmax_t change = file->added + file->deleted; @@ -1385,19 +1372,62 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options) } count = i; /* min(count, data->nr) */ - /* Compute the width of the graph part; - * 10 is for one blank at the beginning of the line plus - * " | count " between the name and the graph. + /* + * We have width = stat_width or term_columns() columns total. + * We want a maximum of min(max_len, stat_name_width) for the name part. + * We also need 1 for " " and 4 + decimal_width(max_change) + * for " | NNNN " and one the empty column at the end, altogether + * 6 + decimal_width(max_change). + * + * If there's not enough space, we will use the smaller of + * stat_name_width (if set) and 5/8*width for the filename, + * and the rest for constant elements + graph part. + * (5/8 gives 50 for filename and 30 for the constant parts + graph + * for the standard terminal size). * - * From here on, name_width is the width of the name area, - * and width is the width of the graph area. + * In other words: stat_width limits the maximum width, and + * stat_name_width fixes the maximum width of the filename, + * and is also used to divide available columns if there + * aren't enough. */ - name_width = (name_width < max_len) ? name_width : max_len; - if (width < (name_width + 10) + max_change) - width = width - (name_width + 10); + + if (options->stat_width == -1) + width = term_columns(); else - width = max_change; + width = options->stat_width ? options->stat_width : 80; + /* + * Guarantee 3/8*16==6 for the graph part + * and 5/8*16==10 for the filename part + */ + if (width < 16 + 6 + number_width) + width = 16 + 6 + number_width; + + /* + * First assign sizes that are wanted, ignoring available width. + */ + graph_width = max_change; + name_width = (options->stat_name_width > 0 && + options->stat_name_width < max_len) ? + options->stat_name_width : max_len; + + /* + * Adjust adjustable widths not to exceed maximum width + */ + if (name_width + number_width + 6 + graph_width > width) { + if (graph_width > width * 3/8 - number_width - 6) + graph_width = width * 3/8 - number_width - 6; + if (name_width > width - number_width - 6 - graph_width) + name_width = width - number_width - 6 - graph_width; + else + graph_width = width - number_width - 6 - name_width; + } + + /* + * From here name_width is the width of the name area, + * and graph_width is the width of the graph area. + * max_change is used to scale graph properly. + */ for (i = 0; i < count; i++) { const char *prefix = ""; char *name = data->files[i]->print_name; @@ -1453,18 +1483,18 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options) adds += add; dels += del; - if (width <= max_change) { + if (graph_width <= max_change) { int total = add + del; - total = scale_linear(add + del, width, max_change); + total = scale_linear(add + del, graph_width, max_change); if (total < 2 && add && del) /* width >= 2 due to the sanity check */ total = 2; if (add < del) { - add = scale_linear(add, width, max_change); + add = scale_linear(add, graph_width, max_change); del = total - add; } else { - del = scale_linear(del, width, max_change); + del = scale_linear(del, graph_width, max_change); add = total - del; } } diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index 954c16f..d0ed0dc 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -22,18 +22,18 @@ test_expect_success 'preparation' ' while read cmd args do cat >expect <<-'EOF' - ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + EOF - test_expect_success "$cmd: a short graph bar does not extend to the full width" ' + test_expect_success "$cmd: small change with long name gives more space to the name" ' git $cmd $args >output && grep " | " output >actual && test_cmp expect actual ' cat >expect <<-'EOF' - ...aaaaaaaaaaaaaaaaaaaaaa | 1 + + ...aaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + EOF - test_expect_success "$cmd --stat=width: name is chopped to leave room to the right of a short bar" ' + test_expect_success "$cmd --stat=width: a long name is given more room when the bar is short" ' git $cmd $args --stat=40 >output && grep " | " output >actual && test_cmp expect actual @@ -131,11 +131,11 @@ test_expect_success 'preparation for long filename tests' ' ' cat >expect <<'EOF' - ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++ + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++ EOF while read cmd args do - test_expect_success "$cmd --stat=width with big change and long name favors name part" ' + test_expect_success "$cmd --stat=width with big change is more balanced" ' git $cmd $args --stat-width=60 >output && grep " | " output >actual && test_cmp expect actual @@ -151,7 +151,7 @@ cat >expect80 <<'EOF' ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++ EOF cat >expect200 <<'EOF' - ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ EOF while read verb expect cmd args do @@ -178,7 +178,7 @@ test_expect_success 'merge --stat respects COLUMNS (big change)' ' ' cat >expect <<'EOF' - ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++++++++++++++++++++++ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++ EOF test_expect_success 'merge --stat respects COLUMNS (long filename)' ' COLUMNS=100 git merge --stat --no-ff master >output && -- cgit v0.10.2-6-g49f6 From c4432d5511f2897b56cd921632c86c1e2ca78159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 1 Mar 2012 13:26:44 +0100 Subject: diff --stat: add a test for output with COLUMNS=40 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for the introduction on the limit of the width of the graph part, a new test with COLUMNS=40 is added to check that the environment variable influences diff, show, log, but not format-patch. A new test is added because limiting the graph part makes COLUMNS=200 stop influencing diff --stat behaviour, which isn't wide enough now. The old test with COLUMNS=200 is retained to check for regressions. Signed-off-by: Zbigniew Jędrzejewski-Szmek Signed-off-by: Junio C Hamano diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index d0ed0dc..9a8f62d 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -101,6 +101,25 @@ respects expect200 show --stat respects expect200 log -1 --stat EOF +cat >expect40 <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++ +EOF + +while read verb expect cmd args +do + test_expect_success "$cmd $verb not enough COLUMNS (big change)" ' + COLUMNS=40 git $cmd $args >output + grep " | " output >actual && + test_cmp "$expect" actual + ' +done <<\EOF +ignores expect80 format-patch -1 --stdout +respects expect40 diff HEAD^ HEAD --stat +respects expect40 show --stat +respects expect40 log -1 --stat +EOF + + cat >expect <<'EOF' abcd | 1000 ++++++++++++++++++++++++++ EOF -- cgit v0.10.2-6-g49f6 From 969fe57b844a514747c1d5d66e0698dc53ed473d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 1 Mar 2012 13:26:45 +0100 Subject: diff --stat: enable limiting of the graph part MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new option --stat-graph-width= can be used to limit the width of the graph part even is more space is available. Up to columns will be used for the graph. If commits changing a lot of lines are displayed in a wide terminal window (200 or more columns), and the +- graph uses the full width, the output can be hard to comfortably scan with a horizontal movement of human eyes. Messages wrapped to about 80 columns would be interspersed with very long +- lines. It makes sense to limit the width of the graph part to a fixed value (e.g. 70 columns), even if more columns are available. Signed-off-by: Zbigniew Jędrzejewski-Szmek Signed-off-by: Junio C Hamano diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 6b9408f..d34efd5 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -59,6 +59,8 @@ endif::git-format-patch[] or 80 columns if not connected to a terminal, and can be overriden by ``. The width of the filename part can be limited by giving another width `` after a comma. + The width of the graph part can be limited by using + `--stat-graph-width=`. By giving a third parameter ``, you can limit the output to the first `` lines, followed by `...` if there are more. diff --git a/diff.c b/diff.c index 1656310..8f2abc8 100644 --- a/diff.c +++ b/diff.c @@ -1375,13 +1375,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options) /* * We have width = stat_width or term_columns() columns total. * We want a maximum of min(max_len, stat_name_width) for the name part. + * We want a maximum of min(max_change, stat_graph_width) for the +- part. * We also need 1 for " " and 4 + decimal_width(max_change) * for " | NNNN " and one the empty column at the end, altogether * 6 + decimal_width(max_change). * * If there's not enough space, we will use the smaller of * stat_name_width (if set) and 5/8*width for the filename, - * and the rest for constant elements + graph part. + * and the rest for constant elements + graph part, but no more + * than stat_graph_width for the graph part. * (5/8 gives 50 for filename and 30 for the constant parts + graph * for the standard terminal size). * @@ -1406,7 +1408,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options) /* * First assign sizes that are wanted, ignoring available width. */ - graph_width = max_change; + graph_width = (options->stat_graph_width && + options->stat_graph_width < max_change) ? + options->stat_graph_width : max_change; name_width = (options->stat_name_width > 0 && options->stat_name_width < max_len) ? options->stat_name_width : max_len; @@ -1417,6 +1421,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options) if (name_width + number_width + 6 + graph_width > width) { if (graph_width > width * 3/8 - number_width - 6) graph_width = width * 3/8 - number_width - 6; + if (options->stat_graph_width && + graph_width > options->stat_graph_width) + graph_width = options->stat_graph_width; if (name_width > width - number_width - 6 - graph_width) name_width = width - number_width - 6 - graph_width; else @@ -3289,6 +3296,7 @@ static int stat_opt(struct diff_options *options, const char **av) char *end; int width = options->stat_width; int name_width = options->stat_name_width; + int graph_width = options->stat_graph_width; int count = options->stat_count; int argcount = 1; @@ -3317,6 +3325,16 @@ static int stat_opt(struct diff_options *options, const char **av) name_width = strtoul(av[1], &end, 10); argcount = 2; } + } else if (!prefixcmp(arg, "-graph-width")) { + arg += strlen("-graph-width"); + if (*arg == '=') + graph_width = strtoul(arg + 1, &end, 10); + else if (!*arg && !av[1]) + die("Option '--stat-graph-width' requires a value"); + else if (!*arg) { + graph_width = strtoul(av[1], &end, 10); + argcount = 2; + } } else if (!prefixcmp(arg, "-count")) { arg += strlen("-count"); if (*arg == '=') @@ -3342,6 +3360,7 @@ static int stat_opt(struct diff_options *options, const char **av) return 0; options->output_format |= DIFF_FORMAT_DIFFSTAT; options->stat_name_width = name_width; + options->stat_graph_width = graph_width; options->stat_width = width; options->stat_count = count; return argcount; diff --git a/diff.h b/diff.h index ae71f4c..2021a1d 100644 --- a/diff.h +++ b/diff.h @@ -129,6 +129,7 @@ struct diff_options { int stat_width; int stat_name_width; + int stat_graph_width; int stat_count; const char *word_regex; enum diff_words_type word_diff; diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index 9a8f62d..3d823af 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -136,6 +136,12 @@ do grep " | " output >actual && test_cmp expect actual ' + + test_expect_success "$cmd --stat-graph--width with big change" ' + git $cmd $args --stat-graph-width=26 >output + grep " | " output >actual && + test_cmp expect actual + ' done <<\EOF format-patch -1 --stdout diff HEAD^ HEAD --stat -- cgit v0.10.2-6-g49f6 From df44483a5dde62f4b49c80fd90d7fe12ddcfb084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 1 Mar 2012 13:26:46 +0100 Subject: diff --stat: add config option to limit graph width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Config option diff.statGraphWidth= is equivalent to --stat-graph-width=, except that the config option is ignored by format-patch. For the graph-width limiting to be usable, it should happen 'automatically' once configured, hence the config option. Nevertheless, graph width limiting only makes sense when used on a wide terminal, so it should not influence the output of format-patch, which adheres to the 80-column standard. Signed-off-by: Zbigniew Jędrzejewski-Szmek Signed-off-by: Junio C Hamano diff --git a/Documentation/diff-config.txt b/Documentation/diff-config.txt index 1aed79e..6aa1be0 100644 --- a/Documentation/diff-config.txt +++ b/Documentation/diff-config.txt @@ -52,6 +52,10 @@ directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: `files,10,cumulative`. +diff.statGraphWidth:: + Limit the width of the graph part in --stat output. If set, applies + to all commands generating --stat outuput except format-patch. + diff.external:: If this config variable is set, diff generation is not performed using the internal diff machinery, but using the diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index d34efd5..87f0a5f 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -54,13 +54,15 @@ endif::git-format-patch[] --stat[=[,[,]]]:: Generate a diffstat. By default, as much space as necessary - will be used for the filename part, and the rest for - the graph part. Maximum width defaults to terminal width, - or 80 columns if not connected to a terminal, and can be - overriden by ``. The width of the filename part can be - limited by giving another width `` after a comma. - The width of the graph part can be limited by using - `--stat-graph-width=`. + will be used for the filename part, and the rest for the graph + part. Maximum width defaults to terminal width, or 80 columns + if not connected to a terminal, and can be overriden by + ``. The width of the filename part can be limited by + giving another width `` after a comma. The width + of the graph part can be limited by using + `--stat-graph-width=` (affects all commands generating + a stat graph) or by setting `diff.statGraphWidth=` + (does not affect `git format-patch`). By giving a third parameter ``, you can limit the output to the first `` lines, followed by `...` if there are more. diff --git a/builtin/diff.c b/builtin/diff.c index 81b6bae..424c815 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -285,8 +285,9 @@ int cmd_diff(int argc, const char **argv, const char *prefix) /* Otherwise, we are doing the usual "git" diff */ rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index; - /* Scale to real terminal size */ + /* Scale to real terminal size and respect statGraphWidth config */ rev.diffopt.stat_width = -1; + rev.diffopt.stat_graph_width = -1; /* Default to let external and textconv be used */ DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL); diff --git a/builtin/log.c b/builtin/log.c index 075a427..8a47012 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -78,6 +78,7 @@ static void cmd_log_init_defaults(struct rev_info *rev) rev->verbose_header = 1; DIFF_OPT_SET(&rev->diffopt, RECURSIVE); rev->diffopt.stat_width = -1; /* use full terminal width */ + rev->diffopt.stat_graph_width = -1; /* respect statGraphWidth config */ rev->abbrev_commit = default_abbrev_commit; rev->show_root_diff = default_show_root; rev->subject_prefix = fmt_patch_subject_prefix; diff --git a/builtin/merge.c b/builtin/merge.c index b1cd90c..34a5034 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -400,6 +400,7 @@ static void finish(struct commit *head_commit, struct diff_options opts; diff_setup(&opts); opts.stat_width = -1; /* use full terminal width */ + opts.stat_graph_width = -1; /* respect statGraphWidth config */ opts.output_format |= DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; opts.detect_rename = DIFF_DETECT_RENAME; diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 78be195..bacf403 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -2118,6 +2118,7 @@ _git_config () core.whitespace core.worktree diff.autorefreshindex + diff.statGraphWidth diff.external diff.ignoreSubmodules diff.mnemonicprefix diff --git a/diff.c b/diff.c index 8f2abc8..4525cda 100644 --- a/diff.c +++ b/diff.c @@ -31,6 +31,7 @@ static const char *external_diff_cmd_cfg; int diff_auto_refresh_index = 1; static int diff_mnemonic_prefix; static int diff_no_prefix; +static int diff_stat_graph_width; static int diff_dirstat_permille_default = 30; static struct diff_options default_diff_options; @@ -156,6 +157,10 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) diff_no_prefix = git_config_bool(var, value); return 0; } + if (!strcmp(var, "diff.statgraphwidth")) { + diff_stat_graph_width = git_config_int(var, value); + return 0; + } if (!strcmp(var, "diff.external")) return git_config_string(&external_diff_cmd_cfg, var, value); if (!strcmp(var, "diff.wordregex")) @@ -1398,6 +1403,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options) else width = options->stat_width ? options->stat_width : 80; + if (options->stat_graph_width == -1) + options->stat_graph_width = diff_stat_graph_width; + /* * Guarantee 3/8*16==6 for the graph part * and 5/8*16==10 for the filename part diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index 3d823af..328aa8f 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -112,6 +112,12 @@ do grep " | " output >actual && test_cmp "$expect" actual ' + + test_expect_success "$cmd $verb statGraphWidth config" ' + git -c diff.statGraphWidth=26 $cmd $args >output + grep " | " output >actual && + test_cmp "$expect" actual + ' done <<\EOF ignores expect80 format-patch -1 --stdout respects expect40 diff HEAD^ HEAD --stat -- cgit v0.10.2-6-g49f6 From 13a4899886958c211b96bced228fdaaa42674491 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 29 Feb 2012 18:14:14 -0800 Subject: t4011: modernise style Match the style to more modern test scripts, namely: - The first line of each test has prereq, title and opening sq for the script body. This makes the test shorter while reducing the need for backslashes. - Be prepared for the case in which the previous test may have failed. If a test wants to start from not having "frotz" that the previous test may have created, write "rm -f frotz", not "rm frotz". - Prepare the expected output inside your own test. - The order of comparison to check the result is "diff expected actual", so that the output will show how the output from the git you just broke is different from what is expected. - Write no SP between redirection '>' (or '<' for that matter) and the filename. Signed-off-by: Junio C Hamano diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh index 408a19c..cb47ec1 100755 --- a/t/t4011-diff-symlink.sh +++ b/t/t4011-diff-symlink.sh @@ -9,85 +9,81 @@ test_description='Test diff of symlinks. . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh -cat > expected << EOF -diff --git a/frotz b/frotz -new file mode 120000 -index 0000000..7c465af ---- /dev/null -+++ b/frotz -@@ -0,0 +1 @@ -+xyzzy -\ No newline at end of file -EOF - -test_expect_success SYMLINKS \ - 'diff new symlink' \ - 'ln -s xyzzy frotz && - git update-index && - tree=$(git write-tree) && - git update-index --add frotz && - GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree > current && - compare_diff_patch current expected' - -test_expect_success SYMLINKS \ - 'diff unchanged symlink' \ - 'tree=$(git write-tree) && - git update-index frotz && - test -z "$(git diff-index --name-only $tree)"' - -cat > expected << EOF -diff --git a/frotz b/frotz -deleted file mode 120000 -index 7c465af..0000000 ---- a/frotz -+++ /dev/null -@@ -1 +0,0 @@ --xyzzy -\ No newline at end of file -EOF - -test_expect_success SYMLINKS \ - 'diff removed symlink' \ - 'mv frotz frotz2 && - git diff-index -M -p $tree > current && - compare_diff_patch current expected' +test_expect_success SYMLINKS 'diff new symlink' ' + cat >expected <<-\EOF && + diff --git a/frotz b/frotz + new file mode 120000 + index 0000000..7c465af + --- /dev/null + +++ b/frotz + @@ -0,0 +1 @@ + +xyzzy + \ No newline at end of file + EOF + ln -s xyzzy frotz && + git update-index && + tree=$(git write-tree) && + git update-index --add frotz && + GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current && + compare_diff_patch expected current +' -cat > expected << EOF -diff --git a/frotz b/frotz -EOF +test_expect_success SYMLINKS 'diff unchanged symlink' ' + tree=$(git write-tree) && + git update-index frotz && + test -z "$(git diff-index --name-only $tree)" +' -test_expect_success SYMLINKS \ - 'diff identical, but newly created symlink' \ - 'ln -s xyzzy frotz && - git diff-index -M -p $tree > current && - compare_diff_patch current expected' +test_expect_success SYMLINKS 'diff removed symlink' ' + cat >expected <<-\EOF && + diff --git a/frotz b/frotz + deleted file mode 120000 + index 7c465af..0000000 + --- a/frotz + +++ /dev/null + @@ -1 +0,0 @@ + -xyzzy + \ No newline at end of file + EOF + mv frotz frotz2 && + git diff-index -M -p $tree >current && + compare_diff_patch expected current +' -cat > expected << EOF -diff --git a/frotz b/frotz -index 7c465af..df1db54 120000 ---- a/frotz -+++ b/frotz -@@ -1 +1 @@ --xyzzy -\ No newline at end of file -+yxyyz -\ No newline at end of file -EOF +test_expect_success SYMLINKS 'diff identical, but newly created symlink' ' + cat >expected <<-\EOF && + diff --git a/frotz b/frotz + EOF + ln -s xyzzy frotz && + git diff-index -M -p $tree >current && + compare_diff_patch expected current +' -test_expect_success SYMLINKS \ - 'diff different symlink' \ - 'rm frotz && - ln -s yxyyz frotz && - git diff-index -M -p $tree > current && - compare_diff_patch current expected' +test_expect_success SYMLINKS 'diff different symlink' ' + cat >expected <<-\EOF && + diff --git a/frotz b/frotz + index 7c465af..df1db54 120000 + --- a/frotz + +++ b/frotz + @@ -1 +1 @@ + -xyzzy + \ No newline at end of file + +yxyyz + \ No newline at end of file + EOF + rm -f frotz && + ln -s yxyyz frotz && + git diff-index -M -p $tree >current && + compare_diff_patch expected current +' -test_expect_success SYMLINKS \ - 'diff symlinks with non-existing targets' \ - 'ln -s narf pinky && - ln -s take\ over brain && - test_must_fail git diff --no-index pinky brain > output 2> output.err && - grep narf output && - ! grep error output.err' +test_expect_success SYMLINKS 'diff symlinks with non-existing targets' ' + ln -s narf pinky && + ln -s take\ over brain && + test_must_fail git diff --no-index pinky brain >output 2>output.err && + grep narf output && + ! test -s output.err +' test_expect_success SYMLINKS 'setup symlinks with attributes' ' echo "*.bin diff=bin" >>.gitattributes && @@ -96,19 +92,19 @@ test_expect_success SYMLINKS 'setup symlinks with attributes' ' git add -N file.bin link.bin ' -cat >expect <<'EOF' -diff --git a/file.bin b/file.bin -index e69de29..d95f3ad 100644 -Binary files a/file.bin and b/file.bin differ -diff --git a/link.bin b/link.bin -index e69de29..dce41ec 120000 ---- a/link.bin -+++ b/link.bin -@@ -0,0 +1 @@ -+file.bin -\ No newline at end of file -EOF test_expect_success SYMLINKS 'symlinks do not respect userdiff config by path' ' + cat >expect <<-\EOF && + diff --git a/file.bin b/file.bin + index e69de29..d95f3ad 100644 + Binary files a/file.bin and b/file.bin differ + diff --git a/link.bin b/link.bin + index e69de29..dce41ec 120000 + --- a/link.bin + +++ b/link.bin + @@ -0,0 +1 @@ + +file.bin + \ No newline at end of file + EOF git config diff.bin.binary true && git diff file.bin link.bin >actual && test_cmp expect actual -- cgit v0.10.2-6-g49f6 From 5597e84b514454f18bba7b13eee2feea04f0165b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 29 Feb 2012 18:14:15 -0800 Subject: t4011: illustrate "diff-index -p" on stat-dirty paths The plumbing that looks at the working tree, i.e. "diff-index" and "diff-files", always emit the "diff --git a/path b/path" header lines without anything else for paths that are only stat-dirty (i.e. different only because the cached stat information in the index no longer matches that of the working tree, but the real contents are the same), when these commands are run with "-p" option to produce patches. Illustrate this current behaviour. Also demonstrate that with the "-w" option, we (correctly) hold off showing a "diff --git" header until actual differences have been found. This also suppresses the header for merely stat-dirty files, which is inconsistent. Signed-off-by: Junio C Hamano diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh index cb47ec1..164f153 100755 --- a/t/t4011-diff-symlink.sh +++ b/t/t4011-diff-symlink.sh @@ -9,7 +9,7 @@ test_description='Test diff of symlinks. . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh -test_expect_success SYMLINKS 'diff new symlink' ' +test_expect_success SYMLINKS 'diff new symlink and file' ' cat >expected <<-\EOF && diff --git a/frotz b/frotz new file mode 120000 @@ -19,22 +19,30 @@ test_expect_success SYMLINKS 'diff new symlink' ' @@ -0,0 +1 @@ +xyzzy \ No newline at end of file + diff --git a/nitfol b/nitfol + new file mode 100644 + index 0000000..7c465af + --- /dev/null + +++ b/nitfol + @@ -0,0 +1 @@ + +xyzzy EOF ln -s xyzzy frotz && + echo xyzzy >nitfol && git update-index && tree=$(git write-tree) && - git update-index --add frotz && + git update-index --add frotz nitfol && GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current && compare_diff_patch expected current ' -test_expect_success SYMLINKS 'diff unchanged symlink' ' +test_expect_success SYMLINKS 'diff unchanged symlink and file' ' tree=$(git write-tree) && - git update-index frotz && + git update-index frotz nitfol && test -z "$(git diff-index --name-only $tree)" ' -test_expect_success SYMLINKS 'diff removed symlink' ' +test_expect_success SYMLINKS 'diff removed symlink and file' ' cat >expected <<-\EOF && diff --git a/frotz b/frotz deleted file mode 120000 @@ -44,22 +52,38 @@ test_expect_success SYMLINKS 'diff removed symlink' ' @@ -1 +0,0 @@ -xyzzy \ No newline at end of file + diff --git a/nitfol b/nitfol + deleted file mode 100644 + index 7c465af..0000000 + --- a/nitfol + +++ /dev/null + @@ -1 +0,0 @@ + -xyzzy EOF mv frotz frotz2 && + mv nitfol nitfol2 && git diff-index -M -p $tree >current && compare_diff_patch expected current ' -test_expect_success SYMLINKS 'diff identical, but newly created symlink' ' +test_expect_success SYMLINKS 'diff identical, but newly created symlink and file' ' cat >expected <<-\EOF && diff --git a/frotz b/frotz + diff --git a/nitfol b/nitfol EOF + rm -f frotz nitfol && + echo xyzzy >nitfol && + test-chmtime +10 nitfol && ln -s xyzzy frotz && git diff-index -M -p $tree >current && + compare_diff_patch expected current && + + >expected && + git diff-index -M -p -w $tree >current && compare_diff_patch expected current ' -test_expect_success SYMLINKS 'diff different symlink' ' +test_expect_success SYMLINKS 'diff different symlink and file' ' cat >expected <<-\EOF && diff --git a/frotz b/frotz index 7c465af..df1db54 120000 @@ -70,9 +94,17 @@ test_expect_success SYMLINKS 'diff different symlink' ' \ No newline at end of file +yxyyz \ No newline at end of file + diff --git a/nitfol b/nitfol + index 7c465af..df1db54 100644 + --- a/nitfol + +++ b/nitfol + @@ -1 +1 @@ + -xyzzy + +yxyyz EOF rm -f frotz && ln -s yxyyz frotz && + echo yxyyz >nitfol && git diff-index -M -p $tree >current && compare_diff_patch expected current ' -- cgit v0.10.2-6-g49f6 From b3f01ff29f7131e959bcfdfd004744d74d5fa319 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 29 Feb 2012 18:14:16 -0800 Subject: diff -p: squelch "diff --git" header for stat-dirty paths The plumbing "diff" commands look at the working tree files without refreshing the index themselves for performance reasons (the calling script is expected to do that upfront just once, before calling one or more of them). In the early days of git, they showed the "diff --git" header before they actually ask the xdiff machinery to produce patches, and ended up showing only these headers if the real contents are the same and the difference they noticed was only because the stat info cached in the index did not match that of the working tree. It was too late for the implementation to take the header that it already emitted back. But 3e97c7c (No diff -b/-w output for all-whitespace changes, 2009-11-19) introduced necessary logic to keep the meta-information headers in a strbuf and delay their output until the xdiff machinery noticed actual changes. This was primarily in order to generate patches that ignore whitespaces. When operating under "-w" mode, we wouldn't know if the header is needed until we actually look at the resulting patch, so it was a sensible thing to do, but we did not realize that the same reasoning applies to stat-dirty paths. Later, 296c6bb (diff: fix "git show -C -C" output when renaming a binary file, 2010-05-26) generalized this machinery and added must_show_header toggle. This is turned on when the header must be shown even when there is no patch to be produced, e.g. only the mode was changed, or the path was renamed, without changing the contents. However, when it did so, it still kept the special case for the "-w" mode, which meant that the plumbing would keep showing these phantom changes. This corrects this historical inconsistency by allowing the plumbing to omit paths that are only stat-dirty from its output in the same way as it handles whitespace only changes under "-w" option. The change in the behaviour can be seen in the updated test. Signed-off-by: Junio C Hamano diff --git a/diff.c b/diff.c index c8e4366..0ecbf32 100644 --- a/diff.c +++ b/diff.c @@ -1972,7 +1972,7 @@ static void builtin_diff(const char *name_a, struct emit_callback ecbdata; const struct userdiff_funcname *pe; - if (!DIFF_XDL_TST(o, WHITESPACE_FLAGS) || must_show_header) { + if (must_show_header) { fprintf(o->file, "%s", header.buf); strbuf_reset(&header); } diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh index 164f153..f0d5041 100755 --- a/t/t4011-diff-symlink.sh +++ b/t/t4011-diff-symlink.sh @@ -67,10 +67,7 @@ test_expect_success SYMLINKS 'diff removed symlink and file' ' ' test_expect_success SYMLINKS 'diff identical, but newly created symlink and file' ' - cat >expected <<-\EOF && - diff --git a/frotz b/frotz - diff --git a/nitfol b/nitfol - EOF + >expected && rm -f frotz nitfol && echo xyzzy >nitfol && test-chmtime +10 nitfol && -- cgit v0.10.2-6-g49f6 From 61821aaa12ed698f2e94bb15fea958c598e4f231 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Thu, 1 Mar 2012 22:40:48 +0100 Subject: t5510: refactor bundle->pack conversion It's not so much a conversion as a "strip everything up to and including the first blank line", but it will come in handy again. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index e0af4c4..6508d8a 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -14,6 +14,14 @@ test_bundle_object_count () { test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l) } +convert_bundle_to_pack () { + while read x && test -n "$x" + do + :; + done + cat +} + test_expect_success setup ' echo >file original && git add file && @@ -207,13 +215,7 @@ test_expect_success 'unbundle 1' ' test_expect_success 'bundle 1 has only 3 files ' ' cd "$D" && - ( - while read x && test -n "$x" - do - :; - done - cat - ) bundle.pack && + convert_bundle_to_pack bundle.pack && git index-pack bundle.pack && test_bundle_object_count bundle.pack 3 ' @@ -230,13 +232,7 @@ test_expect_success 'bundle does not prerequisite objects' ' git add file2 && git commit -m add.file2 file2 && git bundle create bundle3 -1 HEAD && - ( - while read x && test -n "$x" - do - :; - done - cat - ) bundle.pack && + convert_bundle_to_pack bundle.pack && git index-pack bundle.pack && test_bundle_object_count bundle.pack 3 ' -- cgit v0.10.2-6-g49f6 From aa9828561e562a0b9ca559be4225de679b8e8be3 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Thu, 1 Mar 2012 22:40:49 +0100 Subject: t5510: ensure we stay in the toplevel test dir The last test descended into a subdir without ever re-emerging, which is not so nice to the next test writer. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 6508d8a..d7eca5d 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -430,14 +430,16 @@ test_expect_success 'fetch --dry-run' ' ' test_expect_success "should be able to fetch with duplicate refspecs" ' - mkdir dups && - cd dups && - git init && - git config branch.master.remote three && - git config remote.three.url ../three/.git && - git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* && - git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* && - git fetch three + mkdir dups && + ( + cd dups && + git init && + git config branch.master.remote three && + git config remote.three.url ../three/.git && + git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* && + git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* && + git fetch three + ) ' test_done -- cgit v0.10.2-6-g49f6 From efe4be12490ab684786c48135731c4d2648bbecc Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Thu, 1 Mar 2012 22:40:51 +0100 Subject: bundle: keep around names passed to add_pending_object() The 'name' field passed to add_pending_object() is used to later deduplicate in object_array_remove_duplicates(). git-bundle had a bug in this area since 18449ab (git-bundle: avoid packing objects which are in the prerequisites, 2007-03-08): it passed the name of each boundary object in a static buffer. In other words, all that object_array_remove_duplicates() saw was the name of the *last* added boundary object. The recent switch to a strbuf in bc2fed4 (bundle: use a strbuf to scan the log for boundary commits, 2012-02-22) made this slightly worse: we now free the buffer at the end, so it is not even guaranteed that it still points into addressable memory by the time object_array_remove_ duplicates looks at it. On the plus side however, it was now detectable by valgrind. The fix is easy: pass a copy of the string to add_pending_object. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano diff --git a/bundle.c b/bundle.c index 4497343..6c4695e 100644 --- a/bundle.c +++ b/bundle.c @@ -273,7 +273,7 @@ int create_bundle(struct bundle_header *header, const char *path, if (!get_sha1_hex(buf.buf + 1, sha1)) { struct object *object = parse_object(sha1); object->flags |= UNINTERESTING; - add_pending_object(&revs, object, buf.buf); + add_pending_object(&revs, object, xstrdup(buf.buf)); } } else if (!get_sha1_hex(buf.buf, sha1)) { struct object *object = parse_object(sha1); diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index d7eca5d..9d72b16 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -442,4 +442,19 @@ test_expect_success "should be able to fetch with duplicate refspecs" ' ) ' +test_expect_success 'all boundary commits are excluded' ' + test_commit base && + test_commit oneside && + git checkout HEAD^ && + test_commit otherside && + git checkout master && + test_tick && + git merge otherside && + ad=$(git log --no-walk --format=%ad HEAD) && + git bundle create twoside-boundary.bdl master --since="$ad" && + convert_bundle_to_pack twoside-boundary.pack && + pack=$(git index-pack --fix-thin --stdin Date: Fri, 2 Mar 2012 10:29:53 +0800 Subject: Update l10n guide: change the repository URL, etc Host the l10n coordinator repository in a dedicated github organization account "git-l10n", so that the team may have a more permanent home. Also add a hint about reference of TEAMS file for l10n contributors. Update TEAMS file with new zh_CN l10n team members and a repository URL. Signed-off-by: Jiang Xin Signed-off-by: Junio C Hamano diff --git a/po/README b/po/README index 6480882..188ea2c 100644 --- a/po/README +++ b/po/README @@ -6,22 +6,23 @@ describes how you can contribute to the effort of enhancing the language coverage and maintaining the translation. The localization (l10n) coordinator, Jiang Xin , -coordinates our localization effort in his repository: +coordinates our localization effort in the l10 coordinator repository: - https://github.com/gotgit/git-po/ + https://github.com/git-l10n/git-po/ -As a contributor for a language XX, you would fork this repository, -prepare and/or update the translated message file po/XX.po (described -later), and ask the l10n coordinator to pull your work. +As a contributor for a language XX, you should first check TEAMS file in +this directory to see whether a dedicated repository for your language XX +exists. Fork the dedicated repository and start to work if it exists. + +If you are the first contributor for the language XX, please fork this +repository, prepare and/or update the translated message file po/XX.po +(described later), and ask the l10n coordinator to pull your work. If there are multiple contributors for the same language, please first coordinate among yourselves and nominate the team leader for your language, so that the l10n coordinator only needs to interact with one person per language. -For the list of exiting translations and language teams, see TEAMS file in -this directory. - The overall data-flow looks like this: +-------------------+ +------------------+ diff --git a/po/TEAMS b/po/TEAMS index 8ee6199..1d173ac 100644 --- a/po/TEAMS +++ b/po/TEAMS @@ -5,6 +5,11 @@ Language: is (Icelandic) Leader: Ævar Arnfjörð Bjarmason Language: zh_CN (Simplified Chinese) +Repository: https://github.com/gotgit/git-po-zh_CN/ Leader: Jiang Xin -Members: Yichao Yu - Riku +Members: Riku + Zhuang Ya + Lian Cheng + Yichao Yu + ws3389 + Thynson -- cgit v0.10.2-6-g49f6 From 70eb130768d17c33b9efbf60d7953cf6a57daecb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 29 Feb 2012 11:13:22 -0800 Subject: Documentation: do not assume that n > 1 in ~$n We explained ~ as th generation grand-parent, but a reader got confused by the "grand-" part when is 1. Reword it with "ancestor"; with the "generation" and "following only the first parents" around there, what we try to describe should be clear enough now. Noticed-by: Luke Diamand Helped-by: Thomas Rast Helped-by: Andreas Ericsson Signed-off-by: Junio C Hamano diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt index b290b61..1725661 100644 --- a/Documentation/revisions.txt +++ b/Documentation/revisions.txt @@ -101,7 +101,7 @@ the '$GIT_DIR/refs' directory or from the '$GIT_DIR/packed-refs' file. '{tilde}', e.g. 'master{tilde}3':: A suffix '{tilde}' to a revision parameter means the commit - object that is the th generation grand-parent of the named + object that is the th generation ancestor of the named commit object, following only the first parents. I.e. '{tilde}3' is equivalent to '{caret}{caret}{caret}' which is equivalent to '{caret}1{caret}1{caret}1'. See below for an illustration of -- cgit v0.10.2-6-g49f6 From 222433ee4b57750174875ce6b252d10c009a1fa9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 1 Mar 2012 21:08:07 -0800 Subject: Update draft release notes to 1.7.10 Signed-off-by: Junio C Hamano diff --git a/Documentation/RelNotes/1.7.10.txt b/Documentation/RelNotes/1.7.10.txt index 071e40c..7813ea1 100644 --- a/Documentation/RelNotes/1.7.10.txt +++ b/Documentation/RelNotes/1.7.10.txt @@ -11,17 +11,6 @@ UI, Workflows & Features to be the localization coordinator. An initial set of translated messages for simplified chinese is available. - * Improved handling of views, labels and branches in git-p4 (in contrib). - - * "git-p4" (in contrib) suffered from unnecessary merge conflicts when - p4 expanded the embedded $RCS$-like keywords; it can be now told to - unexpand them. - - * Some "git-svn" updates. - - * "vcs-svn"/"svn-fe" learned to read dumps with svn-deltas and - support incremental imports. - * The configuration mechanism learned an "include" facility; an assignment to the include.path pseudo-variable causes the named file to be included in-place when Git looks up configuration @@ -31,6 +20,10 @@ UI, Workflows & Features recorded contents "more useful", and allowed to fail; a filter can new optionally be marked as "required". + * Options whose names begin with "--no-" (e.g. the "--no-verify" + option of the "git commit" command) can be negated by omitting + "no-" from its name, e.g. "git commit --verify". + * "git am" learned to pass "-b" option to underlying "git mailinfo", so that bracketed string other than "PATCH" at the beginning can be kept. @@ -47,6 +40,9 @@ UI, Workflows & Features * "diff-highlight" filter (in contrib/) was updated to produce more aesthetically pleasing output. + * "fsck" learned "--no-dangling" option to omit dangling object + information. + * "git merge" in an interactive session learned to spawn the editor by default to let the user edit the auto-generated merge message, to encourage people to explain their merges better. Legacy scripts @@ -68,6 +64,19 @@ UI, Workflows & Features needed (including the ones that are not necessary for a specific task). +Foreign Interface + + * Improved handling of views, labels and branches in git-p4 (in contrib). + + * "git-p4" (in contrib) suffered from unnecessary merge conflicts when + p4 expanded the embedded $RCS$-like keywords; it can be now told to + unexpand them. + + * Some "git-svn" updates. + + * "vcs-svn"/"svn-fe" learned to read dumps with svn-deltas and + support incremental imports. + Performance * During "git upload-pack" in response to "git fetch", unnecessary calls @@ -143,7 +152,7 @@ details). --- exec >/var/tmp/1 -O=v1.7.9.2-347-gbfabdfe +O=v1.7.9.2-358-g64d1544 echo O=$(git describe) git log --first-parent --oneline ^maint $O.. echo -- cgit v0.10.2-6-g49f6 From dd6139971a18e25a5089c0f96dc80e454683ef0b Mon Sep 17 00:00:00 2001 From: Nelson Benitez Leon Date: Fri, 2 Mar 2012 14:55:57 +0100 Subject: http: support proxies that require authentication When the proxy server specified by the http.proxy configuration or the http_proxy environment variable requires authentication, git failed to connect to the proxy, because we did not configure the cURL handle with CURLOPT_PROXYAUTH. When a proxy is in use, and you tell git that the proxy requires authentication by having username in the http.proxy configuration, an extra request needs to be made to the proxy to find out what authentication method it supports, as this patch uses CURLAUTH_ANY to let the library pick the most secure method supported by the proxy server. The extra round-trip adds extra latency, but relieves the user from the burden to configure a specific authentication method. If it becomes problem, a later patch could add a configuration option to specify what method to use, but let's start simple for the time being. Signed-off-by: Nelson Benitez Leon Signed-off-by: Junio C Hamano diff --git a/http.c b/http.c index 0ffd79c..8ac8eb6 100644 --- a/http.c +++ b/http.c @@ -295,8 +295,10 @@ static CURL *get_curl_handle(void) if (curl_ftp_no_epsv) curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0); - if (curl_http_proxy) + if (curl_http_proxy) { curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy); + curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY); + } return result; } -- cgit v0.10.2-6-g49f6 From 661bfd13b49db0affebbdda5ac478ebe67634947 Mon Sep 17 00:00:00 2001 From: Stefano Lattarini Date: Fri, 2 Mar 2012 19:48:36 +0100 Subject: tests: fix spurious error when run directly with Solaris /usr/xpg4/bin/sh If any test script is run directly with Solaris 10 /usr/xpg4/bin/sh or /bin/ksh, it fails spuriously with a message like: t0000-basic.sh[31]: unset: bad argument count This happens because those shells bail out when encountering a call to "unset" with no arguments, and such unset call could take place in 'test-lib.sh'. Fix that issue, and add a proper comment to ensure we don't regress in this respect. Signed-off-by: Stefano Lattarini Signed-off-by: Junio C Hamano diff --git a/t/test-lib.sh b/t/test-lib.sh index a089a18..c0d04c4 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -42,10 +42,11 @@ TZ=UTC TERM=dumb export LANG LC_ALL PAGER TERM TZ EDITOR=: -unset VISUAL -unset EMAIL -unset LANGUAGE -unset $(perl -e ' +# A call to "unset" with no arguments causes at least Solaris 10 +# /usr/xpg4/bin/sh and /bin/ksh to bail out. So keep the unsets +# deriving from the command substitution clustered with the other +# ones. +unset VISUAL EMAIL LANGUAGE $(perl -e ' my @env = keys %ENV; my $ok = join("|", qw( TRACE -- cgit v0.10.2-6-g49f6 From 1b5b2b641adb1735086a58f4a77c72ba34c87231 Mon Sep 17 00:00:00 2001 From: Stefano Lattarini Date: Fri, 2 Mar 2012 10:08:28 +0100 Subject: t0000: modernise style Match the style to more modern test scripts, namely: - Prefer tabs for indentation. - The first line of each test has prereq, title and opening sq for the script body. - Move cleanup or initialization of data used by a test inside the test itself. - Put a newline before the closing sq for each test. - Don't conclude the test descriptions with a full stop. - Prefer 'test_line_count = COUNT FILE' over 'test $(wc -l Signed-off-by: Junio C Hamano diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index f4e8f43..ccb5435 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -34,69 +34,69 @@ fi # git init has been done in an empty repository. # make sure it is empty. -find .git/objects -type f -print >should-be-empty -test_expect_success \ - '.git/objects should be empty after git init in an empty repo.' \ - 'cmp -s /dev/null should-be-empty' +test_expect_success '.git/objects should be empty after git init in an empty repo' ' + find .git/objects -type f -print >should-be-empty && + test_line_count = 0 should-be-empty +' # also it should have 2 subdirectories; no fan-out anymore, pack, and info. # 3 is counting "objects" itself -find .git/objects -type d -print >full-of-directories -test_expect_success \ - '.git/objects should have 3 subdirectories.' \ - 'test $(wc -l < full-of-directories) = 3' +test_expect_success '.git/objects should have 3 subdirectories' ' + find .git/objects -type d -print >full-of-directories && + test_line_count = 3 full-of-directories +' ################################################################ # Test harness test_expect_success 'success is reported like this' ' - : + : ' test_expect_failure 'pretend we have a known breakage' ' - false + false ' test_expect_success 'pretend we have fixed a known breakage (run in sub test-lib)' " - mkdir passing-todo && - (cd passing-todo && - cat >passing-todo.sh <out 2>err && - ! test -s err && -sed -e 's/^> //' >expect < ok 1 - pretend we have fixed a known breakage # TODO known breakage -> # fixed 1 known breakage(s) -> # passed all 1 test(s) -> 1..1 -EOF - test_cmp expect out) + mkdir passing-todo && + (cd passing-todo && + cat >passing-todo.sh <<-EOF && + #!$SHELL_PATH + + test_description='A passing TODO test + + This is run in a sub test-lib so that we do not get incorrect + passing metrics + ' + + # Point to the t/test-lib.sh, which isn't in ../ as usual + TEST_DIRECTORY=\"$TEST_DIRECTORY\" + . \"\$TEST_DIRECTORY\"/test-lib.sh + + test_expect_failure 'pretend we have fixed a known breakage' ' + : + ' + + test_done + EOF + chmod +x passing-todo.sh && + ./passing-todo.sh >out 2>err && + ! test -s err && + sed -e 's/^> //' >expect <<-\\EOF && + > ok 1 - pretend we have fixed a known breakage # TODO known breakage + > # fixed 1 known breakage(s) + > # passed all 1 test(s) + > 1..1 + EOF + test_cmp expect out) " test_set_prereq HAVEIT haveit=no test_expect_success HAVEIT 'test runs if prerequisite is satisfied' ' - test_have_prereq HAVEIT && - haveit=yes + test_have_prereq HAVEIT && + haveit=yes ' donthaveit=yes test_expect_success DONTHAVEIT 'unmet prerequisite causes test to be skipped' ' - donthaveit=no + donthaveit=no ' if test $haveit$donthaveit != yesyes then @@ -107,17 +107,17 @@ fi test_set_prereq HAVETHIS haveit=no test_expect_success HAVETHIS,HAVEIT 'test runs if prerequisites are satisfied' ' - test_have_prereq HAVEIT && - test_have_prereq HAVETHIS && - haveit=yes + test_have_prereq HAVEIT && + test_have_prereq HAVETHIS && + haveit=yes ' donthaveit=yes test_expect_success HAVEIT,DONTHAVEIT 'unmet prerequisites causes test to be skipped' ' - donthaveit=no + donthaveit=no ' donthaveiteither=yes test_expect_success DONTHAVEIT,HAVEIT 'unmet prerequisites causes test to be skipped' ' - donthaveiteither=no + donthaveiteither=no ' if test $haveit$donthaveit$donthaveiteither != yesyesyes then @@ -127,7 +127,7 @@ fi clean=no test_expect_success 'tests clean up after themselves' ' - test_when_finished clean=yes + test_when_finished clean=yes ' if test $clean != yes @@ -137,106 +137,100 @@ then fi test_expect_success 'tests clean up even on failures' " - mkdir failing-cleanup && - (cd failing-cleanup && - cat >failing-cleanup.sh <out 2>err && - ! test -s err && - ! test -f \"trash directory.failing-cleanup/clean-after-failure\" && -sed -e 's/Z$//' -e 's/^> //' >expect <<\EOF && -> not ok - 1 tests clean up even after a failure -> # Z -> # touch clean-after-failure && -> # test_when_finished rm clean-after-failure && -> # (exit 1) -> # Z -> not ok - 2 failure to clean up causes the test to fail -> # Z -> # test_when_finished \"(exit 2)\" -> # Z -> # failed 2 among 2 test(s) -> 1..2 -EOF - test_cmp expect out) + mkdir failing-cleanup && + ( + cd failing-cleanup && + + cat >failing-cleanup.sh <<-EOF && + #!$SHELL_PATH + + test_description='Failing tests with cleanup commands' + + # Point to the t/test-lib.sh, which isn't in ../ as usual + TEST_DIRECTORY=\"$TEST_DIRECTORY\" + . \"\$TEST_DIRECTORY\"/test-lib.sh + + test_expect_success 'tests clean up even after a failure' ' + touch clean-after-failure && + test_when_finished rm clean-after-failure && + (exit 1) + ' + test_expect_success 'failure to clean up causes the test to fail' ' + test_when_finished \"(exit 2)\" + ' + test_done + + EOF + + chmod +x failing-cleanup.sh && + test_must_fail ./failing-cleanup.sh >out 2>err && + ! test -s err && + ! test -f \"trash directory.failing-cleanup/clean-after-failure\" && + sed -e 's/Z$//' -e 's/^> //' >expect <<-\\EOF && + > not ok - 1 tests clean up even after a failure + > # Z + > # touch clean-after-failure && + > # test_when_finished rm clean-after-failure && + > # (exit 1) + > # Z + > not ok - 2 failure to clean up causes the test to fail + > # Z + > # test_when_finished \"(exit 2)\" + > # Z + > # failed 2 among 2 test(s) + > 1..2 + EOF + test_cmp expect out + ) " ################################################################ # Basics of the basics # updating a new file without --add should fail. -test_expect_success 'git update-index without --add should fail adding.' ' - test_must_fail git update-index should-be-empty +test_expect_success 'git update-index without --add should fail adding' ' + test_must_fail git update-index should-be-empty ' # and with --add it should succeed, even if it is empty (it used to fail). -test_expect_success \ - 'git update-index with --add should succeed.' \ - 'git update-index --add should-be-empty' +test_expect_success 'git update-index with --add should succeed' ' + git update-index --add should-be-empty +' -test_expect_success \ - 'writing tree out with git write-tree' \ - 'tree=$(git write-tree)' +test_expect_success 'writing tree out with git write-tree' ' + tree=$(git write-tree) +' # we know the shape and contents of the tree and know the object ID for it. -test_expect_success \ - 'validate object ID of a known tree.' \ - 'test "$tree" = 7bb943559a305bdd6bdee2cef6e5df2413c3d30a' +test_expect_success 'validate object ID of a known tree' ' + test "$tree" = 7bb943559a305bdd6bdee2cef6e5df2413c3d30a + ' # Removing paths. -rm -f should-be-empty full-of-directories -test_expect_success 'git update-index without --remove should fail removing.' ' - test_must_fail git update-index should-be-empty +test_expect_success 'git update-index without --remove should fail removing' ' + rm -f should-be-empty full-of-directories && + test_must_fail git update-index should-be-empty ' -test_expect_success \ - 'git update-index with --remove should be able to remove.' \ - 'git update-index --remove should-be-empty' +test_expect_success 'git update-index with --remove should be able to remove' ' + git update-index --remove should-be-empty +' # Empty tree can be written with recent write-tree. -test_expect_success \ - 'git write-tree should be able to write an empty tree.' \ - 'tree=$(git write-tree)' +test_expect_success 'git write-tree should be able to write an empty tree' ' + tree=$(git write-tree) +' -test_expect_success \ - 'validate object ID of a known tree.' \ - 'test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904' +test_expect_success 'validate object ID of a known tree' ' + test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904 +' # Various types of objects + # Some filesystems do not support symblic links; on such systems # some expected values are different -mkdir path2 path3 path3/subp3 -paths='path0 path2/file2 path3/file3 path3/subp3/file3' -for p in $paths -do - echo "hello $p" >$p -done if test_have_prereq SYMLINKS then - for p in $paths - do - ln -s "hello $p" ${p}sym - done expectfilter=cat expectedtree=087704a96baf1c2d1c869a8b084481e121c88b5b expectedptree1=21ae8269cacbe57ae09138dcc3a2887f904d02b3 @@ -248,135 +242,154 @@ else expectedptree2=ce580448f0148b985a513b693fdf7d802cacb44f fi -test_expect_success \ - 'adding various types of objects with git update-index --add.' \ - 'find path* ! -type d -print | xargs git update-index --add' + +test_expect_success 'adding various types of objects with git update-index --add' ' + mkdir path2 path3 path3/subp3 && + paths="path0 path2/file2 path3/file3 path3/subp3/file3" && + ( + for p in $paths + do + echo "hello $p" >$p || exit 1 + if test_have_prereq SYMLINKS + then + ln -s "hello $p" ${p}sym || exit 1 + fi + done + ) && + find path* ! -type d -print | xargs git update-index --add +' # Show them and see that matches what we expect. -test_expect_success \ - 'showing stage with git ls-files --stage' \ - 'git ls-files --stage >current' - -$expectfilter >expected <<\EOF -100644 f87290f8eb2cbbea7857214459a0739927eab154 0 path0 -120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0 path0sym -100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0 path2/file2 -120000 d8ce161addc5173867a3c3c730924388daedbc38 0 path2/file2sym -100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0 path3/file3 -120000 8599103969b43aff7e430efea79ca4636466794f 0 path3/file3sym -100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0 path3/subp3/file3 -120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0 path3/subp3/file3sym -EOF -test_expect_success \ - 'validate git ls-files output for a known tree.' \ - 'test_cmp expected current' - -test_expect_success \ - 'writing tree out with git write-tree.' \ - 'tree=$(git write-tree)' -test_expect_success \ - 'validate object ID for a known tree.' \ - 'test "$tree" = "$expectedtree"' - -test_expect_success \ - 'showing tree with git ls-tree' \ - 'git ls-tree $tree >current' -cat >expected <<\EOF -100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 -120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym -040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 -040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 -EOF -test_expect_success SYMLINKS \ - 'git ls-tree output for a known tree.' \ - 'test_cmp expected current' +test_expect_success 'showing stage with git ls-files --stage' ' + git ls-files --stage >current +' + +test_expect_success 'validate git ls-files output for a known tree' ' + $expectfilter >expected <<-\EOF && + 100644 f87290f8eb2cbbea7857214459a0739927eab154 0 path0 + 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0 path0sym + 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0 path2/file2 + 120000 d8ce161addc5173867a3c3c730924388daedbc38 0 path2/file2sym + 100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0 path3/file3 + 120000 8599103969b43aff7e430efea79ca4636466794f 0 path3/file3sym + 100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0 path3/subp3/file3 + 120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0 path3/subp3/file3sym + EOF + test_cmp expected current +' + +test_expect_success 'writing tree out with git write-tree' ' + tree=$(git write-tree) +' + +test_expect_success 'validate object ID for a known tree' ' + test "$tree" = "$expectedtree" +' + +test_expect_success 'showing tree with git ls-tree' ' + git ls-tree $tree >current +' + +test_expect_success SYMLINKS 'git ls-tree output for a known tree' ' + cat >expected <<-\EOF && + 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 + 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym + 040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 + 040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 + EOF + test_cmp expected current +' # This changed in ls-tree pathspec change -- recursive does # not show tree nodes anymore. -test_expect_success \ - 'showing tree with git ls-tree -r' \ - 'git ls-tree -r $tree >current' -$expectfilter >expected <<\EOF -100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 -120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym -100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 -120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym -100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3 -120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym -100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 -120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym -EOF -test_expect_success \ - 'git ls-tree -r output for a known tree.' \ - 'test_cmp expected current' +test_expect_success 'showing tree with git ls-tree -r' ' + git ls-tree -r $tree >current +' + +test_expect_success 'git ls-tree -r output for a known tree' ' + $expectfilter >expected <<-\EOF && + 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 + 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym + 100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 + 120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym + 100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3 + 120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym + 100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 + 120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym + EOF + test_cmp expected current +' # But with -r -t we can have both. -test_expect_success \ - 'showing tree with git ls-tree -r -t' \ - 'git ls-tree -r -t $tree >current' -cat >expected <<\EOF -100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 -120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym -040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 -100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 -120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym -040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 -100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3 -120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym -040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3 -100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 -120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym -EOF -test_expect_success SYMLINKS \ - 'git ls-tree -r output for a known tree.' \ - 'test_cmp expected current' - -test_expect_success \ - 'writing partial tree out with git write-tree --prefix.' \ - 'ptree=$(git write-tree --prefix=path3)' -test_expect_success \ - 'validate object ID for a known tree.' \ - 'test "$ptree" = "$expectedptree1"' - -test_expect_success \ - 'writing partial tree out with git write-tree --prefix.' \ - 'ptree=$(git write-tree --prefix=path3/subp3)' -test_expect_success \ - 'validate object ID for a known tree.' \ - 'test "$ptree" = "$expectedptree2"' - -cat >badobjects <current +' -rm .git/index -test_expect_success \ - 'put invalid objects into the index.' \ - 'git update-index --index-info < badobjects' +test_expect_success SYMLINKS 'git ls-tree -r output for a known tree' ' + cat >expected <<-\EOF && + 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 + 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym + 040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 + 100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 + 120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym + 040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 + 100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3 + 120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym + 040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3 + 100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 + 120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym + EOF + test_cmp expected current +' -test_expect_success 'writing this tree without --missing-ok.' ' - test_must_fail git write-tree +test_expect_success 'writing partial tree out with git write-tree --prefix' ' + ptree=$(git write-tree --prefix=path3) ' -test_expect_success \ - 'writing this tree with --missing-ok.' \ - 'git write-tree --missing-ok' +test_expect_success 'validate object ID for a known tree' ' + test "$ptree" = "$expectedptree1" +' + +test_expect_success 'writing partial tree out with git write-tree --prefix' ' + ptree=$(git write-tree --prefix=path3/subp3) +' + +test_expect_success 'validate object ID for a known tree' ' + test "$ptree" = "$expectedptree2" +' + +test_expect_success 'put invalid objects into the index' ' + rm -f .git/index && + cat >badobjects <<-\EOF && + 100644 blob 1000000000000000000000000000000000000000 dir/file1 + 100644 blob 2000000000000000000000000000000000000000 dir/file2 + 100644 blob 3000000000000000000000000000000000000000 dir/file3 + 100644 blob 4000000000000000000000000000000000000000 dir/file4 + 100644 blob 5000000000000000000000000000000000000000 dir/file5 + EOF + git update-index --index-info expected <<\EOF +test_expect_success 'git read-tree followed by write-tree should be idempotent' ' + rm -f .git/index + git read-tree $tree && + test -f .git/index && + newtree=$(git write-tree) && + test "$newtree" = "$tree" +' + +test_expect_success 'validate git diff-files output for a know cache/work tree state' ' + $expectfilter >expected <<\EOF && :100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M path0 :120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M path0sym :100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M path2/file2 @@ -386,45 +399,47 @@ $expectfilter >expected <<\EOF :100644 100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0000000000000000000000000000000000000000 M path3/subp3/file3 :120000 120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0000000000000000000000000000000000000000 M path3/subp3/file3sym EOF -test_expect_success \ - 'validate git diff-files output for a know cache/work tree state.' \ - 'git diff-files >current && test_cmp current expected >/dev/null' + git diff-files >current && + test_cmp current expected +' -test_expect_success \ - 'git update-index --refresh should succeed.' \ - 'git update-index --refresh' +test_expect_success 'git update-index --refresh should succeed' ' + git update-index --refresh +' -test_expect_success \ - 'no diff after checkout and git update-index --refresh.' \ - 'git diff-files >current && cmp -s current /dev/null' +test_expect_success 'no diff after checkout and git update-index --refresh' ' + git diff-files >current && + cmp -s current /dev/null +' ################################################################ P=$expectedtree -test_expect_success \ - 'git commit-tree records the correct tree in a commit.' \ - 'commit0=$(echo NO | git commit-tree $P) && - tree=$(git show --pretty=raw $commit0 | - sed -n -e "s/^tree //p" -e "/^author /q") && - test "z$tree" = "z$P"' - -test_expect_success \ - 'git commit-tree records the correct parent in a commit.' \ - 'commit1=$(echo NO | git commit-tree $P -p $commit0) && - parent=$(git show --pretty=raw $commit1 | - sed -n -e "s/^parent //p" -e "/^author /q") && - test "z$commit0" = "z$parent"' - -test_expect_success \ - 'git commit-tree omits duplicated parent in a commit.' \ - 'commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) && - parent=$(git show --pretty=raw $commit2 | - sed -n -e "s/^parent //p" -e "/^author /q" | - sort -u) && - test "z$commit0" = "z$parent" && - numparent=$(git show --pretty=raw $commit2 | - sed -n -e "s/^parent //p" -e "/^author /q" | - wc -l) && - test $numparent = 1' + +test_expect_success 'git commit-tree records the correct tree in a commit' ' + commit0=$(echo NO | git commit-tree $P) && + tree=$(git show --pretty=raw $commit0 | + sed -n -e "s/^tree //p" -e "/^author /q") && + test "z$tree" = "z$P" +' + +test_expect_success 'git commit-tree records the correct parent in a commit' ' + commit1=$(echo NO | git commit-tree $P -p $commit0) && + parent=$(git show --pretty=raw $commit1 | + sed -n -e "s/^parent //p" -e "/^author /q") && + test "z$commit0" = "z$parent" +' + +test_expect_success 'git commit-tree omits duplicated parent in a commit' ' + commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) && + parent=$(git show --pretty=raw $commit2 | + sed -n -e "s/^parent //p" -e "/^author /q" | + sort -u) && + test "z$commit0" = "z$parent" && + numparent=$(git show --pretty=raw $commit2 | + sed -n -e "s/^parent //p" -e "/^author /q" | + wc -l) && + test $numparent = 1 +' test_expect_success 'update-index D/F conflict' ' mv path0 tmp && -- cgit v0.10.2-6-g49f6 From b22939a2860604bec718cfd751e930f3a8afd1cc Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 2 Mar 2012 23:50:01 +0100 Subject: gitweb: Fix passing parameters to git_project_search_form The git_project_search_form() subroutine, introduced in a1e1b2d (gitweb: improve usability of projects search form, 2012-01-31) didn't get its arguments from caller correctly. Gitweb worked correctly thanks to sticky-ness of form fields in CGI.pm... but it make UTF-8 fix for project search not working. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 7729ed2..813571b 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5174,7 +5174,7 @@ sub git_patchset_body { # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sub git_project_search_form { - my ($searchtext, $search_use_regexp); + my ($searchtext, $search_use_regexp) = @_; my $limit = ''; if ($project_filter) { -- cgit v0.10.2-6-g49f6 From fe6c64ab0b2b568755a6686c0a435fa95ef619bb Mon Sep 17 00:00:00 2001 From: Tom Grennan Date: Fri, 2 Mar 2012 18:15:34 -0800 Subject: t5512 (ls-remote): modernize style Prepare expected output inside test_expect_success that uses it. Also remove excess blank lines. Signed-off-by: Tom Grennan Signed-off-by: Junio C Hamano diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index 5c546c9..6764d51 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -5,7 +5,6 @@ test_description='git ls-remote' . ./test-lib.sh test_expect_success setup ' - >file && git add file && test_tick && @@ -18,45 +17,33 @@ test_expect_success setup ' ) >expected.all && git remote add self "$(pwd)/.git" - ' test_expect_success 'ls-remote --tags .git' ' - git ls-remote --tags .git >actual && test_cmp expected.tag actual - ' test_expect_success 'ls-remote .git' ' - git ls-remote .git >actual && test_cmp expected.all actual - ' test_expect_success 'ls-remote --tags self' ' - git ls-remote --tags self >actual && test_cmp expected.tag actual - ' test_expect_success 'ls-remote self' ' - git ls-remote self >actual && test_cmp expected.all actual - ' test_expect_success 'dies when no remote specified and no default remotes found' ' - test_must_fail git ls-remote - ' test_expect_success 'use "origin" when no remote specified' ' - URL="$(pwd)/.git" && echo "From $URL" >exp_err && @@ -65,18 +52,14 @@ test_expect_success 'use "origin" when no remote specified' ' test_cmp exp_err actual_err && test_cmp expected.all actual - ' test_expect_success 'suppress "From " with -q' ' - git ls-remote -q 2>actual_err && test_must_fail test_cmp exp_err actual_err - ' test_expect_success 'use branch..remote if possible' ' - # # Test that we are indeed using branch..remote, not "origin", even # though the "origin" remote has been set. @@ -99,14 +82,13 @@ test_expect_success 'use branch..remote if possible' ' git ls-remote 2>actual_err >actual && test_cmp exp_err actual_err && test_cmp exp actual - ' -cat >exp <exp <<-\EOF && + fatal: '\''refs*master'\'' does not appear to be a git repository + fatal: The remote end hung up unexpectedly + EOF # # Do not expect "git ls-remote " to work; ls-remote, correctly, # confuses for . Although ugly, this behaviour is akin @@ -120,7 +102,6 @@ test_expect_success 'confuses pattern as remote when no remote specified' ' # role as a pattern. test_must_fail git ls-remote refs*master >actual 2>&1 && test_cmp exp actual - ' test_expect_success 'die with non-2 for wrong repository even with --exit-code' ' -- cgit v0.10.2-6-g49f6 From 78ed1d2d63390694cb6c451896086fb7338f75b6 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Fri, 2 Mar 2012 19:37:35 -0500 Subject: t0300: work around bug in dash 0.5.6 The construct 'while IFS== read' makes dash 0.5.6 execute read without changing IFS, which results in test breakages all over the place in t0300. Neither dash 0.5.5.1 and older nor dash 0.5.7 and newer are affected: The problem was introduded resp. fixed by the commits 55c46b7 ([BUILTIN] Honor tab as IFS whitespace when splitting fields in readcmd, 2009-08-11) 1d806ac ([VAR] Do not poplocalvars prematurely on regular utilities, 2010-05-27) in http://git.kernel.org/?p=utils/dash/dash.git Putting 'IFS==' before that line makes all versions of dash work. This looks like a dash bug, not a misinterpretation of the standard. However, it's worth working around for two reasons. One, this version of dash was released in Fedora 14-16, so the bug is found in the wild. And two, at least one other shell, Solaris /bin/sh, choked on this by persisting IFS after the read invocation. That is not a shell we usually care about, and I think this use of IFS is acceptable by POSIX (which allows other behavior near "special builtins", but "read" is not one of those). But it seems that this may be a subtle, not-well-tested case for some shells. Given that the workaround is so simple, it's worth just being defensive. Signed-off-by: Michael J Gruber Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index 885af8f..c1c8108 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -8,10 +8,13 @@ test_expect_success 'setup helper scripts' ' cat >dump <<-\EOF && whoami=`echo $0 | sed s/.*git-credential-//` echo >&2 "$whoami: $*" - while IFS== read key value; do + OIFS=$IFS + IFS== + while read key value; do echo >&2 "$whoami: $key=$value" eval "$key=$value" done + IFS=$OIFS EOF cat >git-credential-useless <<-\EOF && -- cgit v0.10.2-6-g49f6 From 15438d5a56acfd08545a11630821179334eb6979 Mon Sep 17 00:00:00 2001 From: Jared Hance Date: Fri, 2 Mar 2012 21:31:15 -0500 Subject: Add threaded versions of functions in symlinks.c. check_leading_path() and has_dirs_only_path() both always use the default cache, which could be a caveat for adding parallelism (which is a concern and even a GSoC proposal). Reimplement these two in terms of new threaded_check_leading_path() and threaded_has_dirs_only_path() that take their own copy of the cache. Signed-off-by: Jared Hance Signed-off-by: Junio C Hamano diff --git a/cache.h b/cache.h index 3a8e125..26ca955 100644 --- a/cache.h +++ b/cache.h @@ -950,7 +950,9 @@ struct cache_def { extern int has_symlink_leading_path(const char *name, int len); extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int); extern int check_leading_path(const char *name, int len); +extern int threaded_check_leading_path(struct cache_def *cache, const char *name, int len); extern int has_dirs_only_path(const char *name, int len, int prefix_len); +extern int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len); extern void schedule_dir_for_removal(const char *name, int len); extern void remove_scheduled_dirs(void); diff --git a/symlinks.c b/symlinks.c index 034943b..2900367 100644 --- a/symlinks.c +++ b/symlinks.c @@ -219,7 +219,20 @@ int has_symlink_leading_path(const char *name, int len) */ int check_leading_path(const char *name, int len) { - struct cache_def *cache = &default_cache; /* FIXME */ + return threaded_check_leading_path(&default_cache, name, len); +} + +/* + * Return zero if path 'name' has a leading symlink component or + * if some leading path component does not exists. + * + * Return -1 if leading path exists and is a directory. + * + * Return path length if leading path exists and is neither a + * directory nor a symlink. + */ +int threaded_check_leading_path(struct cache_def *cache, const char *name, int len) +{ int flags; int match_len = lstat_cache_matchlen(cache, name, len, &flags, FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT); @@ -240,7 +253,18 @@ int check_leading_path(const char *name, int len) */ int has_dirs_only_path(const char *name, int len, int prefix_len) { - struct cache_def *cache = &default_cache; /* FIXME */ + return threaded_has_dirs_only_path(&default_cache, name, len, prefix_len); +} + +/* + * Return non-zero if all path components of 'name' exists as a + * directory. If prefix_len > 0, we will test with the stat() + * function instead of the lstat() function for a prefix length of + * 'prefix_len', thus we then allow for symlinks in the prefix part as + * long as those points to real existing directories. + */ +int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len) +{ return lstat_cache(cache, name, len, FL_DIR|FL_FULLPATH, prefix_len) & FL_DIR; -- cgit v0.10.2-6-g49f6 From 38916c5b4740f6db09dc140a84bb470dfb582366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sat, 3 Mar 2012 12:00:29 +0100 Subject: parse-options: typo check for unknown switches The user specifies a long option but forgets to type the second leading dash, we currently detect and report that fact if its first letter is a valid short option. This is done for safety, to avoid ambiguity between short options (and their arguments) and a long option with a missing dash. This diagnostic message is also helpful for long options whose first letter is not a valid short option, however. Print it in that case, too, as a courtesy. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano diff --git a/parse-options.c b/parse-options.c index 1908996..850cfa7 100644 --- a/parse-options.c +++ b/parse-options.c @@ -393,6 +393,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, case -1: return parse_options_usage(ctx, usagestr, options, 1); case -2: + if (ctx->opt) + check_typos(arg + 1, options); goto unknown; } if (ctx->opt) diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index a44bcb9..e3f354a 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -236,6 +236,16 @@ test_expect_success 'detect possible typos' ' test_cmp typo.err output.err ' +cat > typo.err << EOF +error: did you mean \`--ambiguous\` (with two dashes ?) +EOF + +test_expect_success 'detect possible typos' ' + test_must_fail test-parse-options -ambiguous > output 2> output.err && + test ! -s output && + test_cmp typo.err output.err +' + cat > expect < Date: Sun, 4 Mar 2012 17:50:43 +0100 Subject: http.proxy: also mention https_proxy and all_proxy The current wording of the http.proxy documentation suggests that http_proxy is somehow equivalent to http.proxy. However, while http.proxy (by the means of curl's CURLOPT_PROXY option) overrides the proxy for both HTTP and HTTPS protocols, the http_proxy environment variable is used only for HTTP. But since the docs mention only http_proxy, a user might expect it to apply to all HTTP-like protocols. Avoid any such misunderstanding by explicitly mentioning https_proxy and all_proxy as well. Also replace linkgit:curl[1] with a literal 'curl(1)', because the former gets translated to a dead link in the HTML pages. Signed-off-by: Clemens Buchacher Signed-off-by: Junio C Hamano diff --git a/Documentation/config.txt b/Documentation/config.txt index a7a6dc0..0e1168c 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1260,9 +1260,10 @@ help.autocorrect:: This is the default. http.proxy:: - Override the HTTP proxy, normally configured using the 'http_proxy' - environment variable (see linkgit:curl[1]). This can be overridden - on a per-remote basis; see remote..proxy + Override the HTTP proxy, normally configured using the 'http_proxy', + 'https_proxy', and 'all_proxy' environment variables (see + `curl(1)`). This can be overridden on a per-remote basis; see + remote..proxy http.cookiefile:: File containing previously stored cookie lines which should be used -- cgit v0.10.2-6-g49f6 From f1589d100796c58615033dde10c1c6446b814357 Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Sun, 4 Mar 2012 19:10:57 +0000 Subject: ctype.c: Fix a sparse warning In particular, sparse complains as follows: SP ctype.c ctype.c:30:12: warning: symbol 'tolower_trans_tbl' was not declared.\ Should it be static? An appropriate extern declaration for the 'tolower_trans_tbl' symbol is included in the "cache.h" header file. In order to suppress the warning, therefore, we could replace the "git-compat-util.h" header inclusion with "cache.h", since "cache.h" includes "git-compat-util.h" in turn. Here, however, we choose to move the extern declaration for 'tolower_trans_tbl' into "git-compat-util.h", alongside the other extern declaration from ctype.c for 'sane_ctype'. Signed-off-by: Ramsay Jones Signed-off-by: Junio C Hamano diff --git a/cache.h b/cache.h index 79dc305..79c612f 100644 --- a/cache.h +++ b/cache.h @@ -1258,7 +1258,4 @@ extern struct startup_info *startup_info; /* builtin/merge.c */ int checkout_fast_forward(const unsigned char *from, const unsigned char *to); -/* in ctype.c, for kwset users */ -extern const char tolower_trans_tbl[256]; - #endif /* CACHE_H */ diff --git a/git-compat-util.h b/git-compat-util.h index 230e198..ac0a87b 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -457,6 +457,9 @@ static inline int has_extension(const char *filename, const char *ext) return len > extlen && !memcmp(filename + len - extlen, ext, extlen); } +/* in ctype.c, for kwset users */ +extern const char tolower_trans_tbl[256]; + /* Sane ctype - no locale, and works with signed chars */ #undef isascii #undef isspace -- cgit v0.10.2-6-g49f6 From ead8eb8c1092ce2d94d70872946829a7a946ae9d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Mar 2012 22:21:30 -0800 Subject: Update draft release notes to 1.7.9.3 for the last time Signed-off-by: Junio C Hamano diff --git a/Documentation/RelNotes/1.7.9.3.txt b/Documentation/RelNotes/1.7.9.3.txt index d7be177..91c6501 100644 --- a/Documentation/RelNotes/1.7.9.3.txt +++ b/Documentation/RelNotes/1.7.9.3.txt @@ -11,14 +11,41 @@ Fixes since v1.7.9.2 to link the binary with -lintl even when libintl.h is missing from the system. + * When the filter driver exits before reading the content before the + main git process writes the contents to be filtered to the pipe to + it, the latter could be killed with SIGPIPE instead of ignoring + such an event as an error. + * "git add --refresh " used to warn about unmerged paths outside the given pathspec. + * The bulk check-in codepath in "git add" streamed contents that + needs smudge/clean filters without running them, instead of punting + and delegating to the codepath to run filters after slurping + everything to core. + + * "git branch --with $that" assumed incorrectly that the user will never + ask the question with nonsense value in $that. + + * "git bundle create" produced a corrupt bundle file upon seeing + commits with excessively long subject line. + + * When a remote helper exits before reading the blank line from the + main git process to signal the end of commands, the latter could be + killed with SIGPIPE. Instead we should ignore such event as a + non-error. + * The commit log template given with "git merge --edit" did not have a short instructive text like what "git commit" gives. + * "git rev-list --verify-objects -q" omitted the extra verification + it needs to do over "git rev-list --objects -q" by mistake. + * "gitweb" used to drop warnings in the log file when "heads" view is accessed in a repository whose HEAD does not point at a valid branch. + * An invalid regular expression pattern given by an end user made + "gitweb" to return garbled response. + Also contains minor fixes and documentation updates. -- cgit v0.10.2-6-g49f6 From 3c02396adc0d8836bccc4fbc95edbb3ca8c1f508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 4 Mar 2012 05:41:26 +0100 Subject: Make git-{pull,rebase} message without tracking information friendlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current message is too long and at too low a level for anybody to understand it if they don't know about the configuration format already. The text about setting up a remote is superfluous and doesn't help understand or recover from the error that has happened. Show the usage more prominently and explain how to set up the tracking information. If there is only one remote, that name is used instead of the generic . Also simplify the message we print on detached HEAD to remove unnecessary information which is better left for the documentation. Signed-off-by: Carlos Martín Nieto Signed-off-by: Junio C Hamano diff --git a/git-parse-remote.sh b/git-parse-remote.sh index b24119d..484b2e6 100644 --- a/git-parse-remote.sh +++ b/git-parse-remote.sh @@ -57,34 +57,31 @@ error_on_missing_default_upstream () { op_prep="$3" example="$4" branch_name=$(git symbolic-ref -q HEAD) + # If there's only one remote, use that in the suggestion + remote="" + if test $(git remote | wc -l) = 1 + then + remote=$(git remote) + fi + if test -z "$branch_name" then - echo "You are not currently on a branch, so I cannot use any -'branch..merge' in your configuration file. -Please specify which branch you want to $op_type $op_prep on the command -line and try again (e.g. '$example'). -See git-${cmd}(1) for details." + echo "You are not currently on a branch. Please specify which +branch you want to $op_type $op_prep. See git-${cmd}(1) for details. + + $example +" else - echo "You asked me to $cmd without telling me which branch you -want to $op_type $op_prep, and 'branch.${branch_name#refs/heads/}.merge' in -your configuration file does not tell me, either. Please -specify which branch you want to use on the command line and -try again (e.g. '$example'). -See git-${cmd}(1) for details. + echo "There is no tracking information for the current branch. +Please specify which branch you want to $op_type $op_prep. +See git-${cmd}(1) for details + + $example -If you often $op_type $op_prep the same branch, you may want to -use something like the following in your configuration file: - [branch \"${branch_name#refs/heads/}\"] - remote = - merge = " - test rebase = "$op_type" && - echo " rebase = true" - echo " - [remote \"\"] - url = - fetch = +If you wish to set tracking information for this branch you can do so with: -See git-config(1) for details." + git branch --set-upstream ${branch_name#refs/heads/} $remote/ +" fi exit 1 } diff --git a/git-pull.sh b/git-pull.sh index 434c139..2a10047 100755 --- a/git-pull.sh +++ b/git-pull.sh @@ -180,7 +180,7 @@ error_on_no_merge_candidates () { elif [ -z "$curr_branch" -o -z "$upstream" ]; then . git-parse-remote error_on_missing_default_upstream "pull" $op_type $op_prep \ - "git pull " + "git pull " else echo "Your configuration specifies to $op_type $op_prep the ref '${upstream#refs/heads/}'" echo "from the remote, but no such ref was fetched." diff --git a/git-rebase.sh b/git-rebase.sh index 00ca7b9..69c1374 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -380,7 +380,7 @@ then then . git-parse-remote error_on_missing_default_upstream "rebase" "rebase" \ - "against" "git rebase " + "against" "git rebase " fi ;; *) upstream_name="$1" diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index e647272..7788ae0 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -160,14 +160,12 @@ rm -f B test_expect_success 'fail when upstream arg is missing and not on branch' ' git checkout topic && - test_must_fail git rebase >output.out && - grep "You are not currently on a branch" output.out + test_must_fail git rebase ' test_expect_success 'fail when upstream arg is missing and not configured' ' git checkout -b no-config topic && - test_must_fail git rebase >output.out && - grep "branch.no-config.merge" output.out + test_must_fail git rebase ' test_expect_success 'default to @{upstream} when upstream arg is missing' ' -- cgit v0.10.2-6-g49f6 From 4a92a1721483d6a109cf0993843b20159f8d3387 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Mar 2012 23:38:02 -0800 Subject: Update draft release notes to 1.7.10 Signed-off-by: Junio C Hamano diff --git a/Documentation/RelNotes/1.7.10.txt b/Documentation/RelNotes/1.7.10.txt index 7813ea1..b966a8e 100644 --- a/Documentation/RelNotes/1.7.10.txt +++ b/Documentation/RelNotes/1.7.10.txt @@ -52,6 +52,9 @@ UI, Workflows & Features * "git push" learned the "--prune" option, similar to "git fetch". + * "git symbolic-ref" learned the "--short" option to abbreviate the + refname it shows unambiguously. + * "git tag --list" can be given "--points-at " to limit its output to those that point at the given object. @@ -64,6 +67,9 @@ UI, Workflows & Features needed (including the ones that are not necessary for a specific task). + * Project search in "gitweb" shows the substring that matched in the + project name and description highlighted. + Foreign Interface * Improved handling of views, labels and branches in git-p4 (in contrib). @@ -112,39 +118,10 @@ Unless otherwise noted, all the fixes since v1.7.9 in the maintenance releases are contained in this release (see release notes to them for details). - * "git branch --with $that" assumed incorrectly that the user will never - ask the question with nonsense value in $that. - (merge 6c41e97 cn/maint-branch-with-bad later to maint). - - * An invalid regular expression pattern given by an end user made - "gitweb" to return garbled response. - (merge 36612e4 jn/maint-gitweb-invalid-regexp later to maint). - - * "git rev-list --verify-objects -q" omitted the extra verification - it needs to do over "git rev-list --objects -q" by mistake. - (merge 9899372 nd/maint-verify-objects later to maint). - - * The bulk check-in codepath streamed contents that needs - smudge/clean filters without running them, instead of punting and - delegating to the codepath to run filters after slurping everything - to core. - (merge 4f22b10 jk/maint-avoid-streaming-filtered-contents later to maint). - - * When the filter driver exits before reading the content before the - main git process writes the contents to be filtered to the pipe to - it, the latter could be killed with SIGPIPE instead of ignoring - such an event as an error. - (merge 6424c2a jb/filter-ignore-sigpipe later to maint). - - * When a remote helper exits before reading the blank line from the - main git process to signal the end of commands, the latter could be - killed with SIGPIPE. Instead we should ignore such event as a - non-error. - (merge c34fe63 sp/smart-http-failure-to-push later to maint). - - * "git bundle create" produced a corrupt bundle file upon seeing - commits with excessively long subject line. - (merge 8a557bb tr/maint-bundle-long-subject later to maint). + * The code to synthesize the fake ancestor tree used by 3-way merge + fallback in "git am" was not prepared to read a patch created with + a non-standard -p value. + (merge a61ba26 jc/am-3-nonstandard-popt later to maint). * "gitweb" used to drop warnings in the log file when "heads" view is accessed in a repository whose HEAD does not point at a valid @@ -152,7 +129,7 @@ details). --- exec >/var/tmp/1 -O=v1.7.9.2-358-g64d1544 +O=v1.7.9.2-383-gb8b5290 echo O=$(git describe) git log --first-parent --oneline ^maint $O.. echo -- cgit v0.10.2-6-g49f6 From 284a126c3ef3dfedede9bc64df4cf3a24600dea5 Mon Sep 17 00:00:00 2001 From: Tim Henigan Date: Mon, 5 Mar 2012 09:28:07 -0500 Subject: mergetools: add a plug-in to support DeltaWalker DeltaWalker is a non-free tool popular among some users. Add a plug-in to support it from difftool and mergetool. Note that the $(pwd)/ in front of $MERGED should not be necessary. However without it, DeltaWalker crashes with a JRE exception. Signed-off-by: Tim Henigan Helped-by: David Aguilar Signed-off-by: Junio C Hamano diff --git a/mergetools/deltawalker b/mergetools/deltawalker new file mode 100644 index 0000000..b3c71b6 --- /dev/null +++ b/mergetools/deltawalker @@ -0,0 +1,21 @@ +diff_cmd () { + "$merge_tool_path" "$LOCAL" "$REMOTE" >/dev/null 2>&1 +} + +merge_cmd () { + # Adding $(pwd)/ in front of $MERGED should not be necessary. + # However without it, DeltaWalker (at least v1.9.8 on Windows) + # crashes with a JRE exception. The DeltaWalker user manual, + # shows $(pwd)/ whenever the '-merged' options is given. + # Adding it here seems to work around the problem. + if $base_present + then + "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" -merged="$(pwd)/$MERGED" + else + "$merge_tool_path" "$LOCAL" "$REMOTE" -merged="$(pwd)/$MERGED" + fi >/dev/null 2>&1 +} + +translate_merge_tool_path() { + echo DeltaWalker +} -- cgit v0.10.2-6-g49f6 From a8ea1b7a5580bc4377818fb6718d55d4b735dae8 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Mon, 5 Mar 2012 14:48:49 +0100 Subject: fast-import: zero all of 'struct tag' to silence valgrind When running t9300, valgrind (correctly) complains about an uninitialized value in write_crash_report: ==2971== Use of uninitialised value of size 8 ==2971== at 0x4164F4: sha1_to_hex (hex.c:70) ==2971== by 0x4073E4: die_nicely (fast-import.c:468) ==2971== by 0x43284C: die (usage.c:86) ==2971== by 0x40420D: main (fast-import.c:2731) ==2971== Uninitialised value was created by a heap allocation ==2971== at 0x4C29B3D: malloc (vg_replace_malloc.c:263) ==2971== by 0x433645: xmalloc (wrapper.c:35) ==2971== by 0x405DF5: pool_alloc (fast-import.c:619) ==2971== by 0x407755: pool_calloc.constprop.14 (fast-import.c:634) ==2971== by 0x403F33: main (fast-import.c:3324) Fix this by zeroing all of the 'struct tag'. We would only need to zero out the 'sha1' field, but this way seems more future-proof. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano diff --git a/fast-import.c b/fast-import.c index 6cd19e5..c1486ca 100644 --- a/fast-import.c +++ b/fast-import.c @@ -2712,7 +2712,7 @@ static void parse_new_tag(void) /* Obtain the new tag name from the rest of our command */ sp = strchr(command_buf.buf, ' ') + 1; t = pool_alloc(sizeof(struct tag)); - t->next_tag = NULL; + memset(t, 0, sizeof(struct tag)); t->name = pool_strdup(sp); if (last_tag) last_tag->next_tag = t; -- cgit v0.10.2-6-g49f6 From a8747a1098324c418d2d1de2b563f8e3155dc32f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Mar 2012 11:32:08 -0800 Subject: fsck doc: a minor typofix Reword the misspelled "squelch" noticed by Hermann Gaustere to say "omit", which would sit better anyway. Signed-off-by: Junio C Hamano diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt index 47e2f19..bbb25da 100644 --- a/Documentation/git-fsck.txt +++ b/Documentation/git-fsck.txt @@ -33,7 +33,7 @@ index file, all SHA1 references in .git/refs/*, and all reflogs (unless --dangling:: --no-dangling:: Print objects that exist but that are never 'directly' used (default). - `--no-dangling` can be used to squech this information from the output. + `--no-dangling` can be used to omit this information from the output. --root:: Report root nodes. -- cgit v0.10.2-6-g49f6 From 69f4e08f535d4e5a035069a64d1ebaea7be55d83 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Mar 2012 14:29:07 -0800 Subject: Git 1.7.9.3 Signed-off-by: Junio C Hamano diff --git a/Documentation/git.txt b/Documentation/git.txt index 22fadeb..b257d80 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -44,9 +44,10 @@ unreleased) version of git, that is available from 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v1.7.9.2/git.html[documentation for release 1.7.9.2] +* link:v1.7.9.3/git.html[documentation for release 1.7.9.3] * release notes for + link:RelNotes/1.7.9.3.txt[1.7.9.3], link:RelNotes/1.7.9.2.txt[1.7.9.2], link:RelNotes/1.7.9.1.txt[1.7.9.1], link:RelNotes/1.7.9.txt[1.7.9]. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index a6b6db7..de203dd 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.7.9.2 +DEF_VER=v1.7.9.3 LF=' ' -- cgit v0.10.2-6-g49f6 From 85551232b56e763ecfcc7222e0858bac4e962c80 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Tue, 6 Mar 2012 14:15:01 +0100 Subject: perf: compare diff algorithms 8c912ee (teach --histogram to diff, 2011-07-12) claimed histogram diff was faster than both Myers and patience. We have since incorporated a performance testing framework, so add a test that compares the various diff tasks performed in a real 'log -p' workload. This does indeed show that histogram diff slightly beats Myers, while patience is much slower than the others. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano diff --git a/t/perf/p4000-diff-algorithms.sh b/t/perf/p4000-diff-algorithms.sh new file mode 100755 index 0000000..d6e505c --- /dev/null +++ b/t/perf/p4000-diff-algorithms.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +test_description="Tests diff generation performance" + +. ./perf-lib.sh + +test_perf_default_repo + +test_perf 'log -3000 (baseline)' ' + git log -1000 >/dev/null +' + +test_perf 'log --raw -3000 (tree-only)' ' + git log --raw -3000 >/dev/null +' + +test_perf 'log -p -3000 (Myers)' ' + git log -p -3000 >/dev/null +' + +test_perf 'log -p -3000 --histogram' ' + git log -p -3000 --histogram >/dev/null +' + +test_perf 'log -p -3000 --patience' ' + git log -p -3000 --patience >/dev/null +' + +test_done -- cgit v0.10.2-6-g49f6 From d909e0761c234b28aac77566368c1ee5451a856a Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Tue, 6 Mar 2012 14:15:02 +0100 Subject: Document the --histogram diff option Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 66624a1..de2206b 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -52,6 +52,9 @@ endif::git-format-patch[] --patience:: Generate a diff using the "patience diff" algorithm. +--histogram:: + Generate a diff using the "histogram diff" algorithm. + --stat[=[,[,]]]:: Generate a diffstat. You can override the default output width for 80-column terminal by `--stat=`. -- cgit v0.10.2-6-g49f6 From 0dbe6592ccbd1a394a69a52074e3729d546fe952 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Tue, 6 Mar 2012 15:50:37 +0100 Subject: t5704: fix nonportable sed/grep usages OS X's sed and grep would complain with (respectively) sed: 1: "/^-/{p;q}": extra characters at the end of q command grep: Regular expression too big For sed, use an explicit ; to terminate the q command. For grep, spell the "40 hex digits" explicitly in the regex, which should be safe as other tests already use this and we haven't got breakage reports on OS X about them. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh index a51c8b0..9e43731 100755 --- a/t/t5704-bundle.sh +++ b/t/t5704-bundle.sh @@ -54,8 +54,8 @@ test_expect_success 'ridiculously long subject in boundary' ' git bundle list-heads long-subject-bundle.bdl >heads && test -s heads && git fetch long-subject-bundle.bdl && - sed -n "/^-/{p;q}" long-subject-bundle.bdl >boundary && - grep "^-$_x40 " boundary + sed -n "/^-/{p;q;}" long-subject-bundle.bdl >boundary && + grep "^-[0-9a-f]\\{40\\} " boundary ' test_done -- cgit v0.10.2-6-g49f6 From 56a33c8f1bb5cef11ddf046f7b570f527ea77d37 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 7 Mar 2012 12:51:55 -0800 Subject: Git 1.7.10-rc0 Signed-off-by: Junio C Hamano diff --git a/Documentation/RelNotes/1.7.10.txt b/Documentation/RelNotes/1.7.10.txt index b966a8e..ae446e0 100644 --- a/Documentation/RelNotes/1.7.10.txt +++ b/Documentation/RelNotes/1.7.10.txt @@ -1,6 +1,31 @@ Git v1.7.10 Release Notes ========================= +Compatibility Notes +------------------- + + * From this release on, the "git merge" command in an interactive + session will start an editor when it automatically resolves the + merge for the user to explain the resulting commit, just like the + "git commit" command does when it wasn't given a commit message. + + If you have a script that runs "git merge" and keeps its standard + input and output attached to the user's terminal, and if you do not + want the user to explain the resulting merge commits, you can + export GIT_MERGE_AUTOEDIT environment variable set to "no", like + this: + + #!/bin/sh + GIT_MERGE_AUTOEDIT=no + export GIT_MERGE_AUTOEDIT + + to disable this behaviour (if you want your users to explain their + merge commits, you do not have to do anything). Alternatively, you + can give the "--no-edit" option to individual invocations of the + "git merge" command if you know everybody who uses your script has + Git v1.7.8 or newer. + + Updates since v1.7.9 -------------------- @@ -37,12 +62,19 @@ UI, Workflows & Features lines are taken from the postimage, in order to make it easier to view the output. + * "git diff --stat" learned to adjust the width of the output on + wider terminals, and give more columns to pathnames as needed. + * "diff-highlight" filter (in contrib/) was updated to produce more aesthetically pleasing output. * "fsck" learned "--no-dangling" option to omit dangling object information. + * "git log -G" learned to pay attention to the "-i" option and can + find patch hunks that introduce or remove a string that matches the + given pattern ignoring the case. + * "git merge" in an interactive session learned to spawn the editor by default to let the user edit the auto-generated merge message, to encourage people to explain their merges better. Legacy scripts @@ -50,6 +82,10 @@ UI, Workflows & Features Both "git merge" and "git pull" can be given --no-edit from the command line to accept the auto-generated merge message. + * The advise message given when the user didn't give enough clue on + what to merge to "git pull" and "git merge" has been updated to + be more concise and easier to understand. + * "git push" learned the "--prune" option, similar to "git fetch". * "git symbolic-ref" learned the "--short" option to abbreviate the @@ -72,7 +108,7 @@ UI, Workflows & Features Foreign Interface - * Improved handling of views, labels and branches in git-p4 (in contrib). + * Improved handling of views, labels and branches in "git-p4" (in contrib). * "git-p4" (in contrib) suffered from unnecessary merge conflicts when p4 expanded the embedded $RCS$-like keywords; it can be now told to @@ -83,11 +119,13 @@ Foreign Interface * "vcs-svn"/"svn-fe" learned to read dumps with svn-deltas and support incremental imports. + * "git difftool/mergetool" learned to drive DeltaWalker. + Performance - * During "git upload-pack" in response to "git fetch", unnecessary calls - to parse_object() have been eliminated, to help performance in - repositories with excessive number of refs. + * Unnecessary calls to parse_object() "git upload-pack" makes in + response to "git fetch", have been eliminated, to help performance + in repositories with excessive number of refs. Internal Implementation (please report possible regressions) @@ -108,6 +146,9 @@ Internal Implementation (please report possible regressions) * t/Makefile is adjusted to prevent newer versions of GNU make from running tests in seemingly random order. + * The code to check if a path points at a file beyond a symbolic link + has been restructured to be thread-safe. + Also contains minor documentation updates and code clean-ups. @@ -118,6 +159,17 @@ Unless otherwise noted, all the fixes since v1.7.9 in the maintenance releases are contained in this release (see release notes to them for details). + * "git bundle" did not record boundary commits correctly when there + are many of them. + (merge efe4be1 tr/maint-bundle-boundary later to maint). + + * "git diff-index" and its friends at the plumbing level showed the + "diff --git" header and nothing else for a path whose cached stat + info is dirty without actual difference when asked to produce a + patch. This was a longstanding bug that we could have fixed long + time ago. + (merge b3f01ff jc/maint-diff-patch-header later to maint). + * The code to synthesize the fake ancestor tree used by 3-way merge fallback in "git am" was not prepared to read a patch created with a non-standard -p value. @@ -129,7 +181,7 @@ details). --- exec >/var/tmp/1 -O=v1.7.9.2-383-gb8b5290 +O=v1.7.9.3-366-g1e4d087 echo O=$(git describe) git log --first-parent --oneline ^maint $O.. echo diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index c25fd2a..f28ceef 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.7.9.GIT +DEF_VER=v1.7.10-rc0 LF=' ' -- cgit v0.10.2-6-g49f6