diff options
261 files changed, 2942 insertions, 1472 deletions
diff --git a/.gitattributes b/.gitattributes index 5e98806c6c..320e33c327 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,3 @@ * whitespace=!indent,trail,space -*.[ch] whitespace=indent,trail,space +*.[ch] whitespace=indent,trail,space diff=cpp *.sh whitespace=indent,trail,space diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index 7f4769a02c..4cd95da6b1 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -527,12 +527,13 @@ Writing Documentation: or commands: Literal examples (e.g. use of command-line options, command names, - configuration and environment variables) must be typeset in monospace (i.e. - wrapped with backticks): + branch names, configuration and environment variables) must be + typeset in monospace (i.e. wrapped with backticks): `--pretty=oneline` `git rev-list` `remote.pushDefault` `GIT_DIR` + `HEAD` An environment variable must be prefixed with "$" only when referring to its value and not when referring to the variable itself, in this case there is diff --git a/Documentation/RelNotes/2.10.0.txt b/Documentation/RelNotes/2.10.0.txt index 3853b3dec6..4252eb7348 100644 --- a/Documentation/RelNotes/2.10.0.txt +++ b/Documentation/RelNotes/2.10.0.txt @@ -31,7 +31,6 @@ UI, Workflows & Features * "git add -i/-p" learned to honor diff.compactionHeuristic experimental knob, so that the user can work on the same hunk split as "git diff" output. - (merge 46e3d17 jk/add-i-diff-compact-heuristics later to maint). * "upload-pack" allows a custom "git pack-objects" replacement when responding to "fetch/clone" via the uploadpack.packObjectsHook. @@ -53,7 +52,34 @@ UI, Workflows & Features draw text that is to the right of the ancestry-graph section. It also now accepts negative N that means the column limit is relative to the right border. - (merge 066790d nd/graph-width-padded later to maint). + + * A careless invocation of "git send-email directory/" after editing + 0001-change.patch with an editor often ends up sending both + 0001-change.patch and its backup file, 0001-change.patch~, causing + embarrassment and a minor confusion. Detect such an input and + offer to skip the backup files when sending the patches out. + (merge 531220b jc/send-email-skip-backup later to maint). + + * "git submodule update" that drives many "git clone" could + eventually hit flaky servers/network conditions on one of the + submodules; the command learned to retry the attempt. + + * The output coloring scheme learned two new attributes, italic and + strike, in addition to existing bold, reverse, etc. + + * "git log" learns log.showSignature configuration variable, and a + command line option "--no-show-signature" to countermand it. + (merge fce04c3 mj/log-show-signature-conf later to maint). + + * A couple of "git svn" updates. + + * More markings of messages for i18n, with updates to various tests + to pass GETTEXT_POISON tests. + + * "git archive" learned to handle files that are larger than 8GB and + commits far in the future than expressible by the traditional US-TAR + format. + (merge 5caeeb8 jk/big-and-future-archive-tar later to maint). Performance, Internal Implementation, Development Support etc. @@ -66,7 +92,6 @@ Performance, Internal Implementation, Development Support etc. connection from a client that silently goes offline can hang around for a long time, wasting resources. The socket-level KEEPALIVE has been enabled to allow the OS to notice such failed connections. - (merge a43b68a ew/daemon-socket-keepalive later to maint). * "git upload-pack" command has been updated to use the parse-options API. @@ -92,19 +117,16 @@ Performance, Internal Implementation, Development Support etc. * The ownership rule for the piece of memory that hold references to be fetched in "git fetch" was screwy, which has been cleaned up. - (merge b7410f6 km/fetch-do-not-free-remote-name later to maint). * "git bisect" makes an internal call to "git diff-tree" when bisection finds the culprit, but this call did not initialize the data structure to pass to the diff-tree API correctly. - (merge 43ec550 jk/bisect-show-tree later to maint). * Further preparatory clean-up for "worktree" feature continues. (merge 0409e0b nd/worktree-cleanup-post-head-protection later to maint). * Formats of the various data (and how to validate them) where we use GPG signature have been documented. - (merge cc6ee97 mg/signature-doc later to maint). * A new run-command API function pipe_command() is introduced to sanely feed data to the standard input while capturing data from @@ -116,6 +138,9 @@ Performance, Internal Implementation, Development Support etc. errors (instead of relying on GPG's exit status). (merge efee955 jk/gpg-interface-cleanup later to maint). + * Allow t/perf framework to use the features from the most recent + version of Git even when testing an older installed version. + Also contains various documentation updates and code clean-ups. @@ -132,18 +157,15 @@ notes for details). --no-color or with --color=auto when the output is not connected to a tty; this was corrected to make the format truly behave as "auto". - (merge b15a3e0 et/pretty-format-c-auto later to maint). * "git rev-list --count" whose walk-length is limited with "-n" option did not work well with the counting optimized to look at the bitmap index. - (merge fb85db8 jk/rev-list-count-with-bitmap later to maint). * "git show -W" (extend hunks to cover the entire function, delimited by lines that match the "funcname" pattern) used to show the entire file when a change added an entire function at the end of the file, which has been fixed. - (merge 6f8d9bc rs/xdiff-hunk-with-func-line later to maint). * The documentation set has been updated so that literal commands, configuration variables and environment variables are consistently @@ -186,16 +208,13 @@ notes for details). that recurses down to submodules by forcing the submodules to also be cloned shallowly, which many server instances that host upstream of the submodules are not prepared for. - (merge 18a74a0 sb/clone-shallow-passthru later to maint). * Fix unnecessarily waste in the idiomatic use of ': ${VAR=default}' to set the default value, without enclosing it in double quotes. - (merge 01247e0 lc/shell-default-value-noexpand later to maint). * Some platform-specific code had non-ANSI strict declarations of C functions that do not take any parameters, which has been corrected. - (merge 0767172 js/mingw-parameter-less-c-functions later to maint). * The internal code used to show local timezone offset is not prepared to handle timestamps beyond year 2100, and gave a @@ -207,22 +226,64 @@ notes for details). * One among four invocations of readlink(1) in our test suite has been rewritten so that the test can run on systems without the command (others are in valgrind test framework and t9802). - (merge d2addc3 ak/t7800-wo-readlink later to maint). * t/perf needs /usr/bin/time with GNU extension; the invocation of it is updated to "gtime" on Darwin. - (merge e3efa94 js/perf-on-apple later to maint). * A bug, which caused "git p4" while running under verbose mode to report paths that are omitted due to branch prefix incorrectly, has been fixed; the command said "Ignoring file outside of prefix" for paths that are _inside_. - (merge 09667d0 ao/p4-has-branch-prefix-fix later to maint). + + * The top level documentation "git help git" still pointed at the + documentation set hosted at now-defunct google-code repository. + Update it to point to https://git.github.io/htmldocs/git.html + instead. + + * A helper function that takes the contents of a commit object and + finds its subject line did not ignore leading blank lines, as is + commonly done by other codepaths. Make it ignore leading blank + lines to match. + (merge 054a5ae js/find-commit-subject-ignore-leading-blanks later to maint). + + * For a long time, we carried an in-code comment that said our + colored output would work only when we use fprintf/fputs on + Windows, which no longer is the case for the past few years. + (merge 3d0a833 js/color-on-windows-comment later to maint). + + * "gc.autoPackLimit" when set to 1 should not trigger a repacking + when there is only one pack, but the code counted poorly and did + so. + (merge 5f4e3bf ew/gc-auto-pack-limit-fix later to maint). + + * Add a test to specify the desired behaviour that currently is not + available in "git rebase -Xsubtree=...". + (merge 5f35900 dg/subtree-rebase-test later to maint). + + * More mark-up updates to typeset strings that are expected to + literally typed by the end user in fixed-width font. + (merge 661c3e9 mm/doc-tt later to maint). + + * "git commit --amend --allow-empty-message -S" for a commit without + any message body could have misidentified where the header of the + commit object ends. + (merge 3324dd8 js/sign-empty-commit-fix later to maint). + + * "git rebase -i --autostash" did not restore the auto-stashed change + when the operation was aborted. + (merge 33ba9c6 ps/rebase-i-auto-unstash-upon-abort later to maint). + + * Git does not know what the contents in the index should be for a + path added with "git add -N" yet, so "git grep --cached" should not + show hits (or show lack of hits, with -L) in such a path, but that + logic does not apply to "git grep", i.e. searching in the working + tree files. But we did so by mistake, which has been corrected. + (merge b8e47d1 nd/ita-cleanup later to maint). * Other minor clean-ups and documentation updates (merge e51b0df pb/commit-editmsg-path later to maint). (merge b333d0d jk/send-pack-stdio later to maint). (merge fcf0fe9 lf/sideband-returns-void later to maint). - (merge 5819c2e sb/t5614-modernize later to maint). - (merge fe0537a cb/t7810-test-label-fix later to maint). - (merge 412b9a1 jc/t2300-setup later to maint). + (merge c2691e2 ah/unpack-trees-advice-messages later to maint). + (merge 82f6178 nd/doc-new-command later to maint). + (merge fa90ab4 js/t3404-grammo-fix later to maint). diff --git a/Documentation/RelNotes/2.9.1.txt b/Documentation/RelNotes/2.9.1.txt index 369383b33d..338394097e 100644 --- a/Documentation/RelNotes/2.9.1.txt +++ b/Documentation/RelNotes/2.9.1.txt @@ -59,4 +59,59 @@ Fixes since v2.9 * "git cherry-pick A" worked on an unborn branch, but "git cherry-pick A..B" didn't. + * "git add -i/-p" learned to honor diff.compactionHeuristic + experimental knob, so that the user can work on the same hunk split + as "git diff" output. + + * "log --graph --format=" learned that "%>|(N)" specifies the width + relative to the terminal's left edge, not relative to the area to + draw text that is to the right of the ancestry-graph section. It + also now accepts negative N that means the column limit is relative + to the right border. + + * The ownership rule for the piece of memory that hold references to + be fetched in "git fetch" was screwy, which has been cleaned up. + + * "git bisect" makes an internal call to "git diff-tree" when + bisection finds the culprit, but this call did not initialize the + data structure to pass to the diff-tree API correctly. + + * Formats of the various data (and how to validate them) where we use + GPG signature have been documented. + + * Fix an unintended regression in v2.9 that breaks "clone --depth" + that recurses down to submodules by forcing the submodules to also + be cloned shallowly, which many server instances that host upstream + of the submodules are not prepared for. + + * Fix unnecessarily waste in the idiomatic use of ': ${VAR=default}' + to set the default value, without enclosing it in double quotes. + + * Some platform-specific code had non-ANSI strict declarations of C + functions that do not take any parameters, which has been + corrected. + + * The internal code used to show local timezone offset is not + prepared to handle timestamps beyond year 2100, and gave a + bogus offset value to the caller. Use a more benign looking + +0000 instead and let "git log" going in such a case, instead + of aborting. + + * One among four invocations of readlink(1) in our test suite has + been rewritten so that the test can run on systems without the + command (others are in valgrind test framework and t9802). + + * t/perf needs /usr/bin/time with GNU extension; the invocation of it + is updated to "gtime" on Darwin. + + * A bug, which caused "git p4" while running under verbose mode to + report paths that are omitted due to branch prefix incorrectly, has + been fixed; the command said "Ignoring file outside of prefix" for + paths that are _inside_. + + * The top level documentation "git help git" still pointed at the + documentation set hosted at now-defunct google-code repository. + Update it to point to https://git.github.io/htmldocs/git.html + instead. + Also contains minor documentation updates and code clean-ups. diff --git a/Documentation/RelNotes/2.9.2.txt b/Documentation/RelNotes/2.9.2.txt new file mode 100644 index 0000000000..2620003dcf --- /dev/null +++ b/Documentation/RelNotes/2.9.2.txt @@ -0,0 +1,13 @@ +Git v2.9.2 Release Notes +======================== + +Fixes since v2.9.1 +------------------ + + * A fix merged to v2.9.1 had a few tests that are not meant to be + run on platforms without 64-bit long, which caused unnecessary + test failures on them because we didn't detect the platform and + skip them. These tests are now skipped on platforms that they + are not applicable to. + +No other change is included in this update. diff --git a/Documentation/config.txt b/Documentation/config.txt index e208af118d..e455faeb23 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -140,7 +140,7 @@ boolean:: false;; Boolean false can be spelled as `no`, `off`, `false`, or `0`. + -When converting value to the canonical form using '--bool' type +When converting value to the canonical form using `--bool` type specifier; 'git config' will ensure that the output is "true" or "false" (spelled in lowercase). @@ -150,27 +150,34 @@ integer:: 1024", "by 1024x1024", etc. color:: - The value for a variables that takes a color is a list of - colors (at most two) and attributes (at most one), separated - by spaces. The colors accepted are `normal`, `black`, - `red`, `green`, `yellow`, `blue`, `magenta`, `cyan` and - `white`; the attributes are `bold`, `dim`, `ul`, `blink` and - `reverse`. The first color given is the foreground; the - second is the background. The position of the attribute, if - any, doesn't matter. Attributes may be turned off specifically - by prefixing them with `no` (e.g., `noreverse`, `noul`, etc). -+ -Colors (foreground and background) may also be given as numbers between -0 and 255; these use ANSI 256-color mode (but note that not all -terminals may support this). If your terminal supports it, you may also -specify 24-bit RGB values as hex, like `#ff0ab3`. -+ -The attributes are meant to be reset at the beginning of each item -in the colored output, so setting color.decorate.branch to `black` -will paint that branch name in a plain `black`, even if the previous -thing on the same output line (e.g. opening parenthesis before the -list of branch names in `log --decorate` output) is set to be -painted with `bold` or some other attribute. + The value for a variable that takes a color is a list of + colors (at most two, one for foreground and one for background) + and attributes (as many as you want), separated by spaces. ++ +The basic colors accepted are `normal`, `black`, `red`, `green`, `yellow`, +`blue`, `magenta`, `cyan` and `white`. The first color given is the +foreground; the second is the background. ++ +Colors may also be given as numbers between 0 and 255; these use ANSI +256-color mode (but note that not all terminals may support this). If +your terminal supports it, you may also specify 24-bit RGB values as +hex, like `#ff0ab3`. ++ +The accepted attributes are `bold`, `dim`, `ul`, `blink`, `reverse`, +`italic`, and `strike` (for crossed-out or "strikethrough" letters). +The position of any attributes with respect to the colors +(before, after, or in between), doesn't matter. Specific attributes may +be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`, +`no-ul`, etc). ++ +For git's pre-defined color slots, the attributes are meant to be reset +at the beginning of each item in the colored output. So setting +`color.decorate.branch` to `black` will paint that branch name in a +plain `black`, even if the previous thing on the same output line (e.g. +opening parenthesis before the list of branch names in `log --decorate` +output) is set to be painted with `bold` or some other attribute. +However, custom log formats may do more complicated and layered +coloring, and the negated forms may be useful there. pathname:: A variable that takes a pathname value can be given a @@ -443,6 +450,13 @@ specify that no proxy be used for a given domain pattern. This is useful for excluding servers inside a firewall from proxy use, while defaulting to a common proxy for external domains. +core.sshCommand:: + If this variable is set, `git fetch` and `git push` will + use the specified command instead of `ssh` when they need to + connect to a remote system. The command is in the same form as + the `GIT_SSH_COMMAND` environment variable and is overridden + when the environment variable is set. + core.ignoreStat:: If true, Git will avoid using lstat() calls to detect if files have changed by setting the "assume-unchanged" bit for those tracked files @@ -481,7 +495,7 @@ core.worktree:: If `GIT_COMMON_DIR` environment variable is set, core.worktree is ignored and not used for determining the root of working tree. This can be overridden by the `GIT_WORK_TREE` environment - variable and the '--work-tree' command-line option. + variable and the `--work-tree` command-line option. The value can be an absolute path or relative to the path to the .git directory, which is either specified by --git-dir or GIT_DIR, or automatically discovered. @@ -779,7 +793,7 @@ core.abbrev:: add.ignoreErrors:: add.ignore-errors (deprecated):: Tells 'git add' to continue adding files when some files cannot be - added due to indexing errors. Equivalent to the '--ignore-errors' + added due to indexing errors. Equivalent to the `--ignore-errors` option of linkgit:git-add[1]. `add.ignore-errors` is deprecated, as it does not follow the usual naming convention for configuration variables. @@ -805,9 +819,9 @@ from the original current directory. See linkgit:git-rev-parse[1]. am.keepcr:: If true, git-am will call git-mailsplit for patches in mbox format - with parameter '--keep-cr'. In this case git-mailsplit will + with parameter `--keep-cr`. In this case git-mailsplit will not remove `\r` from lines ending with `\r\n`. Can be overridden - by giving '--no-keep-cr' from the command line. + by giving `--no-keep-cr` from the command line. See linkgit:git-am[1], linkgit:git-mailsplit[1]. am.threeWay:: @@ -820,7 +834,7 @@ am.threeWay:: apply.ignoreWhitespace:: When set to 'change', tells 'git apply' to ignore changes in - whitespace, in the same way as the '--ignore-space-change' + whitespace, in the same way as the `--ignore-space-change` option. When set to one of: no, none, never, false tells 'git apply' to respect all whitespace differences. @@ -828,7 +842,7 @@ apply.ignoreWhitespace:: apply.whitespace:: Tells 'git apply' how to handle whitespaces, in the same way - as the '--whitespace' option. See linkgit:git-apply[1]. + as the `--whitespace` option. See linkgit:git-apply[1]. branch.autoSetupMerge:: Tells 'git branch' and 'git checkout' to set up new branches @@ -930,7 +944,7 @@ browser.<tool>.cmd:: browser.<tool>.path:: Override the path for the given tool that may be used to - browse HTML help (see '-w' option in linkgit:git-help[1]) or a + browse HTML help (see `-w` option in linkgit:git-help[1]) or a working repository in gitweb (see linkgit:git-instaweb[1]). clean.requireForce:: @@ -1229,6 +1243,11 @@ fetch.prune:: If true, fetch will automatically behave as if the `--prune` option was given on the command line. See also `remote.<name>.prune`. +fetch.output:: + Control how ref update status is printed. Valid values are + `full` and `compact`. Default value is `full`. See section + OUTPUT in linkgit:git-fetch[1] for detail. + format.attach:: Enable multipart/mixed attachments as the default for 'format-patch'. The value can also be a double quoted string @@ -1429,9 +1448,9 @@ gitcvs.logFile:: gitcvs.usecrlfattr:: If true, the server will look up the end-of-line conversion - attributes for files to determine the '-k' modes to use. If + attributes for files to determine the `-k` modes to use. If the attributes force Git to treat a file as text, - the '-k' mode will be left blank so CVS clients will + the `-k` mode will be left blank so CVS clients will treat it as text. If they suppress text conversion, the file will be set with '-kb' mode, which suppresses any newline munging the client might otherwise do. If the attributes do not allow @@ -1501,16 +1520,16 @@ gitweb.snapshot:: See linkgit:gitweb.conf[5] for description. grep.lineNumber:: - If set to true, enable '-n' option by default. + If set to true, enable `-n` option by default. grep.patternType:: Set the default matching behavior. Using a value of 'basic', 'extended', - 'fixed', or 'perl' will enable the '--basic-regexp', '--extended-regexp', - '--fixed-strings', or '--perl-regexp' option accordingly, while the + 'fixed', or 'perl' will enable the `--basic-regexp`, `--extended-regexp`, + `--fixed-strings`, or `--perl-regexp` option accordingly, while the value 'default' will return to the default matching behavior. grep.extendedRegexp:: - If set to true, enable '--extended-regexp' option by default. This + If set to true, enable `--extended-regexp` option by default. This option is ignored when the `grep.patternType` option is set to a value other than 'default'. @@ -1967,7 +1986,7 @@ log.decorate:: specified, the full ref name (including prefix) will be printed. If 'auto' is specified, then if the output is going to a terminal, the ref names are shown as if 'short' were given, otherwise no ref - names are shown. This is the same as the '--decorate' option + names are shown. This is the same as the `--decorate` option of the `git log`. log.follow:: @@ -2350,16 +2369,16 @@ new default). -- push.followTags:: - If set to true enable '--follow-tags' option by default. You + If set to true enable `--follow-tags` option by default. You may override this configuration at time of push by specifying - '--no-follow-tags'. + `--no-follow-tags`. push.gpgSign:: May be set to a boolean value, or the string 'if-asked'. A true - value causes all pushes to be GPG signed, as if '--signed' is + value causes all pushes to be GPG signed, as if `--signed` is passed to linkgit:git-push[1]. The string 'if-asked' causes pushes to be signed if the server supports it, as if - '--signed=if-asked' is passed to 'git push'. A false value may + `--signed=if-asked` is passed to 'git push'. A false value may override a value from a lower-priority config file. An explicit command-line flag always overrides this config option. @@ -2382,7 +2401,7 @@ rebase.stat:: rebase. False by default. rebase.autoSquash:: - If set to true enable '--autosquash' option by default. + If set to true enable `--autosquash` option by default. rebase.autoStash:: When set to true, automatically create a temporary stash diff --git a/Documentation/diff-config.txt b/Documentation/diff-config.txt index f1101c7b21..d5a5b17d50 100644 --- a/Documentation/diff-config.txt +++ b/Documentation/diff-config.txt @@ -105,7 +105,7 @@ diff.orderFile:: diff.renameLimit:: The number of files to consider when performing the copy/rename - detection; equivalent to the 'git diff' option '-l'. + detection; equivalent to the 'git diff' option `-l`. diff.renames:: Whether and how Git detects renames. If set to "false", diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index 85b08909ce..cf5262622f 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -46,11 +46,11 @@ That is, from the left to the right: . sha1 for "dst"; 0\{40\} if creation, unmerged or "look at work tree". . a space. . status, followed by optional "score" number. -. a tab or a NUL when '-z' option is used. +. a tab or a NUL when `-z` option is used. . path for "src" -. a tab or a NUL when '-z' option is used; only exists for C or R. +. a tab or a NUL when `-z` option is used; only exists for C or R. . path for "dst"; only exists for C or R. -. an LF or a NUL when '-z' option is used, to terminate the record. +. an LF or a NUL when `-z` option is used, to terminate the record. Possible status letters are: @@ -86,7 +86,7 @@ diff format for merges ---------------------- "git-diff-tree", "git-diff-files" and "git-diff --raw" -can take '-c' or '--cc' option +can take `-c` or `--cc` option to generate diff output also for merge commits. The output differs from the format described above in the following way: diff --git a/Documentation/diff-generate-patch.txt b/Documentation/diff-generate-patch.txt index c91afee21c..d2a7ff56e8 100644 --- a/Documentation/diff-generate-patch.txt +++ b/Documentation/diff-generate-patch.txt @@ -2,7 +2,7 @@ Generating patches with -p -------------------------- When "git-diff-index", "git-diff-tree", or "git-diff-files" are run -with a '-p' option, "git diff" without the '--raw' option, or +with a `-p` option, "git diff" without the `--raw` option, or "git log" with the "-p" option, they do not produce the output described above; instead they produce a patch file. You can customize the creation of such patches via the @@ -114,11 +114,11 @@ index fabadb8,cc95eb0..4866510 ------------ 1. It is preceded with a "git diff" header, that looks like - this (when '-c' option is used): + this (when `-c` option is used): diff --combined file + -or like this (when '--cc' option is used): +or like this (when `--cc` option is used): diff --cc file diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index b05a8341e8..9eab1f5fa4 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -88,7 +88,7 @@ ifndef::git-pull[] to whatever else would otherwise be fetched. Using this option alone does not subject tags to pruning, even if --prune is used (though tags may be pruned anyway if they are also the - destination of an explicit refspec; see '--prune'). + destination of an explicit refspec; see `--prune`). --recurse-submodules[=yes|on-demand|no]:: This option controls if and under what conditions new commits of @@ -110,7 +110,7 @@ ifndef::git-pull[] --no-recurse-submodules:: Disable recursive fetching of submodules (this has the same effect as - using the '--recurse-submodules=no' option). + using the `--recurse-submodules=no` option). --submodule-prefix=<path>:: Prepend <path> to paths printed in informative messages @@ -137,7 +137,7 @@ endif::git-pull[] --upload-pack <upload-pack>:: When given, and the repository to fetch from is handled - by 'git fetch-pack', '--exec=<upload-pack>' is passed to + by 'git fetch-pack', `--exec=<upload-pack>` is passed to the command to specify non-default path for the command run on the other end. diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index 6348c29fea..12879e4029 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -199,12 +199,12 @@ When initially invoking `git am`, you give it the names of the mailboxes to process. Upon seeing the first patch that does not apply, it aborts in the middle. You can recover from this in one of two ways: -. skip the current patch by re-running the command with the '--skip' +. skip the current patch by re-running the command with the `--skip` option. . hand resolve the conflict in the working directory, and update the index file to bring it into a state that the patch should - have produced. Then run the command with the '--continue' option. + have produced. Then run the command with the `--continue` option. The command refuses to process new mailboxes until the current operation is finished, so if you decide to start over from scratch, diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index d9f960b509..2bb9a577a2 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -358,7 +358,7 @@ OPTIONS --no-checkout:: + Do not checkout the new working tree at each iteration of the bisection -process. Instead just update a special reference named 'BISECT_HEAD' to make +process. Instead just update a special reference named `BISECT_HEAD` to make it point to the commit that should be tested. + This option may be useful when the test you would perform in each step diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index 4a7037f1c8..1fe73448f3 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -39,10 +39,10 @@ named commit). With `--merged`, only branches merged into the named commit (i.e. the branches whose tip commits are reachable from the named commit) will be listed. With `--no-merged` only branches not merged into the named commit will be listed. If the <commit> argument is missing it -defaults to 'HEAD' (i.e. the tip of the current branch). +defaults to `HEAD` (i.e. the tip of the current branch). The command's second form creates a new branch head named <branchname> -which points to the current 'HEAD', or <start-point> if given. +which points to the current `HEAD`, or <start-point> if given. Note that this will create the new branch, but it will not switch the working tree to it; use "git checkout <newbranch>" to switch to the @@ -172,7 +172,7 @@ This option is only applicable in non-verbose mode. + This behavior is the default when the start point is a remote-tracking branch. Set the branch.autoSetupMerge configuration variable to `false` if you -want `git checkout` and `git branch` to always behave as if '--no-track' +want `git checkout` and `git branch` to always behave as if `--no-track` were given. Set it to `always` if you want this behavior when the start-point is either a local or remote-tracking branch. diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index eb3d6945a9..18d03d8e8b 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -15,8 +15,8 @@ SYNOPSIS DESCRIPTION ----------- In its first form, the command provides the content or the type of an object in -the repository. The type is required unless '-t' or '-p' is used to find the -object type, or '-s' is used to find the object size, or '--textconv' is used +the repository. The type is required unless `-t` or `-p` is used to find the +object type, or `-s` is used to find the object size, or `--textconv` is used (which implies type "blob"). In the second form, a list of objects (separated by linefeeds) is provided on @@ -144,13 +144,13 @@ respectively print: OUTPUT ------ -If '-t' is specified, one of the <type>. +If `-t` is specified, one of the <type>. -If '-s' is specified, the size of the <object> in bytes. +If `-s` is specified, the size of the <object> in bytes. -If '-e' is specified, no output. +If `-e` is specified, no output. -If '-p' is specified, the contents of <object> are pretty-printed. +If `-p` is specified, the contents of <object> are pretty-printed. If <type> is specified, the raw (though uncompressed) contents of the <object> will be returned. diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 5e5273e073..7a2201b051 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -157,7 +157,7 @@ of it"). When creating a new branch, set up "upstream" configuration. See "--track" in linkgit:git-branch[1] for details. + -If no '-b' option is given, the name of the new branch will be +If no `-b` option is given, the name of the new branch will be derived from the remote-tracking branch, by looking at the local part of the refspec configured for the corresponding remote, and then stripping the initial part up to the "*". @@ -165,7 +165,7 @@ This would tell us to use "hack" as the local branch when branching off of "origin/hack" (or "remotes/origin/hack", or even "refs/remotes/origin/hack"). If the given name has no slash, or the above guessing results in an empty name, the guessing is aborted. You can -explicitly give a name with '-b' in such a case. +explicitly give a name with `-b` in such a case. --no-track:: Do not set up "upstream" configuration, even if the diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index c104a594af..d35d771fc8 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -47,7 +47,7 @@ OPTIONS For a more complete list of ways to spell commits, see linkgit:gitrevisions[7]. Sets of commits can be passed but no traversal is done by - default, as if the '--no-walk' option was specified, see + default, as if the `--no-walk` option was specified, see linkgit:git-rev-list[1]. Note that specifying a range will feed all <commit>... arguments to a single revision walk (see a later example that uses 'maint master..next'). diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt index 51a7e26a8e..03056dad0d 100644 --- a/Documentation/git-clean.txt +++ b/Documentation/git-clean.txt @@ -16,7 +16,7 @@ DESCRIPTION Cleans the working tree by recursively removing files that are not under version control, starting from the current directory. -Normally, only files unknown to Git are removed, but if the '-x' +Normally, only files unknown to Git are removed, but if the `-x` option is specified, ignored files are also removed. This can, for example, be useful to remove all build products. diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt index cb69faab68..002dae625e 100644 --- a/Documentation/git-commit-tree.txt +++ b/Documentation/git-commit-tree.txt @@ -44,7 +44,7 @@ OPTIONS An existing tree object -p <parent>:: - Each '-p' indicates the id of a parent commit object. + Each `-p` indicates the id of a parent commit object. -m <message>:: A paragraph in the commit log message. This can be given more than diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index e7049537d9..b0a294d3b5 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -75,7 +75,7 @@ OPTIONS -c <commit>:: --reedit-message=<commit>:: - Like '-C', but with '-c' the editor is invoked, so that + Like '-C', but with `-c` the editor is invoked, so that the user can further edit the commit message. --fixup=<commit>:: @@ -260,7 +260,7 @@ FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].) staged for other paths. This is the default mode of operation of 'git commit' if any paths are given on the command line, in which case this option can be omitted. - If this option is specified together with '--amend', then + If this option is specified together with `--amend`, then no paths need to be specified, which can be used to amend the last commit without committing changes that have already been staged. diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index a89c304916..f163113a6f 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -31,29 +31,29 @@ You can query/set/replace/unset options with this command. The name is actually the section and the key separated by a dot, and the value will be escaped. -Multiple lines can be added to an option by using the '--add' option. +Multiple lines can be added to an option by using the `--add` option. If you want to update or unset an option which can occur on multiple lines, a POSIX regexp `value_regex` needs to be given. Only the existing values that match the regexp are updated or unset. If you want to handle the lines that do *not* match the regex, just prepend a single exclamation mark in front (see also <<EXAMPLES>>). -The type specifier can be either '--int' or '--bool', to make +The type specifier can be either `--int` or `--bool`, to make 'git config' ensure that the variable(s) are of the given type and convert the value to the canonical form (simple decimal number for int, -a "true" or "false" string for bool), or '--path', which does some -path expansion (see '--path' below). If no type specifier is passed, no +a "true" or "false" string for bool), or `--path`, which does some +path expansion (see `--path` below). If no type specifier is passed, no checks or transformations are performed on the value. When reading, the values are read from the system, global and repository local configuration files by default, and options -'--system', '--global', '--local' and '--file <filename>' can be +`--system`, `--global`, `--local` and `--file <filename>` can be used to tell the command to read from only that location (see <<FILES>>). When writing, the new value is written to the repository local -configuration file by default, and options '--system', '--global', -'--file <filename>' can be used to tell the command to write to -that location (you can say '--local' but that is the default). +configuration file by default, and options `--system`, `--global`, +`--file <filename>` can be used to tell the command to write to +that location (you can say `--local` but that is the default). This command will fail with non-zero status upon error. Some exit codes are: @@ -138,7 +138,7 @@ See also <<FILES>>. Use the given config file instead of the one specified by GIT_CONFIG. --blob blob:: - Similar to '--file' but use the given blob instead of a file. E.g. + Similar to `--file` but use the given blob instead of a file. E.g. you can use 'master:.gitmodules' to read values from the file '.gitmodules' in the master branch. See "SPECIFYING REVISIONS" section in linkgit:gitrevisions[7] for a more complete list of @@ -220,7 +220,7 @@ See also <<FILES>>. -e:: --edit:: Opens an editor to modify the specified config file; either - '--system', '--global', or repository (default). + `--system`, `--global`, or repository (default). --[no-]includes:: Respect `include.*` directives in config files when looking up @@ -232,7 +232,7 @@ See also <<FILES>>. FILES ----- -If not set explicitly with '--file', there are four files where +If not set explicitly with `--file`, there are four files where 'git config' will search for configuration options: $(prefix)/etc/gitconfig:: @@ -264,11 +264,11 @@ precedence over values read earlier. When multiple values are taken then all values of a key from all files will be used. All writing options will per default write to the repository specific -configuration file. Note that this also affects options like '--replace-all' -and '--unset'. *'git config' will only ever change one file at a time*. +configuration file. Note that this also affects options like `--replace-all` +and `--unset`. *'git config' will only ever change one file at a time*. You can override these rules either by command-line options or by environment -variables. The '--global' and the '--system' options will limit the file used +variables. The `--global` and the `--system` options will limit the file used to the global or system-wide file respectively. The `GIT_CONFIG` environment variable has a similar effect, but you can specify any filename you want. diff --git a/Documentation/git-credential-store.txt b/Documentation/git-credential-store.txt index e3c8f276b1..25fb963f4b 100644 --- a/Documentation/git-credential-store.txt +++ b/Documentation/git-credential-store.txt @@ -44,7 +44,7 @@ OPTIONS FILES ----- -If not set explicitly with '--file', there are two files where +If not set explicitly with `--file`, there are two files where git-credential-store will search for credentials in order of precedence: ~/.git-credentials:: diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt index 00a0679a28..41207a24b0 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@ -74,10 +74,10 @@ OPTIONS akin to the way 'git clone' uses 'origin' by default. -o <branch-for-HEAD>:: - When no remote is specified (via -r) the 'HEAD' branch + When no remote is specified (via -r) the `HEAD` branch from CVS is imported to the 'origin' branch within the Git - repository, as 'HEAD' already has a special meaning for Git. - When a remote is specified the 'HEAD' branch is named + repository, as `HEAD` already has a special meaning for Git. + When a remote is specified the `HEAD` branch is named remotes/<remote>/master mirroring 'git clone' behaviour. Use this option if you want to import into a different branch. @@ -103,7 +103,7 @@ the old cvs2git tool. -p <options-for-cvsps>:: Additional options for cvsps. - The options '-u' and '-A' are implicit and should not be used here. + The options `-u` and '-A' are implicit and should not be used here. + If you need to pass multiple options, separate them with a comma. @@ -122,7 +122,7 @@ If you need to pass multiple options, separate them with a comma. -M <regex>:: Attempt to detect merges based on the commit message with a custom - regex. It can be used with '-m' to enable the default regexes + regex. It can be used with `-m` to enable the default regexes as well. You must escape forward slashes. + The regex must capture the source branch name in $1. @@ -186,7 +186,7 @@ messages, bug-tracking systems, email archives, and the like. OUTPUT ------ -If '-v' is specified, the script reports what it is doing. +If `-v` is specified, the script reports what it is doing. Otherwise, success is indicated the Unix way, i.e. by simply exiting with a zero exit status. diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt index db4d7a917c..a336ae5f6f 100644 --- a/Documentation/git-cvsserver.txt +++ b/Documentation/git-cvsserver.txt @@ -54,7 +54,7 @@ Print usage information and exit You can specify a list of allowed directories. If no directories are given, all are allowed. This is an additional restriction, gitcvs access still needs to be enabled by the `gitcvs.enabled` config option -unless '--export-all' was given, too. +unless `--export-all` was given, too. DESCRIPTION @@ -332,7 +332,7 @@ To get a checkout with the Eclipse CVS client: 3. Browse the 'modules' available. It will give you a list of the heads in the repository. You will not be able to browse the tree from there. Only the heads. -4. Pick 'HEAD' when it asks what branch/tag to check out. Untick the +4. Pick `HEAD` when it asks what branch/tag to check out. Untick the "launch commit wizard" to avoid committing the .project file. Protocol notes: If you are using anonymous access via pserver, just select that. @@ -402,12 +402,12 @@ Exports and tagging (tags and branches) are not supported at this stage. CRLF Line Ending Conversions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -By default the server leaves the '-k' mode blank for all files, +By default the server leaves the `-k` mode blank for all files, which causes the CVS client to treat them as a text files, subject to end-of-line conversion on some platforms. You can make the server use the end-of-line conversion attributes to -set the '-k' modes for files by setting the `gitcvs.usecrlfattr` +set the `-k` modes for files by setting the `gitcvs.usecrlfattr` config variable. See linkgit:gitattributes[5] for more information about end-of-line conversion. @@ -415,9 +415,9 @@ Alternatively, if `gitcvs.usecrlfattr` config is not enabled or the attributes do not allow automatic detection for a filename, then the server uses the `gitcvs.allBinary` config for the default setting. If `gitcvs.allBinary` is set, then file not otherwise -specified will default to '-kb' mode. Otherwise the '-k' mode +specified will default to '-kb' mode. Otherwise the `-k` mode is left blank. But if `gitcvs.allBinary` is set to "guess", then -the correct '-k' mode will be guessed based on the contents of +the correct `-k` mode will be guessed based on the contents of the file. For best consistency with 'cvs', it is probably best to override the diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt index dc20275825..3c91db7bed 100644 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.txt @@ -30,7 +30,7 @@ that service if it is enabled. It verifies that the directory has the magic file "git-daemon-export-ok", and it will refuse to export any Git directory that hasn't explicitly been marked -for export this way (unless the '--export-all' parameter is specified). If you +for export this way (unless the `--export-all` parameter is specified). If you pass some directory paths as 'git daemon' arguments, you can further restrict the offers to a whitelist comprising of those. @@ -90,10 +90,10 @@ OPTIONS is not supported, then --listen=hostname is also not supported and --listen must be given an IPv4 address. Can be given more than once. - Incompatible with '--inetd' option. + Incompatible with `--inetd` option. --port=<n>:: - Listen on an alternative port. Incompatible with '--inetd' option. + Listen on an alternative port. Incompatible with `--inetd` option. --init-timeout=<n>:: Timeout (in seconds) between the moment the connection is established @@ -296,7 +296,7 @@ they correspond to these IP addresses. selectively enable/disable services per repository:: To enable 'git archive --remote' and disable 'git fetch' against a repository, have the following in the configuration file in the - repository (that is the file 'config' next to 'HEAD', 'refs' and + repository (that is the file 'config' next to `HEAD`, 'refs' and 'objects'). + ---------------------------------------------------------------- diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt index c8f28c8c86..e4ac448ff5 100644 --- a/Documentation/git-describe.txt +++ b/Documentation/git-describe.txt @@ -154,7 +154,7 @@ is found, its name will be output and searching will stop. If an exact match was not found, 'git describe' will walk back through the commit history to locate an ancestor commit which has been tagged. The ancestor's tag will be output along with an -abbreviation of the input commit-ish's SHA-1. If '--first-parent' was +abbreviation of the input commit-ish's SHA-1. If `--first-parent` was specified then the walk will only consider the first parent of each commit. diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt index a86cf62e68..a171506952 100644 --- a/Documentation/git-diff-index.txt +++ b/Documentation/git-diff-index.txt @@ -40,13 +40,13 @@ include::diff-format.txt[] Operating Modes --------------- You can choose whether you want to trust the index file entirely -(using the '--cached' flag) or ask the diff logic to show any files +(using the `--cached` flag) or ask the diff logic to show any files that don't match the stat state as being "tentatively changed". Both of these operations are very useful indeed. Cached Mode ----------- -If '--cached' is specified, it allows you to ask: +If `--cached` is specified, it allows you to ask: show me the differences between HEAD and the current index contents (the ones I'd write using 'git write-tree') diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt index 1439486e40..7870e175b7 100644 --- a/Documentation/git-diff-tree.txt +++ b/Documentation/git-diff-tree.txt @@ -43,11 +43,11 @@ include::diff-options.txt[] show tree entry itself as well as subtrees. Implies -r. --root:: - When '--root' is specified the initial commit will be shown as a big + When `--root` is specified the initial commit will be shown as a big creation event. This is equivalent to a diff against the NULL tree. --stdin:: - When '--stdin' is specified, the command does not take + When `--stdin` is specified, the command does not take <tree-ish> arguments from the command line. Instead, it reads lines containing either two <tree>, one <commit>, or a list of <commit> from its standard input. (Use a single space @@ -70,13 +70,13 @@ commits (but not trees). By default, 'git diff-tree --stdin' does not show differences for merge commits. With this flag, it shows differences to that commit from all of its parents. See - also '-c'. + also `-c`. -s:: By default, 'git diff-tree --stdin' shows differences, - either in machine-readable form (without '-p') or in patch - form (with '-p'). This output can be suppressed. It is - only useful with '-v' flag. + either in machine-readable form (without `-p`) or in patch + form (with `-p`). This output can be suppressed. It is + only useful with `-v` flag. -v:: This flag causes 'git diff-tree --stdin' to also show @@ -91,17 +91,17 @@ include::pretty-options.txt[] -c:: This flag changes the way a merge commit is displayed (which means it is useful only when the command is given - one <tree-ish>, or '--stdin'). It shows the differences + one <tree-ish>, or `--stdin`). It shows the differences from each of the parents to the merge result simultaneously instead of showing pairwise diff between a parent and the - result one at a time (which is what the '-m' option does). + result one at a time (which is what the `-m` option does). Furthermore, it lists only files which were modified from all parents. --cc:: This flag changes the way a merge commit patch is displayed, - in a similar way to the '-c' option. It implies the '-c' - and '-p' options and further compresses the patch output + in a similar way to the `-c` option. It implies the `-c` + and `-p` options and further compresses the patch output by omitting uninteresting hunks whose the contents in the parents have only two variants and the merge result picks one of them without modification. When all hunks are uninteresting, the commit diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt index 333cf6ff91..224fb3090b 100644 --- a/Documentation/git-difftool.txt +++ b/Documentation/git-difftool.txt @@ -98,7 +98,7 @@ instead. `--no-symlinks` is the default on Windows. invoked diff tool returns a non-zero exit code. + 'git-difftool' will forward the exit code of the invoked tool when -'--trust-exit-code' is used. +`--trust-exit-code` is used. See linkgit:git-diff[1] for the full list of supported options. diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 644df993f9..2b762654bf 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -1056,7 +1056,7 @@ relative-marks:: no-relative-marks:: force:: Act as though the corresponding command-line option with - a leading '--' was passed on the command line + a leading `--` was passed on the command line (see OPTIONS, above). import-marks:: @@ -1107,7 +1107,7 @@ options the user may specify to git fast-import itself. The `<option>` part of the command may contain any of the options listed in the OPTIONS section that do not change import semantics, -without the leading '--' and is treated in the same way. +without the leading `--` and is treated in the same way. Option commands must be the first commands on the input (not counting feature commands), to give an option command after any non-option diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index 239623cc24..24417ee3a6 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -41,13 +41,13 @@ OPTIONS option, then the refs from stdin are processed after those on the command line. + -If '--stateless-rpc' is specified together with this option then +If `--stateless-rpc` is specified together with this option then the list of refs must be in packet format (pkt-line). Each ref must be in a separate packet, and the list must end with a flush packet. -q:: --quiet:: - Pass '-q' flag to 'git unpack-objects'; this makes the + Pass `-q` flag to 'git unpack-objects'; this makes the cloning process less verbose. -k:: diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt index efe56e0808..9e4216999d 100644 --- a/Documentation/git-fetch.txt +++ b/Documentation/git-fetch.txt @@ -99,6 +99,57 @@ The latter use of the `remote.<repository>.fetch` values can be overridden by giving the `--refmap=<refspec>` parameter(s) on the command line. +OUTPUT +------ + +The output of "git fetch" depends on the transport method used; this +section describes the output when fetching over the Git protocol +(either locally or via ssh) and Smart HTTP protocol. + +The status of the fetch is output in tabular form, with each line +representing the status of a single ref. Each line is of the form: + +------------------------------- + <flag> <summary> <from> -> <to> [<reason>] +------------------------------- + +The status of up-to-date refs is shown only if the --verbose option is +used. + +In compact output mode, specified with configuration variable +fetch.output, if either entire `<from>` or `<to>` is found in the +other string, it will be substituted with `*` in the other string. For +example, `master -> origin/master` becomes `master -> origin/*`. + +flag:: + A single character indicating the status of the ref: +(space);; for a successfully fetched fast-forward; +`+`;; for a successful forced update; +`-`;; for a successfully pruned ref; +`t`;; for a successful tag update; +`*`;; for a successfully fetched new ref; +`!`;; for a ref that was rejected or failed to update; and +`=`;; for a ref that was up to date and did not need fetching. + +summary:: + For a successfully fetched ref, the summary shows the old and new + values of the ref in a form suitable for using as an argument to + `git log` (this is `<old>..<new>` in most cases, and + `<old>...<new>` for forced non-fast-forward updates). + +from:: + The name of the remote ref being fetched from, minus its + `refs/<type>/` prefix. In the case of deletion, the name of + the remote ref is "(none)". + +to:: + The name of the local ref being updated, minus its + `refs/<type>/` prefix. + +reason:: + A human-readable explanation. In the case of successfully fetched + refs, no explanation is needed. For a failed ref, the reason for + failure is described. EXAMPLES -------- diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index bd560d38d9..0a09698c03 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -52,7 +52,7 @@ if different from the rewritten ones, will be stored in the namespace Note that since this operation is very I/O expensive, it might be a good idea to redirect the temporary directory off-disk with the -'-d' option, e.g. on tmpfs. Reportedly the speedup is very noticeable. +`-d` option, e.g. on tmpfs. Reportedly the speedup is very noticeable. Filters @@ -171,7 +171,7 @@ to other tags will be rewritten to point to the underlying commit. untouched. This switch allow git-filter-branch to ignore such commits. Though, this switch only applies for commits that have one and only one parent, it will hence keep merges points. Also, this - option is not compatible with the use of '--commit-filter'. Though you + option is not compatible with the use of `--commit-filter`. Though you just need to use the function 'git_commit_non_empty_tree "$@"' instead of the `git commit-tree "$@"` idiom in your commit filter to make that happen. @@ -197,7 +197,7 @@ to other tags will be rewritten to point to the underlying commit. <rev-list options>...:: Arguments for 'git rev-list'. All positive refs included by these options are rewritten. You may also specify options - such as '--all', but you must use '--' to separate them from + such as `--all`, but you must use `--` to separate them from the 'git filter-branch' options. Implies <<Remap_to_ancestor>>. diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index d9d406dcfb..f57e69bc83 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -142,7 +142,7 @@ align:: <width> and <position> used instead. For instance, `%(align:<width>,<position>)`. If the contents length is more than the width then no alignment is performed. If used with - '--quote' everything in between %(align:...) and %(end) is + `--quote` everything in between %(align:...) and %(end) is quoted, but if nested then only the topmost level performs quoting. diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt index 84ee92e158..7fc68eb319 100644 --- a/Documentation/git-fsck.txt +++ b/Documentation/git-fsck.txt @@ -95,7 +95,7 @@ DISCUSSION git-fsck tests SHA-1 and general object sanity, and it does full tracking of the resulting reachability and everything else. It prints out any corruption it finds (missing or bad objects), and if you use the -'--unreachable' flag it will also print out objects that exist but that +`--unreachable` flag it will also print out objects that exist but that aren't reachable from any of the specified head nodes (or the default set, as mentioned above). diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 40cfe37d00..0ecea6e491 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -41,16 +41,16 @@ CONFIGURATION ------------- grep.lineNumber:: - If set to true, enable '-n' option by default. + If set to true, enable `-n` option by default. grep.patternType:: Set the default matching behavior. Using a value of 'basic', 'extended', - 'fixed', or 'perl' will enable the '--basic-regexp', '--extended-regexp', - '--fixed-strings', or '--perl-regexp' option accordingly, while the + 'fixed', or 'perl' will enable the `--basic-regexp`, `--extended-regexp`, + `--fixed-strings`, or `--perl-regexp` option accordingly, while the value 'default' will return to the default matching behavior. grep.extendedRegexp:: - If set to true, enable '--extended-regexp' option by default. This + If set to true, enable `--extended-regexp` option by default. This option is ignored when the `grep.patternType` option is set to a value other than 'default'. @@ -59,7 +59,7 @@ grep.threads:: 8 threads are used by default (for now). grep.fullName:: - If set to true, enable '--full-name' option by default. + If set to true, enable `--full-name` option by default. grep.fallbackToNoIndex:: If set to true, fall back to git grep --no-index if git grep diff --git a/Documentation/git-gui.txt b/Documentation/git-gui.txt index 8144527ae0..c1a3e8bf07 100644 --- a/Documentation/git-gui.txt +++ b/Documentation/git-gui.txt @@ -35,7 +35,7 @@ blame:: browser:: Start a tree browser showing all files in the specified - commit (or 'HEAD' by default). Files selected through the + commit (or `HEAD` by default). Files selected through the browser are opened in the blame viewer. citool:: diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt index 338b8d61ce..40d328a4b3 100644 --- a/Documentation/git-help.txt +++ b/Documentation/git-help.txt @@ -18,10 +18,10 @@ With no options and no COMMAND or GUIDE given, the synopsis of the 'git' command and a list of the most commonly used Git commands are printed on the standard output. -If the option '--all' or '-a' is given, all available commands are +If the option `--all` or `-a` is given, all available commands are printed on the standard output. -If the option '--guide' or '-g' is given, a list of the useful +If the option `--guide` or `-g` is given, a list of the useful Git guides is also printed on the standard output. If a command, or a guide, is given, a manual page for that command or @@ -176,7 +176,7 @@ Note about git config --global ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Note that all these configuration variables should probably be set -using the '--global' flag, for example like this: +using the `--global` flag, for example like this: ------------------------------------------------ $ git config --global help.format web diff --git a/Documentation/git-http-push.txt b/Documentation/git-http-push.txt index 2e67362bd4..2aceb6f26d 100644 --- a/Documentation/git-http-push.txt +++ b/Documentation/git-http-push.txt @@ -81,13 +81,13 @@ destination side. exist in the set of remote refs; the ref matched <src> locally is used as the name of the destination. -Without '--force', the <src> ref is stored at the remote only if +Without `--force`, the <src> ref is stored at the remote only if <dst> does not exist, or <dst> is a proper subset (i.e. an ancestor) of <src>. This check, known as "fast-forward check", is performed in order to avoid accidentally overwriting the remote ref and lose other peoples' commits from there. -With '--force', the fast-forward check is disabled for all refs. +With `--force`, the fast-forward check is disabled for all refs. Optionally, a <ref> parameter can be prefixed with a plus '+' sign to disable the fast-forward check only on that ref. diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt index a77b901f1d..93d1db6528 100644 --- a/Documentation/git-interpret-trailers.txt +++ b/Documentation/git-interpret-trailers.txt @@ -219,7 +219,7 @@ Signed-off-by: Alice <alice@example.com> Signed-off-by: Bob <bob@example.com> ------------ -* Use the '--in-place' option to edit a message file in place: +* Use the `--in-place` option to edit a message file in place: + ------------ $ cat msg.txt diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 4a6c47f843..32246fdb00 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -198,6 +198,10 @@ log.showRoot:: `git log -p` output would be shown without a diff attached. The default is `true`. +log.showSignature:: + If `true`, `git log` and related commands will act as if the + `--show-signature` option was passed to them. + mailmap.*:: See linkgit:git-shortlog[1]. diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt index 75c3f4157d..078b556665 100644 --- a/Documentation/git-ls-files.txt +++ b/Documentation/git-ls-files.txt @@ -175,7 +175,7 @@ followed by the ("attr/<eolattr>"). Output ------ -'git ls-files' just outputs the filenames unless '--stage' is specified in +'git ls-files' just outputs the filenames unless `--stage` is specified in which case it outputs: [<tag> ]<mode> <object> <stage> <file> diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt index 16e87fd6dd..dbc91f98ff 100644 --- a/Documentation/git-ls-tree.txt +++ b/Documentation/git-ls-tree.txt @@ -20,16 +20,16 @@ in the current working directory. Note that: - the behaviour is slightly different from that of "/bin/ls" in that the '<path>' denotes just a list of patterns to match, e.g. so specifying - directory name (without '-r') will behave differently, and order of the + directory name (without `-r`) will behave differently, and order of the arguments does not matter. - the behaviour is similar to that of "/bin/ls" in that the '<path>' is taken as relative to the current working directory. E.g. when you are in a directory 'sub' that has a directory 'dir', you can run 'git ls-tree -r HEAD dir' to list the contents of the tree (that is - 'sub/dir' in 'HEAD'). You don't want to give a tree that is not at the + 'sub/dir' in `HEAD`). You don't want to give a tree that is not at the root level (e.g. `git ls-tree -r HEAD:sub dir`) in this case, as that - would result in asking for 'sub/sub/dir' in the 'HEAD' commit. + would result in asking for 'sub/sub/dir' in the `HEAD` commit. However, the current working directory can be ignored by passing --full-tree option. @@ -46,7 +46,7 @@ OPTIONS -t:: Show tree entries even when going to recurse them. Has no effect - if '-r' was not passed. '-d' implies '-t'. + if `-r` was not passed. `-d` implies `-t`. -l:: --long:: diff --git a/Documentation/git-mktree.txt b/Documentation/git-mktree.txt index 5c6ebdfad9..c3616e7711 100644 --- a/Documentation/git-mktree.txt +++ b/Documentation/git-mktree.txt @@ -32,7 +32,7 @@ OPTIONS --batch:: Allow building of more than one tree object before exiting. Each tree is separated by as single blank line. The final new-line is - optional. Note - if the '-z' option is used, lines are terminated + optional. Note - if the `-z` option is used, lines are terminated with NUL. GIT diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.txt index e4531325cd..79449bf98f 100644 --- a/Documentation/git-mv.txt +++ b/Documentation/git-mv.txt @@ -32,10 +32,10 @@ OPTIONS --force:: Force renaming or moving of a file even if the target exists -k:: - Skip move or rename actions which would lead to an error + Skip move or rename actions which would lead to an error condition. An error happens when a source is neither existing nor controlled by Git, or when it would overwrite an existing - file unless '-f' is given. + file unless `-f` is given. -n:: --dry-run:: Do nothing; only show what would happen diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt index 02a10bc3b6..be7db3048d 100644 --- a/Documentation/git-notes.txt +++ b/Documentation/git-notes.txt @@ -152,7 +152,7 @@ OPTIONS -c <object>:: --reedit-message=<object>:: - Like '-C', but with '-c' the editor is invoked, so that + Like '-C', but with `-c` the editor is invoked, so that the user can further edit the note message. --allow-empty:: diff --git a/Documentation/git-p4.txt b/Documentation/git-p4.txt index 9d4f1519e7..c83aaf39c3 100644 --- a/Documentation/git-p4.txt +++ b/Documentation/git-p4.txt @@ -104,7 +104,7 @@ $ git p4 sync //path/in/your/perforce/depot ------------ This imports the specified depot into 'refs/remotes/p4/master' in an existing Git repository. The -'--branch' option can be used to specify a different branch to +`--branch` option can be used to specify a different branch to be used for the p4 content. If a Git repository includes branches 'refs/remotes/origin/p4', these @@ -114,7 +114,7 @@ from a Git remote, this can be useful in a multi-developer environment. If there are multiple branches, doing 'git p4 sync' will automatically use the "BRANCH DETECTION" algorithm to try to partition new changes -into the right branch. This can be overridden with the '--branch' +into the right branch. This can be overridden with the `--branch` option to specify just a single branch to update. @@ -150,10 +150,10 @@ $ git p4 submit topicbranch ------------ The upstream reference is generally 'refs/remotes/p4/master', but can -be overridden using the '--origin=' command-line option. +be overridden using the `--origin=` command-line option. The p4 changes will be created as the user invoking 'git p4 submit'. The -'--preserve-user' option will cause ownership to be modified +`--preserve-user` option will cause ownership to be modified according to the author of the Git commit. This option requires admin privileges in p4, which can be granted using 'p4 protect'. @@ -221,7 +221,7 @@ Git repository: where they will be treated as remote-tracking branches by linkgit:git-branch[1] and other commands. This option instead puts p4 branches in 'refs/heads/p4/'. Note that future - sync operations must specify '--import-local' as well so that + sync operations must specify `--import-local` as well so that they can find the p4 branches in refs/heads. --max-changes <n>:: @@ -245,7 +245,7 @@ Git repository: default, involves removing the entire depot path. With this option, the full p4 depot path is retained in Git. For example, path '//depot/main/foo/bar.c', when imported from - '//depot/main/', becomes 'foo/bar.c'. With '--keep-path', the + '//depot/main/', becomes 'foo/bar.c'. With `--keep-path`, the Git path is instead 'depot/main/foo/bar.c'. --use-client-spec:: @@ -275,7 +275,7 @@ These options can be used to modify 'git p4 submit' behavior. --origin <commit>:: Upstream location from which commits are identified to submit to p4. By default, this is the most recent p4 commit reachable - from 'HEAD'. + from `HEAD`. -M:: Detect renames. See linkgit:git-diff[1]. Renames will be @@ -341,7 +341,7 @@ p4 revision specifier on the end: Import all changes from both named depot paths into a single repository. Only files below these directories are included. There is not a subdirectory in Git for each "proj1" and "proj2". - You must use the '--destination' option when specifying more + You must use the `--destination` option when specifying more than one depot path. The revision specifier must be specified identically on each depot path. If there are files in the depot paths with the same name, the path with the most recently @@ -355,7 +355,7 @@ CLIENT SPEC The p4 client specification is maintained with the 'p4 client' command and contains among other fields, a View that specifies how the depot is mapped into the client repository. The 'clone' and 'sync' commands -can consult the client spec when given the '--use-client-spec' option or +can consult the client spec when given the `--use-client-spec` option or when the useClientSpec variable is true. After 'git p4 clone', the useClientSpec variable is automatically set in the repository configuration file. This allows future 'git p4 submit' commands to @@ -390,7 +390,7 @@ different areas in the tree, and indicate related content. 'git p4' can use these mappings to determine branch relationships. If you have a repository where all the branches of interest exist as -subdirectories of a single depot path, you can use '--detect-branches' +subdirectories of a single depot path, you can use `--detect-branches` when cloning or syncing to have 'git p4' automatically find subdirectories in p4, and to generate these as branches in Git. @@ -507,7 +507,7 @@ git-p4.labelImportRegexp:: git-p4.useClientSpec:: Specify that the p4 client spec should be used to identify p4 depot paths of interest. This is equivalent to specifying the - option '--use-client-spec'. See the "CLIENT SPEC" section above. + option `--use-client-spec`. See the "CLIENT SPEC" section above. This variable is a boolean, not the name of a p4 client. git-p4.pathEncoding:: diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index 19f46b64d3..93c3527f0c 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -275,7 +275,7 @@ origin +master` to force a push to the `master` branch). See the all submodules that changed in the revisions to be pushed will be pushed. If on-demand was not able to push all necessary revisions it will also be aborted and exit with non-zero status. A value of - 'no' or using '--no-recurse-submodules' can be used to override the + 'no' or using `--no-recurse-submodules` can be used to override the push.recurseSubmodules configuration variable when no submodule recursion is required. diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 0387b40e0a..de222c81af 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -208,10 +208,10 @@ rebase.stat:: rebase. False by default. rebase.autoSquash:: - If set to true enable '--autosquash' option by default. + If set to true enable `--autosquash` option by default. rebase.autoStash:: - If set to true enable '--autostash' option by default. + If set to true enable `--autostash` option by default. rebase.missingCommitsCheck:: If set to "warn", print warnings about removed commits in @@ -220,7 +220,7 @@ rebase.missingCommitsCheck:: done. "ignore" by default. rebase.instructionFormat:: - Custom commit list format to use during an '--interactive' rebase. + Custom commit list format to use during an `--interactive` rebase. OPTIONS ------- @@ -428,9 +428,9 @@ without an explicit `--interactive`. "fixup! " or "squash! " after the first, in case you referred to an earlier fixup/squash with `git commit --fixup/--squash`. + -This option is only valid when the '--interactive' option is used. +This option is only valid when the `--interactive` option is used. + -If the '--autosquash' option is enabled by default using the +If the `--autosquash` option is enabled by default using the configuration variable `rebase.autoSquash`, this option can be used to override and disable this setting. diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index 1d7eceaa93..577b969c1b 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -137,9 +137,9 @@ branches, adds to that list. Retrieves the URLs for a remote. Configurations for `insteadOf` and `pushInsteadOf` are expanded here. By default, only the first URL is listed. + -With '--push', push URLs are queried rather than fetch URLs. +With `--push`, push URLs are queried rather than fetch URLs. + -With '--all', all URLs for the remote will be listed. +With `--all`, all URLs for the remote will be listed. 'set-url':: @@ -147,11 +147,11 @@ Changes URLs for the remote. Sets first URL for remote <name> that matches regex <oldurl> (first URL if no <oldurl> is given) to <newurl>. If <oldurl> doesn't match any URL, an error occurs and nothing is changed. + -With '--push', push URLs are manipulated instead of fetch URLs. +With `--push`, push URLs are manipulated instead of fetch URLs. + -With '--add', instead of changing existing URLs, new URL is added. +With `--add`, instead of changing existing URLs, new URL is added. + -With '--delete', instead of changing existing URLs, all URLs matching +With `--delete`, instead of changing existing URLs, all URLs matching regex <url> are deleted for remote <name>. Trying to delete all non-push URLs is an error. + diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index b58b6b5972..c5975234f4 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -33,7 +33,7 @@ OPTIONS pack everything referenced into a single pack. Especially useful when packing a repository that is used for private development. Use - with '-d'. This will clean up the objects that `git prune` + with `-d`. This will clean up the objects that `git prune` leaves behind, but `git fsck --full --dangling` shows as dangling. + @@ -42,7 +42,7 @@ whole new pack in order to get any contained object, no matter how many other objects in that pack they already have locally. -A:: - Same as `-a`, unless '-d' is used. Then any unreachable + Same as `-a`, unless `-d` is used. Then any unreachable objects in a previous pack become loose, unpacked objects, instead of being left in the old pack. Unreachable objects are never intentionally added to a pack, even when repacking. diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index 573616a04a..837707a8fd 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -24,7 +24,7 @@ from the HEAD commit). Note: 'git revert' is used to record some new commits to reverse the effect of some earlier commits (often only a faulty one). If you want to throw away all uncommitted changes in your working directory, you -should see linkgit:git-reset[1], particularly the '--hard' option. If +should see linkgit:git-reset[1], particularly the `--hard` option. If you want to extract specific files as they were in another commit, you should see linkgit:git-checkout[1], specifically the `git checkout <commit> -- <filename>` syntax. Take care with these alternatives as @@ -37,7 +37,7 @@ OPTIONS For a more complete list of ways to spell commit names, see linkgit:gitrevisions[7]. Sets of commits can also be given but no traversal is done by - default, see linkgit:git-rev-list[1] and its '--no-walk' + default, see linkgit:git-rev-list[1] and its `--no-walk` option. -e:: diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index d0b38b4b10..642d0ef199 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -66,7 +66,7 @@ This option may be specified multiple times. Invoke a text editor (see GIT_EDITOR in linkgit:git-var[1]) to edit an introductory message for the patch series. + -When '--compose' is used, git send-email will use the From, Subject, and +When `--compose` is used, git send-email will use the From, Subject, and In-Reply-To headers specified in the message. If the body of the message (what you type after the headers and a blank line) only contains blank (or Git: prefixed) lines, the summary won't be sent, but From, Subject, @@ -182,19 +182,19 @@ $ git send-email --smtp-auth="PLAIN LOGIN GSSAPI" ... + If at least one of the specified mechanisms matches the ones advertised by the SMTP server and if it is supported by the utilized SASL library, the mechanism -is used for authentication. If neither 'sendemail.smtpAuth' nor '--smtp-auth' +is used for authentication. If neither 'sendemail.smtpAuth' nor `--smtp-auth` is specified, all mechanisms supported by the SASL library can be used. --smtp-pass[=<password>]:: Password for SMTP-AUTH. The argument is optional: If no argument is specified, then the empty string is used as the password. Default is the value of `sendemail.smtpPass`, - however '--smtp-pass' always overrides this value. + however `--smtp-pass` always overrides this value. + Furthermore, passwords need not be specified in configuration files or on the command line. If a username has been specified (with -'--smtp-user' or a `sendemail.smtpUser`), but no password has been -specified (with '--smtp-pass' or `sendemail.smtpPass`), then +`--smtp-user` or a `sendemail.smtpUser`), but no password has been +specified (with `--smtp-pass` or `sendemail.smtpPass`), then a password is obtained using 'git-credential'. --smtp-server=<host>:: @@ -240,7 +240,7 @@ must be used for each option. --smtp-user=<user>:: Username for SMTP-AUTH. Default is the value of `sendemail.smtpUser`; - if a username is not specified (with '--smtp-user' or `sendemail.smtpUser`), + if a username is not specified (with `--smtp-user` or `sendemail.smtpUser`), then authentication is not attempted. --smtp-debug=0|1:: @@ -364,8 +364,8 @@ have been specified, in which case default to 'compose'. --[no-]format-patch:: When an argument may be understood either as a reference or as a file name, - choose to understand it as a format-patch argument ('--format-patch') - or as a file name ('--no-format-patch'). By default, when such a conflict + choose to understand it as a format-patch argument (`--format-patch`) + or as a file name (`--no-format-patch`). By default, when such a conflict occurs, git send-email will fail. --quiet:: @@ -382,7 +382,7 @@ have been specified, in which case default to 'compose'. -- + Default is the value of `sendemail.validate`; if this is not set, -default to '--validate'. +default to `--validate`. --force:: Send emails even if safety checks would prevent it. @@ -428,13 +428,13 @@ sendmail;; sendemail.multiEdit:: If true (default), a single editor instance will be spawned to edit - files you have to edit (patches when '--annotate' is used, and the - summary when '--compose' is used). If false, files will be edited one + files you have to edit (patches when `--annotate` is used, and the + summary when `--compose` is used). If false, files will be edited one after the other, spawning a new editor each time. sendemail.confirm:: Sets the default for whether to confirm before sending. Must be - one of 'always', 'never', 'cc', 'compose', or 'auto'. See '--confirm' + one of 'always', 'never', 'cc', 'compose', or 'auto'. See `--confirm` in the previous section for the meaning of these values. EXAMPLE diff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt index 6aa91e830c..a831dd0288 100644 --- a/Documentation/git-send-pack.txt +++ b/Documentation/git-send-pack.txt @@ -44,7 +44,7 @@ OPTIONS option, then the refs from stdin are processed after those on the command line. + -If '--stateless-rpc' is specified together with this option then +If `--stateless-rpc` is specified together with this option then the list of refs must be in packet format (pkt-line). Each ref must be in a separate packet, and the list must end with a flush packet. @@ -99,11 +99,11 @@ Specifying the Refs There are three ways to specify which refs to update on the remote end. -With '--all' flag, all refs that exist locally are transferred to +With `--all` flag, all refs that exist locally are transferred to the remote side. You cannot specify any '<ref>' if you use this flag. -Without '--all' and without any '<ref>', the heads that exist +Without `--all` and without any '<ref>', the heads that exist both on the local side and on the remote side are updated. When one or more '<ref>' are specified explicitly (whether on the @@ -134,13 +134,13 @@ name. See linkgit:git-rev-parse[1]. exist in the set of remote refs; the ref matched <src> locally is used as the name of the destination. -Without '--force', the <src> ref is stored at the remote only if +Without `--force`, the <src> ref is stored at the remote only if <dst> does not exist, or <dst> is a proper subset (i.e. an ancestor) of <src>. This check, known as "fast-forward check", is performed in order to avoid accidentally overwriting the remote ref and lose other peoples' commits from there. -With '--force', the fast-forward check is disabled for all refs. +With `--force`, the fast-forward check is disabled for all refs. Optionally, a <ref> parameter can be prefixed with a plus '+' sign to disable the fast-forward check only on that ref. diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt index e4bdd2235c..2e30a3e42d 100644 --- a/Documentation/git-shell.txt +++ b/Documentation/git-shell.txt @@ -24,7 +24,7 @@ named `git-shell-commands` in the user's home directory. COMMANDS -------- -'git shell' accepts the following commands after the '-c' option: +'git shell' accepts the following commands after the `-c` option: 'git receive-pack <argument>':: 'git upload-pack <argument>':: @@ -43,7 +43,7 @@ directory. INTERACTIVE USE --------------- -By default, the commands above can be executed only with the '-c' +By default, the commands above can be executed only with the `-c` option; the shell is not interactive. If a `~/git-shell-commands` directory is present, 'git shell' diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt index b91d4e545b..7818e0f098 100644 --- a/Documentation/git-show-branch.txt +++ b/Documentation/git-show-branch.txt @@ -60,7 +60,7 @@ OPTIONS are shown before their parents). --date-order:: - This option is similar to '--topo-order' in the sense that no + This option is similar to `--topo-order` in the sense that no parent comes before all of its children, but otherwise commits are ordered according to their commit date. diff --git a/Documentation/git-show-ref.txt b/Documentation/git-show-ref.txt index 3a32451984..c0aa871c9e 100644 --- a/Documentation/git-show-ref.txt +++ b/Documentation/git-show-ref.txt @@ -60,7 +60,7 @@ OPTIONS Enable stricter reference checking by requiring an exact ref path. Aside from returning an error code of 1, it will also print an error - message if '--quiet' was not specified. + message if `--quiet` was not specified. --abbrev[=<n>]:: @@ -70,7 +70,7 @@ OPTIONS -q:: --quiet:: - Do not print any results to stdout. When combined with '--verify' this + Do not print any results to stdout. When combined with `--verify` this can be used to silently check if a reference exists. --exclude-existing[=<pattern>]:: @@ -134,7 +134,7 @@ use: This will show "refs/heads/master" but also "refs/remote/other-repo/master", if such references exists. -When using the '--verify' flag, the command requires an exact path: +When using the `--verify` flag, the command requires an exact path: ----------------------------------------------------------------------------- git show-ref --verify refs/heads/master diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 698a6685f6..7e17cade7f 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -98,11 +98,11 @@ your Perl's Getopt::Long is < v2.37). --ignore-paths=<regex>;; When passed to 'init' or 'clone' this regular expression will be preserved as a config key. See 'fetch' for a description - of '--ignore-paths'. + of `--ignore-paths`. --include-paths=<regex>;; When passed to 'init' or 'clone' this regular expression will be preserved as a config key. See 'fetch' for a description - of '--include-paths'. + of `--include-paths`. --no-minimize-url;; When tracking multiple directories (using --stdlayout, --branches, or --tags options), git svn will attempt to connect @@ -110,7 +110,7 @@ your Perl's Getopt::Long is < v2.37). repository. This default allows better tracking of history if entire projects are moved within a repository, but may cause issues on repositories where read access restrictions are in - place. Passing '--no-minimize-url' will allow git svn to + place. Passing `--no-minimize-url` will allow git svn to accept URLs as-is without attempting to connect to a higher level directory. This option is off by default when only one URL/branch is tracked (it would do little good). @@ -141,7 +141,7 @@ the same local time zone. --ignore-paths=<regex>;; This allows one to specify a Perl regular expression that will cause skipping of all matching paths from checkout from SVN. - The '--ignore-paths' option should match for every 'fetch' + The `--ignore-paths` option should match for every 'fetch' (including automatic fetches due to 'clone', 'dcommit', 'rebase', etc) on a given repository. + @@ -170,10 +170,10 @@ Skip "branches" and "tags" of first level directories;; --include-paths=<regex>;; This allows one to specify a Perl regular expression that will cause the inclusion of only matching paths from checkout from SVN. - The '--include-paths' option should match for every 'fetch' + The `--include-paths` option should match for every 'fetch' (including automatic fetches due to 'clone', 'dcommit', - 'rebase', etc) on a given repository. '--ignore-paths' takes - precedence over '--include-paths'. + 'rebase', etc) on a given repository. `--ignore-paths` takes + precedence over `--include-paths`. + [verse] config key: svn-remote.<name>.include-paths @@ -191,7 +191,7 @@ config key: svn-remote.<name>.include-paths or if a second argument is passed; it will create a directory and work within that. It accepts all arguments that the 'init' and 'fetch' commands accept; with the exception of - '--fetch-all' and '--parent'. After a repository is cloned, + `--fetch-all` and `--parent`. After a repository is cloned, the 'fetch' command will be able to update revisions without affecting the working tree; and the 'rebase' command will be able to update the working tree with the latest changes. @@ -216,7 +216,7 @@ it preserves linear history with 'git rebase' instead of 'git merge' for ease of dcommitting with 'git svn'. + This accepts all options that 'git svn fetch' and 'git rebase' -accept. However, '--fetch-all' only fetches from the current +accept. However, `--fetch-all` only fetches from the current [svn-remote], and not all [svn-remote] definitions. + Like 'git rebase'; this requires that the working tree be clean @@ -919,7 +919,7 @@ parent of the branch. However, it is possible that there is no suitable Git commit to serve as parent. This will happen, among other reasons, if the SVN branch is a copy of a revision that was not fetched by 'git svn' (e.g. because it is an old revision that was skipped with -'--revision'), or if in SVN a directory was copied that is not tracked +`--revision`), or if in SVN a directory was copied that is not tracked by 'git svn' (such as a branch that is not tracked at all, or a subdirectory of a tracked branch). In these cases, 'git svn' will still create a Git branch, but instead of using an existing Git commit as the @@ -996,12 +996,12 @@ directories in the working copy. While this is the easiest way to get a copy of a complete repository, for projects with many branches it will lead to a working copy many times larger than just the trunk. Thus for projects using the standard directory structure (trunk/branches/tags), -it is recommended to clone with option '--stdlayout'. If the project +it is recommended to clone with option `--stdlayout`. If the project uses a non-standard structure, and/or if branches and tags are not required, it is easiest to only clone one directory (typically trunk), without giving any repository layout options. If the full history with -branches and tags is required, the options '--trunk' / '--branches' / -'--tags' must be used. +branches and tags is required, the options `--trunk` / `--branches` / +`--tags` must be used. When using multiple --branches or --tags, 'git svn' does not automatically handle name collisions (for example, if two branches from different paths have diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index 6b89393746..7ecca8e247 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -167,7 +167,7 @@ This option is only applicable when listing tags without annotation lines. --[no-]merged [<commit>]:: Only list tags whose tips are reachable, or not reachable - if '--no-merged' is used, from the specified commit ('HEAD' + if `--no-merged` is used, from the specified commit (`HEAD` if not specified). CONFIGURATION diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index c6cbed189c..7386c93162 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -102,7 +102,7 @@ thus, in case the assumed-untracked file is changed upstream, you will need to handle the situation manually. --really-refresh:: - Like '--refresh', but checks stat information unconditionally, + Like `--refresh`, but checks stat information unconditionally, without regard to the "assume unchanged" setting. --[no-]skip-worktree:: @@ -211,7 +211,7 @@ will remove the intended effect of the option. Using --refresh --------------- -'--refresh' does not calculate a new sha1 file or bring the index +`--refresh` does not calculate a new sha1 file or bring the index up-to-date for mode/content changes. But what it *does* do is to "re-match" the stat information of a file with the index, so that you can refresh the index for a file that hasn't been changed but where @@ -222,7 +222,7 @@ up the stat index details with the proper files. Using --cacheinfo or --info-only -------------------------------- -'--cacheinfo' is used to register a file that is not in the +`--cacheinfo` is used to register a file that is not in the current working directory. This is useful for minimum-checkout merging. @@ -232,12 +232,12 @@ To pretend you have a file with mode and sha1 at path, say: $ git update-index --cacheinfo <mode>,<sha1>,<path> ---------------- -'--info-only' is used to register files without placing them in the object +`--info-only` is used to register files without placing them in the object database. This is useful for status-only repositories. -Both '--cacheinfo' and '--info-only' behave similarly: the index is updated -but the object database isn't. '--cacheinfo' is useful when the object is -in the database but the file isn't available locally. '--info-only' is +Both `--cacheinfo` and `--info-only` behave similarly: the index is updated +but the object database isn't. `--cacheinfo` is useful when the object is +in the database but the file isn't available locally. `--info-only` is useful when the file is available, but you do not wish to update the object database. diff --git a/Documentation/git-web--browse.txt b/Documentation/git-web--browse.txt index 7daa28fd94..2d6b09a43c 100644 --- a/Documentation/git-web--browse.txt +++ b/Documentation/git-web--browse.txt @@ -110,7 +110,7 @@ Note about git-config --global ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Note that these configuration variables should probably be set using -the '--global' flag, for example like this: +the `--global` flag, for example like this: ------------------------------------------------ $ git config --global web.browser firefox diff --git a/Documentation/git.txt b/Documentation/git.txt index ca611c9f86..f4dfc9d42c 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -31,8 +31,8 @@ page to learn what commands Git offers. You can learn more about individual Git commands with "git help command". linkgit:gitcli[7] manual page gives you an overview of the command-line command syntax. -Formatted and hyperlinked version of the latest Git documentation -can be viewed at `http://git-htmldocs.googlecode.com/git/git.html`. +A formatted and hyperlinked copy of the latest Git documentation +can be viewed at `https://git.github.io/htmldocs/git.html`. ifdef::stalenotes[] [NOTE] @@ -43,9 +43,11 @@ unreleased) version of Git, that is available from the 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v2.9.0/git.html[documentation for release 2.9] +* link:v2.9.2/git.html[documentation for release 2.9.2] * release notes for + link:RelNotes/2.9.2.txt[2.9.2], + link:RelNotes/2.9.1.txt[2.9.1], link:RelNotes/2.9.0.txt[2.9]. * link:v2.8.4/git.html[documentation for release 2.8.4] @@ -513,7 +515,7 @@ OPTIONS --help:: Prints the synopsis and a list of the most commonly used - commands. If the option '--all' or '-a' is given then all + commands. If the option `--all` or `-a` is given then all available commands are printed. If a Git command is named this option will bring up the manual page for that command. + @@ -855,16 +857,16 @@ Git so take care if using a foreign front-end. If the `GIT_DIR` environment variable is set then it specifies a path to use instead of the default `.git` for the base of the repository. - The '--git-dir' command-line option also sets this value. + The `--git-dir` command-line option also sets this value. `GIT_WORK_TREE`:: Set the path to the root of the working tree. - This can also be controlled by the '--work-tree' command-line + This can also be controlled by the `--work-tree` command-line option and the core.worktree configuration variable. `GIT_NAMESPACE`:: Set the Git namespace; see linkgit:gitnamespaces[7] for details. - The '--namespace' command-line option also sets this value. + The `--namespace` command-line option also sets this value. `GIT_CEILING_DIRECTORIES`:: This should be a colon-separated list of absolute paths. If @@ -979,7 +981,7 @@ other The command will be given exactly two or four arguments: the 'username@host' (or just 'host') from the URL and the shell command to execute on that remote system, optionally preceded by - '-p' (literally) and the 'port' from the URL when it specifies + `-p` (literally) and the 'port' from the URL when it specifies something other than the default SSH port. + `$GIT_SSH_COMMAND` takes precedence over `$GIT_SSH`, and is interpreted diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt index 15b3bfa8db..4546fa0d75 100644 --- a/Documentation/gitcore-tutorial.txt +++ b/Documentation/gitcore-tutorial.txt @@ -949,7 +949,7 @@ for details. [NOTE] If there were more commits on the 'master' branch after the merge, the merge commit itself would not be shown by 'git show-branch' by -default. You would need to provide '--sparse' option to make the +default. You would need to provide `--sparse` option to make the merge commit visible in this case. Now, let's pretend you are the one who did all the work in diff --git a/Documentation/gitdiffcore.txt b/Documentation/gitdiffcore.txt index c579593e55..08cf62278e 100644 --- a/Documentation/gitdiffcore.txt +++ b/Documentation/gitdiffcore.txt @@ -28,8 +28,8 @@ The 'git diff-{asterisk}' family works by first comparing two sets of files: - 'git diff-index' compares contents of a "tree" object and the - working directory (when '--cached' flag is not used) or a - "tree" object and the index file (when '--cached' flag is + working directory (when `--cached` flag is not used) or a + "tree" object and the index file (when `--cached` flag is used); - 'git diff-files' compares contents of the index file and the diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt index 6ade002176..a68d860fa3 100644 --- a/Documentation/gitk.txt +++ b/Documentation/gitk.txt @@ -82,7 +82,7 @@ linkgit:git-rev-list[1] for a complete list. --simplify-merges:: - Additional option to '--full-history' to remove some needless + Additional option to `--full-history` to remove some needless merges from the resulting history, as there are no selected commits contributing to this merge. (See "History simplification" in linkgit:git-log[1] for a more detailed diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt index ac70eca321..07cdd73ab2 100644 --- a/Documentation/gitmodules.txt +++ b/Documentation/gitmodules.txt @@ -19,7 +19,7 @@ of linkgit:git-config[1]. The file contains one subsection per submodule, and the subsection value is the name of the submodule. The name is set to the path where the -submodule has been added unless it was customized with the '--name' +submodule has been added unless it was customized with the `--name` option of 'git submodule add'. Each submodule section also contains the following required keys: diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt index 1e8659492f..a4de50ad22 100644 --- a/Documentation/gitremote-helpers.txt +++ b/Documentation/gitremote-helpers.txt @@ -210,17 +210,17 @@ the remote repository. 'export-marks' <file>:: This modifies the 'export' capability, instructing Git to dump the internal marks table to <file> when complete. For details, - read up on '--export-marks=<file>' in linkgit:git-fast-export[1]. + read up on `--export-marks=<file>` in linkgit:git-fast-export[1]. 'import-marks' <file>:: This modifies the 'export' capability, instructing Git to load the marks specified in <file> before processing any input. For details, - read up on '--import-marks=<file>' in linkgit:git-fast-export[1]. + read up on `--import-marks=<file>` in linkgit:git-fast-export[1]. 'signed-tags':: This modifies the 'export' capability, instructing Git to pass - '--signed-tags=verbatim' to linkgit:git-fast-export[1]. In the - absence of this capability, Git will use '--signed-tags=warn-strip'. + `--signed-tags=verbatim` to linkgit:git-fast-export[1]. In the + absence of this capability, Git will use `--signed-tags=warn-strip`. @@ -298,7 +298,7 @@ Supported if the helper has the "fetch" capability. is followed by a blank line). For example, the following would be two batches of 'push', the first asking the remote-helper to push the local ref 'master' to the remote ref 'master' and - the local 'HEAD' to the remote 'branch', and the second + the local `HEAD` to the remote 'branch', and the second asking to push ref 'foo' to ref 'bar' (forced update requested by the '+'). + diff --git a/Documentation/howto/new-command.txt b/Documentation/howto/new-command.txt index 6d772bd927..15a4c8031f 100644 --- a/Documentation/howto/new-command.txt +++ b/Documentation/howto/new-command.txt @@ -94,7 +94,7 @@ your language, document it in the INSTALL file. 6. There is a file command-list.txt in the distribution main directory that categorizes commands by type, so they can be listed in appropriate subsections in the documentation's summary command list. Add an entry -for yours. To understand the categories, look at git-commands.txt +for yours. To understand the categories, look at command-list.txt in the main directory. If the new command is part of the typical Git workflow and you believe it common enough to be mentioned in 'git help', map this command to a common group in the column [common]. diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 4f009d4424..c5bd21812d 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -193,7 +193,7 @@ endif::git-rev-list[] --stdin:: In addition to the '<commit>' listed on the command - line, read them from the standard input. If a '--' separator is + line, read them from the standard input. If a `--` separator is seen, stop reading commits and start reading paths to limit the result. diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt index 19314e3b7f..abae363983 100644 --- a/Documentation/revisions.txt +++ b/Documentation/revisions.txt @@ -28,8 +28,8 @@ blobs contained in a commit. first match in the following rules: . If '$GIT_DIR/<refname>' exists, that is what you mean (this is usually - useful only for 'HEAD', 'FETCH_HEAD', 'ORIG_HEAD', 'MERGE_HEAD' - and 'CHERRY_PICK_HEAD'); + useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD`, `MERGE_HEAD` + and `CHERRY_PICK_HEAD`); . otherwise, 'refs/<refname>' if it exists; @@ -41,16 +41,16 @@ blobs contained in a commit. . otherwise, 'refs/remotes/<refname>/HEAD' if it exists. + -'HEAD' names the commit on which you based the changes in the working tree. -'FETCH_HEAD' records the branch which you fetched from a remote repository +`HEAD` names the commit on which you based the changes in the working tree. +`FETCH_HEAD` records the branch which you fetched from a remote repository with your last `git fetch` invocation. -'ORIG_HEAD' is created by commands that move your 'HEAD' in a drastic -way, to record the position of the 'HEAD' before their operation, so that +`ORIG_HEAD` is created by commands that move your `HEAD` in a drastic +way, to record the position of the `HEAD` before their operation, so that you can easily change the tip of the branch back to the state before you ran them. -'MERGE_HEAD' records the commit(s) which you are merging into your branch +`MERGE_HEAD` records the commit(s) which you are merging into your branch when you run `git merge`. -'CHERRY_PICK_HEAD' records the commit which you are cherry-picking +`CHERRY_PICK_HEAD` records the commit which you are cherry-picking when you run `git cherry-pick`. + Note that any of the 'refs/*' cases above may come either from @@ -59,7 +59,7 @@ While the ref name encoding is unspecified, UTF-8 is preferred as some output processing may assume ref names in UTF-8. '@':: - '@' alone is a shortcut for 'HEAD'. + '@' alone is a shortcut for `HEAD`. '<refname>@{<date>}', e.g. 'master@\{yesterday\}', 'HEAD@{5 minutes ago}':: A ref followed by the suffix '@' with a date specification @@ -71,7 +71,7 @@ some output processing may assume ref names in UTF-8. existing log ('$GIT_DIR/logs/<ref>'). Note that this looks up the state of your *local* ref at a given time; e.g., what was in your local 'master' branch last week. If you want to look at commits made during - certain times, see '--since' and '--until'. + certain times, see `--since` and `--until`. '<refname>@{<n>}', e.g. 'master@\{1\}':: A ref followed by the suffix '@' with an ordinal specification @@ -101,7 +101,7 @@ some output processing may assume ref names in UTF-8. '<branchname>@\{push\}', e.g. 'master@\{push\}', '@\{push\}':: The suffix '@\{push}' reports the branch "where we would push to" if `git push` were run while `branchname` was checked out (or the current - 'HEAD' if no branchname is specified). Since our push destination is + `HEAD` if no branchname is specified). Since our push destination is in a remote repository, of course, we report the local tracking branch that corresponds to that branch (i.e., something in 'refs/remotes/'). + @@ -283,12 +283,12 @@ To summarize: '<rev1>..<rev2>':: Include commits that are reachable from <rev2> but exclude those that are reachable from <rev1>. When either <rev1> or - <rev2> is omitted, it defaults to 'HEAD'. + <rev2> is omitted, it defaults to `HEAD`. '<rev1>\...<rev2>':: Include commits that are reachable from either <rev1> or <rev2> but exclude those that are reachable from both. When - either <rev1> or <rev2> is omitted, it defaults to 'HEAD'. + either <rev1> or <rev2> is omitted, it defaults to `HEAD`. '<rev>{caret}@', e.g. 'HEAD{caret}@':: A suffix '{caret}' followed by an at sign is the same as listing @@ -939,7 +939,7 @@ BUILTIN_OBJS += builtin/verify-tag.o BUILTIN_OBJS += builtin/worktree.o BUILTIN_OBJS += builtin/write-tree.o -GITLIBS = $(LIB_FILE) $(XDIFF_LIB) +GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) EXTLIBS = GIT_USER_AGENT = git/$(GIT_VERSION) @@ -1572,7 +1572,15 @@ TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH)) DIFF_SQ = $(subst ','\'',$(DIFF)) PERLLIB_EXTRA_SQ = $(subst ','\'',$(PERLLIB_EXTRA)) -LIBS = $(GITLIBS) $(EXTLIBS) +# We must filter out any object files from $(GITLIBS), +# as it is typically used like: +# +# foo: foo.o $(GITLIBS) +# $(CC) $(filter %.o,$^) $(LIBS) +# +# where we use it as a dependency. Since we also pull object files +# from the dependency list, that would make each entry appear twice. +LIBS = $(filter-out %.o, $(GITLIBS)) $(EXTLIBS) BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \ $(COMPAT_CFLAGS) @@ -1708,8 +1716,8 @@ git.sp git.s git.o: EXTRA_CPPFLAGS = \ '-DGIT_INFO_PATH="$(infodir_relative_SQ)"' git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS) - $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) git.o \ - $(BUILTIN_OBJS) $(LIBS) + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \ + $(filter %.o,$^) $(LIBS) help.sp help.s help.o: common-cmds.h @@ -1902,6 +1910,7 @@ TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) OBJECTS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \ $(XDIFF_OBJS) \ $(VCSSVN_OBJS) \ + common-main.o \ git.o ifndef NO_CURL OBJECTS += http.o http-walker.o remote-curl.o @@ -2063,7 +2072,10 @@ XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \ --keyword=gettextln --keyword=eval_gettextln XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H) -LOCALIZED_SH = $(SCRIPT_SH) git-parse-remote.sh +LOCALIZED_SH = $(SCRIPT_SH) +LOCALIZED_SH += git-parse-remote.sh +LOCALIZED_SH += git-rebase--interactive.sh +LOCALIZED_SH += git-sh-setup.sh LOCALIZED_PERL = $(SCRIPT_PERL) ifdef XGETTEXT_INCLUDE_TESTS @@ -79,7 +79,20 @@ int git_default_advice_config(const char *var, const char *value) int error_resolve_conflict(const char *me) { - error("%s is not possible because you have unmerged files.", me); + if (!strcmp(me, "cherry-pick")) + error(_("Cherry-picking is not possible because you have unmerged files.")); + else if (!strcmp(me, "commit")) + error(_("Committing is not possible because you have unmerged files.")); + else if (!strcmp(me, "merge")) + error(_("Merging is not possible because you have unmerged files.")); + else if (!strcmp(me, "pull")) + error(_("Pulling is not possible because you have unmerged files.")); + else if (!strcmp(me, "revert")) + error(_("Reverting is not possible because you have unmerged files.")); + else + error(_("It is not possible to %s because you have unmerged files."), + me); + if (advice_resolve_conflict) /* * Message used both when 'git commit' fails and when @@ -93,7 +106,7 @@ int error_resolve_conflict(const char *me) void NORETURN die_resolve_conflict(const char *me) { error_resolve_conflict(me); - die("Exiting because of an unresolved conflict."); + die(_("Exiting because of an unresolved conflict.")); } void NORETURN die_conclude_merge(void) @@ -106,14 +119,14 @@ void NORETURN die_conclude_merge(void) void detach_advice(const char *new_name) { - const char fmt[] = - "Note: checking out '%s'.\n\n" + const char *fmt = + _("Note: checking out '%s'.\n\n" "You are in 'detached HEAD' state. You can look around, make experimental\n" "changes and commit them, and you can discard any commits you make in this\n" "state without impacting any branches by performing another checkout.\n\n" "If you want to create a new branch to retain commits you create, you may\n" "do so (now or later) by using -b with the checkout command again. Example:\n\n" - " git checkout -b <new-branch-name>\n\n"; + " git checkout -b <new-branch-name>\n\n"); fprintf(stderr, fmt, new_name); } diff --git a/archive-tar.c b/archive-tar.c index cb99df2814..55682404d5 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -18,6 +18,21 @@ static int tar_umask = 002; static int write_tar_filter_archive(const struct archiver *ar, struct archiver_args *args); +/* + * This is the max value that a ustar size header can specify, as it is fixed + * at 11 octal digits. POSIX specifies that we switch to extended headers at + * this size. + * + * Likewise for the mtime (which happens to use a buffer of the same size). + */ +#if ULONG_MAX == 0xFFFFFFFF +#define USTAR_MAX_SIZE ULONG_MAX +#define USTAR_MAX_MTIME ULONG_MAX +#else +#define USTAR_MAX_SIZE 077777777777UL +#define USTAR_MAX_MTIME 077777777777UL +#endif + /* writes out the whole block, but only if it is full */ static void write_if_needed(void) { @@ -137,6 +152,20 @@ static void strbuf_append_ext_header(struct strbuf *sb, const char *keyword, strbuf_addch(sb, '\n'); } +/* + * Like strbuf_append_ext_header, but for numeric values. + */ +static void strbuf_append_ext_header_uint(struct strbuf *sb, + const char *keyword, + uintmax_t value) +{ + char buf[40]; /* big enough for 2^128 in decimal, plus NUL */ + int len; + + len = xsnprintf(buf, sizeof(buf), "%"PRIuMAX, value); + strbuf_append_ext_header(sb, keyword, buf, len); +} + static unsigned int ustar_header_chksum(const struct ustar_header *header) { const unsigned char *p = (const unsigned char *)header; @@ -208,7 +237,7 @@ static int write_tar_entry(struct archiver_args *args, struct ustar_header header; struct strbuf ext_header = STRBUF_INIT; unsigned int old_mode = mode; - unsigned long size; + unsigned long size, size_in_header; void *buffer; int err = 0; @@ -267,7 +296,13 @@ static int write_tar_entry(struct archiver_args *args, memcpy(header.linkname, buffer, size); } - prepare_header(args, &header, mode, size); + size_in_header = size; + if (S_ISREG(mode) && size > USTAR_MAX_SIZE) { + size_in_header = 0; + strbuf_append_ext_header_uint(&ext_header, "size", size); + } + + prepare_header(args, &header, mode, size_in_header); if (ext_header.len > 0) { err = write_extended_header(args, sha1, ext_header.buf, @@ -289,15 +324,25 @@ static int write_tar_entry(struct archiver_args *args, return err; } -static int write_global_extended_header(struct archiver_args *args) +static void write_global_extended_header(struct archiver_args *args) { const unsigned char *sha1 = args->commit_sha1; struct strbuf ext_header = STRBUF_INIT; struct ustar_header header; unsigned int mode; - int err = 0; - strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40); + if (sha1) + strbuf_append_ext_header(&ext_header, "comment", + sha1_to_hex(sha1), 40); + if (args->time > USTAR_MAX_MTIME) { + strbuf_append_ext_header_uint(&ext_header, "mtime", + args->time); + args->time = USTAR_MAX_MTIME; + } + + if (!ext_header.len) + return; + memset(&header, 0, sizeof(header)); *header.typeflag = TYPEFLAG_GLOBAL_HEADER; mode = 0100666; @@ -306,7 +351,6 @@ static int write_global_extended_header(struct archiver_args *args) write_blocked(&header, sizeof(header)); write_blocked(ext_header.buf, ext_header.len); strbuf_release(&ext_header); - return err; } static struct archiver **tar_filters; @@ -382,10 +426,8 @@ static int write_tar_archive(const struct archiver *ar, { int err = 0; - if (args->commit_sha1) - err = write_global_extended_header(args); - if (!err) - err = write_archive_entries(args, write_tar_entry); + write_global_extended_header(args); + err = write_archive_entries(args, write_tar_entry); if (!err) write_trailer(); return err; @@ -438,12 +438,12 @@ static void read_bisect_paths(struct argv_array *array) FILE *fp = fopen(filename, "r"); if (!fp) - die_errno("Could not open file '%s'", filename); + die_errno(_("Could not open file '%s'"), filename); while (strbuf_getline_lf(&str, fp) != EOF) { strbuf_trim(&str); if (sq_dequote_to_argv_array(str.buf, array)) - die("Badly quoted content in file '%s': %s", + die(_("Badly quoted content in file '%s': %s"), filename, str.buf); } @@ -652,7 +652,7 @@ static void exit_if_skipped_commits(struct commit_list *tried, if (bad) printf("%s\n", oid_to_hex(bad)); - printf("We cannot bisect more!\n"); + printf(_("We cannot bisect more!\n")); exit(2); } @@ -705,7 +705,7 @@ static struct commit *get_commit_reference(const unsigned char *sha1) { struct commit *r = lookup_commit_reference(sha1); if (!r) - die("Not a valid commit name %s", sha1_to_hex(sha1)); + die(_("Not a valid commit name %s"), sha1_to_hex(sha1)); return r; } @@ -729,27 +729,27 @@ static void handle_bad_merge_base(void) char *bad_hex = oid_to_hex(current_bad_oid); char *good_hex = join_sha1_array_hex(&good_revs, ' '); if (!strcmp(term_bad, "bad") && !strcmp(term_good, "good")) { - fprintf(stderr, "The merge base %s is bad.\n" + fprintf(stderr, _("The merge base %s is bad.\n" "This means the bug has been fixed " - "between %s and [%s].\n", + "between %s and [%s].\n"), bad_hex, bad_hex, good_hex); } else if (!strcmp(term_bad, "new") && !strcmp(term_good, "old")) { - fprintf(stderr, "The merge base %s is new.\n" + fprintf(stderr, _("The merge base %s is new.\n" "The property has changed " - "between %s and [%s].\n", + "between %s and [%s].\n"), bad_hex, bad_hex, good_hex); } else { - fprintf(stderr, "The merge base %s is %s.\n" + fprintf(stderr, _("The merge base %s is %s.\n" "This means the first '%s' commit is " - "between %s and [%s].\n", + "between %s and [%s].\n"), bad_hex, term_bad, term_good, bad_hex, good_hex); } exit(3); } - fprintf(stderr, "Some %s revs are not ancestor of the %s rev.\n" + fprintf(stderr, _("Some %s revs are not ancestor of the %s rev.\n" "git bisect cannot work properly in this case.\n" - "Maybe you mistook %s and %s revs?\n", + "Maybe you mistook %s and %s revs?\n"), term_good, term_bad, term_good, term_bad); exit(1); } @@ -757,14 +757,14 @@ static void handle_bad_merge_base(void) static void handle_skipped_merge_base(const unsigned char *mb) { char *mb_hex = sha1_to_hex(mb); - char *bad_hex = sha1_to_hex(current_bad_oid->hash); + char *bad_hex = oid_to_hex(current_bad_oid); char *good_hex = join_sha1_array_hex(&good_revs, ' '); - warning("the merge base between %s and [%s] " + warning(_("the merge base between %s and [%s] " "must be skipped.\n" "So we cannot be sure the first %s commit is " "between %s and %s.\n" - "We continue anyway.", + "We continue anyway."), bad_hex, good_hex, term_bad, mb_hex, bad_hex); free(good_hex); } @@ -795,7 +795,7 @@ static void check_merge_bases(int no_checkout) } else if (0 <= sha1_array_lookup(&skipped_revs, mb)) { handle_skipped_merge_base(mb); } else { - printf("Bisecting: a merge base must be tested\n"); + printf(_("Bisecting: a merge base must be tested\n")); exit(bisect_checkout(mb, no_checkout)); } } @@ -846,7 +846,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout) int fd; if (!current_bad_oid) - die("a %s revision is needed", term_bad); + die(_("a %s revision is needed"), term_bad); /* Check if file BISECT_ANCESTORS_OK exists. */ if (!stat(filename, &st) && S_ISREG(st.st_mode)) @@ -863,7 +863,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout) /* Create file BISECT_ANCESTORS_OK. */ fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (fd < 0) - warning_errno("could not create file '%s'", + warning_errno(_("could not create file '%s'"), filename); else close(fd); @@ -914,7 +914,7 @@ void read_bisect_terms(const char **read_bad, const char **read_good) *read_good = "good"; return; } else { - die_errno("could not read file '%s'", filename); + die_errno(_("could not read file '%s'"), filename); } } else { strbuf_getline_lf(&str, fp); @@ -940,10 +940,11 @@ int bisect_next_all(const char *prefix, int no_checkout) struct commit_list *tried; int reaches = 0, all = 0, nr, steps; const unsigned char *bisect_rev; + char steps_msg[32]; read_bisect_terms(&term_bad, &term_good); if (read_bisect_refs()) - die("reading bisect refs failed"); + die(_("reading bisect refs failed")); check_good_are_ancestors_of_bad(prefix, no_checkout); @@ -963,7 +964,7 @@ int bisect_next_all(const char *prefix, int no_checkout) */ exit_if_skipped_commits(tried, NULL); - printf("%s was both %s and %s\n", + printf(_("%s was both %s and %s\n"), oid_to_hex(current_bad_oid), term_good, term_bad); @@ -971,8 +972,8 @@ int bisect_next_all(const char *prefix, int no_checkout) } if (!all) { - fprintf(stderr, "No testable commit found.\n" - "Maybe you started with bad path parameters?\n"); + fprintf(stderr, _("No testable commit found.\n" + "Maybe you started with bad path parameters?\n")); exit(4); } @@ -989,9 +990,14 @@ int bisect_next_all(const char *prefix, int no_checkout) nr = all - reaches - 1; steps = estimate_bisect_steps(all); - printf("Bisecting: %d revision%s left to test after this " - "(roughly %d step%s)\n", nr, (nr == 1 ? "" : "s"), - steps, (steps == 1 ? "" : "s")); + xsnprintf(steps_msg, sizeof(steps_msg), + Q_("(roughly %d step)", "(roughly %d steps)", steps), + steps); + /* TRANSLATORS: the last %s will be replaced with + "(roughly %d steps)" translation */ + printf(Q_("Bisecting: %d revision left to test after this %s\n", + "Bisecting: %d revisions left to test after this %s\n", + nr), nr, steps_msg); return bisect_checkout(bisect_rev, no_checkout); } diff --git a/builtin/apply.c b/builtin/apply.c index 7fc5c3e307..1a488f9e88 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -3359,7 +3359,7 @@ static int load_patch_target(struct apply_state *state, { if (state->cached || state->check_index) { if (read_file_or_gitlink(ce, buf)) - return error(_("read of %s failed"), name); + return error(_("failed to read %s"), name); } else if (name) { if (S_ISGITLINK(expected_mode)) { if (ce) @@ -3370,7 +3370,7 @@ static int load_patch_target(struct apply_state *state, return error(_("reading from '%s' beyond a symbolic link"), name); } else { if (read_old_data(st, name, buf)) - return error(_("read of %s failed"), name); + return error(_("failed to read %s"), name); } } return 0; @@ -3416,7 +3416,7 @@ static int load_preimage(struct apply_state *state, free_fragment_list(patch->fragments); patch->fragments = NULL; } else if (status) { - return error(_("read of %s failed"), patch->old_name); + return error(_("failed to read %s"), patch->old_name); } } diff --git a/builtin/blame.c b/builtin/blame.c index 1e214bd4ec..8fec0e1fb3 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -134,7 +134,7 @@ struct progress_info { int blamed_lines; }; -static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, long ctxlen, +static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, xdl_emit_hunk_consume_func_t hunk_func, void *cb_data) { xpparam_t xpp = {0}; @@ -142,7 +142,6 @@ static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, long ctxlen, xdemitcb_t ecb = {NULL}; xpp.flags = xdl_opts; - xecfg.ctxlen = ctxlen; xecfg.hunk_func = hunk_func; ecb.priv = cb_data; return xdi_diff(file_a, file_b, &xpp, &xecfg, &ecb); @@ -599,7 +598,7 @@ static struct origin *find_origin(struct scoreboard *sb, p->status); case 'M': porigin = get_origin(sb, parent, origin->path); - hashcpy(porigin->blob_sha1, p->one->sha1); + hashcpy(porigin->blob_sha1, p->one->oid.hash); porigin->mode = p->one->mode; break; case 'A': @@ -645,7 +644,7 @@ static struct origin *find_rename(struct scoreboard *sb, if ((p->status == 'R' || p->status == 'C') && !strcmp(p->two->path, origin->path)) { porigin = get_origin(sb, parent, p->one->path); - hashcpy(porigin->blob_sha1, p->one->sha1); + hashcpy(porigin->blob_sha1, p->one->oid.hash); porigin->mode = p->one->mode; break; } @@ -980,7 +979,7 @@ static void pass_blame_to_parent(struct scoreboard *sb, fill_origin_blob(&sb->revs->diffopt, target, &file_o); num_get_patch++; - if (diff_hunks(&file_p, &file_o, 0, blame_chunk_cb, &d)) + if (diff_hunks(&file_p, &file_o, blame_chunk_cb, &d)) die("unable to generate diff (%s -> %s)", oid_to_hex(&parent->commit->object.oid), oid_to_hex(&target->commit->object.oid)); @@ -1129,7 +1128,7 @@ static void find_copy_in_blob(struct scoreboard *sb, * file_p partially may match that image. */ memset(split, 0, sizeof(struct blame_entry [3])); - if (diff_hunks(file_p, &file_o, 1, handle_split_cb, &d)) + if (diff_hunks(file_p, &file_o, handle_split_cb, &d)) die("unable to generate diff (%s)", oid_to_hex(&parent->commit->object.oid)); /* remainder, if any, all match the preimage */ @@ -1309,7 +1308,7 @@ static void find_copy_in_parent(struct scoreboard *sb, continue; norigin = get_origin(sb, parent, p->one->path); - hashcpy(norigin->blob_sha1, p->one->sha1); + hashcpy(norigin->blob_sha1, p->one->oid.hash); norigin->mode = p->one->mode; fill_origin_blob(&sb->revs->diffopt, norigin, &file_p); if (!file_p.ptr) diff --git a/builtin/branch.c b/builtin/branch.c index 2ecde53bf8..12203fdcc8 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -614,9 +614,9 @@ static int edit_branch_description(const char *branch_name) if (!buf.len || buf.buf[buf.len-1] != '\n') strbuf_addch(&buf, '\n'); strbuf_commented_addf(&buf, - "Please edit the description for the branch\n" - " %s\n" - "Lines starting with '%c' will be stripped.\n", + _("Please edit the description for the branch\n" + " %s\n" + "Lines starting with '%c' will be stripped.\n"), branch_name, comment_line_char); if (write_file_gently(git_path(edit_description), "%s", buf.buf)) { strbuf_release(&buf); diff --git a/builtin/checkout.c b/builtin/checkout.c index c3486bdec3..27c1a05246 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -276,7 +276,7 @@ static int checkout_paths(const struct checkout_opts *opts, hold_locked_index(lock_file, 1); if (read_cache_preload(&opts->pathspec) < 0) - return error(_("corrupt index file")); + return error(_("index file corrupt")); if (opts->source_tree) read_tree_some(opts->source_tree, &opts->pathspec); @@ -470,7 +470,7 @@ static int merge_working_tree(const struct checkout_opts *opts, hold_locked_index(lock_file, 1); if (read_cache_preload(NULL) < 0) - return error(_("corrupt index file")); + return error(_("index file corrupt")); resolve_undo_clear(); if (opts->force) { @@ -1138,7 +1138,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"), N_("create/reset and checkout a branch")), OPT_BOOL('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")), - OPT_BOOL(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")), + OPT_BOOL(0, "detach", &opts.force_detach, N_("detach HEAD at named commit")), OPT_SET_INT('t', "track", &opts.track, N_("set upstream info for new branch"), BRANCH_TRACK_EXPLICIT), OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new-branch"), N_("new unparented branch")), diff --git a/builtin/commit.c b/builtin/commit.c index 3f189428b1..1f6dbcd0d0 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -715,7 +715,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, char *buffer; buffer = strstr(use_message_buffer, "\n\n"); if (buffer) - strbuf_addstr(&sb, buffer + 2); + strbuf_addstr(&sb, skip_blank_lines(buffer + 2)); hook_arg1 = "commit"; hook_arg2 = use_message; } else if (fixup_message) { diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 8164b581a6..c0652a7ed0 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -368,7 +368,7 @@ static void show_filemodify(struct diff_queue_struct *q, print_path(spec->path); putchar('\n'); - if (!hashcmp(ospec->sha1, spec->sha1) && + if (!oidcmp(&ospec->oid, &spec->oid) && ospec->mode == spec->mode) break; /* fallthrough */ @@ -383,10 +383,10 @@ static void show_filemodify(struct diff_queue_struct *q, if (no_data || S_ISGITLINK(spec->mode)) printf("M %06o %s ", spec->mode, sha1_to_hex(anonymize ? - anonymize_sha1(spec->sha1) : - spec->sha1)); + anonymize_sha1(spec->oid.hash) : + spec->oid.hash)); else { - struct object *object = lookup_object(spec->sha1); + struct object *object = lookup_object(spec->oid.hash); printf("M %06o :%d ", spec->mode, get_object_mark(object)); } @@ -572,7 +572,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev) /* Export the referenced blobs, and remember the marks. */ for (i = 0; i < diff_queued_diff.nr; i++) if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode)) - export_blob(diff_queued_diff.queue[i]->two->sha1); + export_blob(diff_queued_diff.queue[i]->two->oid.hash); refname = commit->util; if (anonymize) { diff --git a/builtin/fetch.c b/builtin/fetch.c index f896aa1f88..d9ea6f392a 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -15,6 +15,7 @@ #include "submodule.h" #include "connected.h" #include "argv-array.h" +#include "utf8.h" static const char * const builtin_fetch_usage[] = { N_("git fetch [<options>] [<repository> [<refspec>...]]"), @@ -449,7 +450,132 @@ fail: : STORE_REF_ERROR_OTHER; } -#define REFCOL_WIDTH 10 +static int refcol_width = 10; +static int compact_format; + +static void adjust_refcol_width(const struct ref *ref) +{ + int max, rlen, llen, len; + + /* uptodate lines are only shown on high verbosity level */ + if (!verbosity && !oidcmp(&ref->peer_ref->old_oid, &ref->old_oid)) + return; + + max = term_columns(); + rlen = utf8_strwidth(prettify_refname(ref->name)); + + llen = utf8_strwidth(prettify_refname(ref->peer_ref->name)); + + /* + * rough estimation to see if the output line is too long and + * should not be counted (we can't do precise calculation + * anyway because we don't know if the error explanation part + * will be printed in update_local_ref) + */ + if (compact_format) { + llen = 0; + max = max * 2 / 3; + } + len = 21 /* flag and summary */ + rlen + 4 /* -> */ + llen; + if (len >= max) + return; + + /* + * Not precise calculation for compact mode because '*' can + * appear on the left hand side of '->' and shrink the column + * back. + */ + if (refcol_width < rlen) + refcol_width = rlen; +} + +static void prepare_format_display(struct ref *ref_map) +{ + struct ref *rm; + const char *format = "full"; + + git_config_get_string_const("fetch.output", &format); + if (!strcasecmp(format, "full")) + compact_format = 0; + else if (!strcasecmp(format, "compact")) + compact_format = 1; + else + die(_("configuration fetch.output contains invalid value %s"), + format); + + for (rm = ref_map; rm; rm = rm->next) { + if (rm->status == REF_STATUS_REJECT_SHALLOW || + !rm->peer_ref || + !strcmp(rm->name, "HEAD")) + continue; + + adjust_refcol_width(rm); + } +} + +static void print_remote_to_local(struct strbuf *display, + const char *remote, const char *local) +{ + strbuf_addf(display, "%-*s -> %s", refcol_width, remote, local); +} + +static int find_and_replace(struct strbuf *haystack, + const char *needle, + const char *placeholder) +{ + const char *p = strstr(haystack->buf, needle); + int plen, nlen; + + if (!p) + return 0; + + if (p > haystack->buf && p[-1] != '/') + return 0; + + plen = strlen(p); + nlen = strlen(needle); + if (plen > nlen && p[nlen] != '/') + return 0; + + strbuf_splice(haystack, p - haystack->buf, nlen, + placeholder, strlen(placeholder)); + return 1; +} + +static void print_compact(struct strbuf *display, + const char *remote, const char *local) +{ + struct strbuf r = STRBUF_INIT; + struct strbuf l = STRBUF_INIT; + + if (!strcmp(remote, local)) { + strbuf_addf(display, "%-*s -> *", refcol_width, remote); + return; + } + + strbuf_addstr(&r, remote); + strbuf_addstr(&l, local); + + if (!find_and_replace(&r, local, "*")) + find_and_replace(&l, remote, "*"); + print_remote_to_local(display, r.buf, l.buf); + + strbuf_release(&r); + strbuf_release(&l); +} + +static void format_display(struct strbuf *display, char code, + const char *summary, const char *error, + const char *remote, const char *local) +{ + strbuf_addf(display, "%c %-*s ", code, TRANSPORT_SUMMARY(summary)); + if (!compact_format) + print_remote_to_local(display, remote, local); + else + print_compact(display, remote, local); + if (error) + strbuf_addf(display, " (%s)", error); +} static int update_local_ref(struct ref *ref, const char *remote, @@ -467,9 +593,8 @@ static int update_local_ref(struct ref *ref, if (!oidcmp(&ref->old_oid, &ref->new_oid)) { if (verbosity > 0) - strbuf_addf(display, "= %-*s %-*s -> %s", - TRANSPORT_SUMMARY(_("[up to date]")), - REFCOL_WIDTH, remote, pretty_ref); + format_display(display, '=', _("[up to date]"), NULL, + remote, pretty_ref); return 0; } @@ -481,10 +606,9 @@ static int update_local_ref(struct ref *ref, * If this is the head, and it's not okay to update * the head, and the old value of the head isn't empty... */ - strbuf_addf(display, - _("! %-*s %-*s -> %s (can't fetch in current branch)"), - TRANSPORT_SUMMARY(_("[rejected]")), - REFCOL_WIDTH, remote, pretty_ref); + format_display(display, '!', _("[rejected]"), + _("can't fetch in current branch"), + remote, pretty_ref); return 1; } @@ -492,11 +616,9 @@ static int update_local_ref(struct ref *ref, starts_with(ref->name, "refs/tags/")) { int r; r = s_update_ref("updating tag", ref, 0); - strbuf_addf(display, "%c %-*s %-*s -> %s%s", - r ? '!' : '-', - TRANSPORT_SUMMARY(_("[tag update]")), - REFCOL_WIDTH, remote, pretty_ref, - r ? _(" (unable to update local ref)") : ""); + format_display(display, r ? '!' : 't', _("[tag update]"), + r ? _("unable to update local ref") : NULL, + remote, pretty_ref); return r; } @@ -527,11 +649,9 @@ static int update_local_ref(struct ref *ref, (recurse_submodules != RECURSE_SUBMODULES_ON)) check_for_new_submodule_commits(ref->new_oid.hash); r = s_update_ref(msg, ref, 0); - strbuf_addf(display, "%c %-*s %-*s -> %s%s", - r ? '!' : '*', - TRANSPORT_SUMMARY(what), - REFCOL_WIDTH, remote, pretty_ref, - r ? _(" (unable to update local ref)") : ""); + format_display(display, r ? '!' : '*', what, + r ? _("unable to update local ref") : NULL, + remote, pretty_ref); return r; } @@ -545,11 +665,9 @@ static int update_local_ref(struct ref *ref, (recurse_submodules != RECURSE_SUBMODULES_ON)) check_for_new_submodule_commits(ref->new_oid.hash); r = s_update_ref("fast-forward", ref, 1); - strbuf_addf(display, "%c %-*s %-*s -> %s%s", - r ? '!' : ' ', - TRANSPORT_SUMMARY_WIDTH, quickref.buf, - REFCOL_WIDTH, remote, pretty_ref, - r ? _(" (unable to update local ref)") : ""); + format_display(display, r ? '!' : ' ', quickref.buf, + r ? _("unable to update local ref") : NULL, + remote, pretty_ref); strbuf_release(&quickref); return r; } else if (force || ref->force) { @@ -562,18 +680,14 @@ static int update_local_ref(struct ref *ref, (recurse_submodules != RECURSE_SUBMODULES_ON)) check_for_new_submodule_commits(ref->new_oid.hash); r = s_update_ref("forced-update", ref, 1); - strbuf_addf(display, "%c %-*s %-*s -> %s (%s)", - r ? '!' : '+', - TRANSPORT_SUMMARY_WIDTH, quickref.buf, - REFCOL_WIDTH, remote, pretty_ref, - r ? _("unable to update local ref") : _("forced update")); + format_display(display, r ? '!' : '+', quickref.buf, + r ? _("unable to update local ref") : _("forced update"), + remote, pretty_ref); strbuf_release(&quickref); return r; } else { - strbuf_addf(display, "! %-*s %-*s -> %s %s", - TRANSPORT_SUMMARY(_("[rejected]")), - REFCOL_WIDTH, remote, pretty_ref, - _("(non-fast-forward)")); + format_display(display, '!', _("[rejected]"), _("non-fast-forward"), + remote, pretty_ref); return 1; } } @@ -620,6 +734,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, goto abort; } + prepare_format_display(ref_map); + /* * We do a pass for each fetch_head_status type in their enum order, so * merged entries are written before not-for-merge. That lets readers @@ -714,11 +830,10 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, rc |= update_local_ref(ref, what, rm, ¬e); free(ref); } else - strbuf_addf(¬e, "* %-*s %-*s -> FETCH_HEAD", - TRANSPORT_SUMMARY_WIDTH, - *kind ? kind : "branch", - REFCOL_WIDTH, - *what ? what : "HEAD"); + format_display(¬e, '*', + *kind ? kind : "branch", NULL, + *what ? what : "HEAD", + "FETCH_HEAD"); if (note.len) { if (verbosity >= 0 && !shown_url) { fprintf(stderr, _("From %.*s\n"), @@ -812,13 +927,15 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map, if (verbosity >= 0) { for (ref = stale_refs; ref; ref = ref->next) { + struct strbuf sb = STRBUF_INIT; if (!shown_url) { fprintf(stderr, _("From %.*s\n"), url_len, url); shown_url = 1; } - fprintf(stderr, " x %-*s %-*s -> %s\n", - TRANSPORT_SUMMARY(_("[deleted]")), - REFCOL_WIDTH, _("(none)"), prettify_refname(ref->name)); + format_display(&sb, '-', _("[deleted]"), NULL, + _("(none)"), prettify_refname(ref->name)); + fprintf(stderr, " %s\n",sb.buf); + strbuf_release(&sb); warn_dangling_symref(stderr, dangling_msg, ref->name); } } diff --git a/builtin/gc.c b/builtin/gc.c index c583aad6ec..332bcf7e7a 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -177,7 +177,7 @@ static int too_many_packs(void) */ cnt++; } - return gc_auto_pack_limit <= cnt; + return gc_auto_pack_limit < cnt; } static void add_repack_all_option(void) diff --git a/builtin/grep.c b/builtin/grep.c index 462e607901..ae738312aa 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -386,7 +386,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int for (nr = 0; nr < active_nr; nr++) { const struct cache_entry *ce = active_cache[nr]; - if (!S_ISREG(ce->ce_mode) || ce_intent_to_add(ce)) + if (!S_ISREG(ce->ce_mode)) continue; if (!ce_path_match(ce, pathspec, NULL)) continue; @@ -396,7 +396,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int * cache version instead */ if (cached || (ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) { - if (ce_stage(ce)) + if (ce_stage(ce) || ce_intent_to_add(ce)) continue; hit |= grep_sha1(opt, ce->sha1, ce->name, 0, ce->name); } diff --git a/builtin/init-db.c b/builtin/init-db.c index b2d8d40a67..3a45f0bcfb 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -397,13 +397,16 @@ int init_db(const char *template_dir, unsigned int flags) if (!(flags & INIT_DB_QUIET)) { int len = strlen(git_dir); - /* TRANSLATORS: The first '%s' is either "Reinitialized - existing" or "Initialized empty", the second " shared" or - "", and the last '%s%s' is the verbatim directory name. */ - printf(_("%s%s Git repository in %s%s\n"), - reinit ? _("Reinitialized existing") : _("Initialized empty"), - get_shared_repository() ? _(" shared") : "", - git_dir, len && git_dir[len-1] != '/' ? "/" : ""); + if (reinit) + printf(get_shared_repository() + ? _("Reinitialized existing shared Git repository in %s%s\n") + : _("Reinitialized existing Git repository in %s%s\n"), + git_dir, len && git_dir[len-1] != '/' ? "/" : ""); + else + printf(get_shared_repository() + ? _("Initialized empty shared Git repository in %s%s\n") + : _("Initialized empty Git repository in %s%s\n"), + git_dir, len && git_dir[len-1] != '/' ? "/" : ""); } return 0; diff --git a/builtin/log.c b/builtin/log.c index de47b4e89a..fd1652f52b 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -33,6 +33,7 @@ static const char *default_date_mode = NULL; static int default_abbrev_commit; static int default_show_root = 1; static int default_follow; +static int default_show_signature; static int decoration_style; static int decoration_given; static int use_mailmap_config; @@ -119,6 +120,7 @@ static void cmd_log_init_defaults(struct rev_info *rev) rev->abbrev_commit = default_abbrev_commit; rev->show_root_diff = default_show_root; rev->subject_prefix = fmt_patch_subject_prefix; + rev->show_signature = default_show_signature; DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV); if (default_date_mode) @@ -236,16 +238,17 @@ static void show_early_header(struct rev_info *rev, const char *stage, int nr) if (rev->commit_format != CMIT_FMT_ONELINE) putchar(rev->diffopt.line_termination); } - printf(_("Final output: %d %s\n"), nr, stage); + fprintf(rev->diffopt.file, _("Final output: %d %s\n"), nr, stage); } static struct itimerval early_output_timer; static void log_show_early(struct rev_info *revs, struct commit_list *list) { - int i = revs->early_output; + int i = revs->early_output, close_file = revs->diffopt.close_file; int show_header = 1; + revs->diffopt.close_file = 0; sort_in_topological_order(&list, revs->sort_order); while (list && i) { struct commit *commit = list->item; @@ -262,14 +265,19 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list) case commit_ignore: break; case commit_error: + if (close_file) + fclose(revs->diffopt.file); return; } list = list->next; } /* Did we already get enough commits for the early output? */ - if (!i) + if (!i) { + if (close_file) + fclose(revs->diffopt.file); return; + } /* * ..if no, then repeat it twice a second until we @@ -331,7 +339,7 @@ static int cmd_log_walk(struct rev_info *rev) { struct commit *commit; int saved_nrl = 0; - int saved_dcctc = 0; + int saved_dcctc = 0, close_file = rev->diffopt.close_file; if (rev->early_output) setup_early_output(rev); @@ -347,6 +355,7 @@ static int cmd_log_walk(struct rev_info *rev) * and HAS_CHANGES being accumulated in rev->diffopt, so be careful to * retain that state information if replacing rev->diffopt in this loop */ + rev->diffopt.close_file = 0; while ((commit = get_revision(rev)) != NULL) { if (!log_tree_commit(rev, commit) && rev->max_count >= 0) /* @@ -367,6 +376,8 @@ static int cmd_log_walk(struct rev_info *rev) } rev->diffopt.degraded_cc_to_c = saved_dcctc; rev->diffopt.needed_rename_limit = saved_nrl; + if (close_file) + fclose(rev->diffopt.file); if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF && DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) { @@ -409,6 +420,10 @@ static int git_log_config(const char *var, const char *value, void *cb) use_mailmap_config = git_config_bool(var, value); return 0; } + if (!strcmp(var, "log.showsignature")) { + default_show_signature = git_config_bool(var, value); + return 0; + } if (grep_config(var, value, cb) < 0) return -1; @@ -445,7 +460,7 @@ static void show_tagger(char *buf, int len, struct rev_info *rev) pp.fmt = rev->commit_format; pp.date_mode = rev->date_mode; pp_user_info(&pp, "Tagger", &out, buf, get_log_output_encoding()); - printf("%s", out.buf); + fprintf(rev->diffopt.file, "%s", out.buf); strbuf_release(&out); } @@ -456,7 +471,7 @@ static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, con char *buf; unsigned long size; - fflush(stdout); + fflush(rev->diffopt.file); if (!DIFF_OPT_TOUCHED(&rev->diffopt, ALLOW_TEXTCONV) || !DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV)) return stream_blob_to_fd(1, sha1, NULL, 0); @@ -496,7 +511,7 @@ static int show_tag_object(const unsigned char *sha1, struct rev_info *rev) } if (offset < size) - fwrite(buf + offset, size - offset, 1, stdout); + fwrite(buf + offset, size - offset, 1, rev->diffopt.file); free(buf); return 0; } @@ -505,7 +520,8 @@ static int show_tree_object(const unsigned char *sha1, struct strbuf *base, const char *pathname, unsigned mode, int stage, void *context) { - printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : ""); + FILE *file = context; + fprintf(file, "%s%s\n", pathname, S_ISDIR(mode) ? "/" : ""); return 0; } @@ -565,7 +581,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) if (rev.shown_one) putchar('\n'); - printf("%stag %s%s\n", + fprintf(rev.diffopt.file, "%stag %s%s\n", diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), t->tag, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); @@ -584,12 +600,12 @@ int cmd_show(int argc, const char **argv, const char *prefix) case OBJ_TREE: if (rev.shown_one) putchar('\n'); - printf("%stree %s%s\n\n", + fprintf(rev.diffopt.file, "%stree %s%s\n\n", diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), name, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); read_tree_recursive((struct tree *)o, "", 0, 0, &match_all, - show_tree_object, NULL); + show_tree_object, rev.diffopt.file); rev.shown_one = 1; break; case OBJ_COMMIT: @@ -795,11 +811,10 @@ static int git_format_config(const char *var, const char *value, void *cb) return git_log_config(var, value, cb); } -static FILE *realstdout = NULL; static const char *output_directory = NULL; static int outdir_offset; -static int reopen_stdout(struct commit *commit, const char *subject, +static int open_next_file(struct commit *commit, const char *subject, struct rev_info *rev, int quiet) { struct strbuf filename = STRBUF_INIT; @@ -821,9 +836,9 @@ static int reopen_stdout(struct commit *commit, const char *subject, fmt_output_subject(&filename, subject, rev); if (!quiet) - fprintf(realstdout, "%s\n", filename.buf + outdir_offset); + printf("%s\n", filename.buf + outdir_offset); - if (freopen(filename.buf, "w", stdout) == NULL) + if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) return error(_("Cannot open patch file %s"), filename.buf); strbuf_release(&filename); @@ -882,15 +897,15 @@ static void gen_message_id(struct rev_info *info, char *base) info->message_id = strbuf_detach(&buf, NULL); } -static void print_signature(void) +static void print_signature(FILE *file) { if (!signature || !*signature) return; - printf("-- \n%s", signature); + fprintf(file, "-- \n%s", signature); if (signature[strlen(signature)-1] != '\n') - putchar('\n'); - putchar('\n'); + putc('\n', file); + putc('\n', file); } static void add_branch_description(struct strbuf *buf, const char *branch_name) @@ -959,7 +974,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, committer = git_committer_info(0); if (!use_stdout && - reopen_stdout(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet)) + open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet)) return; log_write_email_headers(rev, head, &pp.subject, &pp.after_subject, @@ -982,7 +997,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte); pp_remainder(&pp, &msg, &sb, 0); add_branch_description(&sb, branch_name); - printf("%s\n", sb.buf); + fprintf(rev->diffopt.file, "%s\n", sb.buf); strbuf_release(&sb); @@ -991,6 +1006,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, log.wrap = 72; log.in1 = 2; log.in2 = 4; + log.file = rev->diffopt.file; for (i = 0; i < nr; i++) shortlog_add_commit(&log, list[i]); @@ -1013,8 +1029,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, diffcore_std(&opts); diff_flush(&opts); - printf("\n"); - print_signature(); + fprintf(rev->diffopt.file, "\n"); + print_signature(rev->diffopt.file); } static const char *clean_message_id(const char *msg_id) @@ -1324,7 +1340,7 @@ static void prepare_bases(struct base_tree_info *bases, } } -static void print_bases(struct base_tree_info *bases) +static void print_bases(struct base_tree_info *bases, FILE *file) { int i; @@ -1333,11 +1349,11 @@ static void print_bases(struct base_tree_info *bases) return; /* Show the base commit */ - printf("base-commit: %s\n", oid_to_hex(&bases->base_commit)); + fprintf(file, "base-commit: %s\n", oid_to_hex(&bases->base_commit)); /* Show the prerequisite patches */ for (i = bases->nr_patch_id - 1; i >= 0; i--) - printf("prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i])); + fprintf(file, "prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i])); free(bases->patch_id); bases->nr_patch_id = 0; @@ -1569,6 +1585,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) setup_pager(); if (output_directory) { + if (rev.diffopt.use_color != GIT_COLOR_ALWAYS) + rev.diffopt.use_color = GIT_COLOR_NEVER; if (use_stdout) die(_("standard output, or directory, which one?")); if (mkdir(output_directory, 0777) < 0 && errno != EEXIST) @@ -1626,9 +1644,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) get_patch_ids(&rev, &ids); } - if (!use_stdout) - realstdout = xfdopen(xdup(1), "w"); - if (prepare_revision_walk(&rev)) die(_("revision walk setup failed")); rev.boundary = 1; @@ -1693,7 +1708,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) gen_message_id(&rev, "cover"); make_cover_letter(&rev, use_stdout, origin, nr, list, branch_name, quiet); - print_bases(&bases); + print_bases(&bases, rev.diffopt.file); total++; start_number--; } @@ -1739,7 +1754,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } if (!use_stdout && - reopen_stdout(rev.numbered_files ? NULL : commit, NULL, &rev, quiet)) + open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet)) die(_("Failed to create output files")); shown = log_tree_commit(&rev, commit); free_commit_buffer(commit); @@ -1754,15 +1769,15 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.shown_one = 0; if (shown) { if (rev.mime_boundary) - printf("\n--%s%s--\n\n\n", + fprintf(rev.diffopt.file, "\n--%s%s--\n\n\n", mime_boundary_leader, rev.mime_boundary); else - print_signature(); - print_bases(&bases); + print_signature(rev.diffopt.file); + print_bases(&bases, rev.diffopt.file); } if (!use_stdout) - fclose(stdout); + fclose(rev.diffopt.file); } free(list); free(branch_name); @@ -1794,15 +1809,15 @@ static const char * const cherry_usage[] = { }; static void print_commit(char sign, struct commit *commit, int verbose, - int abbrev) + int abbrev, FILE *file) { if (!verbose) { - printf("%c %s\n", sign, + fprintf(file, "%c %s\n", sign, find_unique_abbrev(commit->object.oid.hash, abbrev)); } else { struct strbuf buf = STRBUF_INIT; pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf); - printf("%c %s %s\n", sign, + fprintf(file, "%c %s %s\n", sign, find_unique_abbrev(commit->object.oid.hash, abbrev), buf.buf); strbuf_release(&buf); @@ -1883,7 +1898,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) commit = list->item; if (has_commit_patch_id(commit, &ids)) sign = '-'; - print_commit(sign, commit, verbose, abbrev); + print_commit(sign, commit, verbose, abbrev, revs.diffopt.file); list = list->next; } diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index 491efd556e..fd2c4556e1 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -9,10 +9,10 @@ static const char builtin_merge_recursive_usage[] = static const char *better_branch_name(const char *branch) { - static char githead_env[8 + 40 + 1]; + static char githead_env[8 + GIT_SHA1_HEXSZ + 1]; char *name; - if (strlen(branch) != 40) + if (strlen(branch) != GIT_SHA1_HEXSZ) return branch; xsnprintf(githead_env, sizeof(githead_env), "GITHEAD_%s", branch); name = getenv(githead_env); @@ -21,10 +21,10 @@ static const char *better_branch_name(const char *branch) int cmd_merge_recursive(int argc, const char **argv, const char *prefix) { - const unsigned char *bases[21]; + const struct object_id *bases[21]; unsigned bases_count = 0; int i, failed; - unsigned char h1[20], h2[20]; + struct object_id h1, h2; struct merge_options o; struct commit *result; @@ -46,10 +46,10 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) continue; } if (bases_count < ARRAY_SIZE(bases)-1) { - unsigned char *sha = xmalloc(20); - if (get_sha1(argv[i], sha)) + struct object_id *oid = xmalloc(sizeof(struct object_id)); + if (get_oid(argv[i], oid)) die("Could not parse object '%s'", argv[i]); - bases[bases_count++] = sha; + bases[bases_count++] = oid; } else warning("Cannot handle more than %d bases. " @@ -62,9 +62,9 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) o.branch1 = argv[++i]; o.branch2 = argv[++i]; - if (get_sha1(o.branch1, h1)) + if (get_oid(o.branch1, &h1)) die("Could not resolve ref '%s'", o.branch1); - if (get_sha1(o.branch2, h2)) + if (get_oid(o.branch2, &h2)) die("Could not resolve ref '%s'", o.branch2); o.branch1 = better_branch_name(o.branch1); @@ -73,7 +73,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) if (o.verbosity >= 3) printf("Merging %s with %s\n", o.branch1, o.branch2); - failed = merge_recursive_generic(&o, h1, h2, bases_count, bases, &result); + failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result); if (failed < 0) return 128; /* die() error code */ return failed; diff --git a/builtin/merge.c b/builtin/merge.c index b555a1bf9c..0dfe09eb19 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -211,7 +211,7 @@ static struct option builtin_merge_options[] = { PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, FF_ONLY }, OPT_RERERE_AUTOUPDATE(&allow_rerere_auto), OPT_BOOL(0, "verify-signatures", &verify_signatures, - N_("Verify that the named commit has a valid GPG signature")), + N_("verify that the named commit has a valid GPG signature")), OPT_CALLBACK('s', "strategy", &use_strategies, N_("strategy"), N_("merge strategy to use"), option_parse_strategy), OPT_CALLBACK('X', "strategy-option", &xopts, N_("option=value"), @@ -501,7 +501,7 @@ static void merge_name(const char *remote, struct strbuf *msg) if (ref_exists(truname.buf)) { strbuf_addf(msg, "%s\t\tbranch '%s'%s of .\n", - sha1_to_hex(remote_head->object.oid.hash), + oid_to_hex(&remote_head->object.oid), truname.buf + 11, (early ? " (early part)" : "")); strbuf_release(&truname); @@ -515,7 +515,7 @@ static void merge_name(const char *remote, struct strbuf *msg) desc = merge_remote_util(remote_head); if (desc && desc->obj && desc->obj->type == OBJ_TAG) { strbuf_addf(msg, "%s\t\t%s '%s'\n", - sha1_to_hex(desc->obj->oid.hash), + oid_to_hex(&desc->obj->oid), typename(desc->obj->type), remote); goto cleanup; @@ -523,7 +523,7 @@ static void merge_name(const char *remote, struct strbuf *msg) } strbuf_addf(msg, "%s\t\tcommit '%s'\n", - sha1_to_hex(remote_head->object.oid.hash), remote); + oid_to_hex(&remote_head->object.oid), remote); cleanup: strbuf_release(&buf); strbuf_release(&bname); @@ -1014,7 +1014,7 @@ static int default_edit_option(void) if (e) { int v = git_config_maybe_bool(name, e); if (v < 0) - die("Bad value '%s' in environment '%s'", e, name); + die(_("Bad value '%s' in environment '%s'"), e, name); return v; } @@ -1115,7 +1115,7 @@ static void handle_fetch_head(struct commit_list **remotes, struct strbuf *merge if (!commit) { if (ptr) *ptr = '\0'; - die("not something we can merge in %s: %s", + die(_("not something we can merge in %s: %s"), filename, merge_names->buf + pos); } remotes = &commit_list_insert(commit, remotes)->next; @@ -1149,7 +1149,7 @@ static struct commit_list *collect_parents(struct commit *head_commit, struct commit *commit = get_merge_parent(argv[i]); if (!commit) help_unknown_ref(argv[i], "merge", - "not something we can merge"); + _("not something we can merge")); remotes = &commit_list_insert(commit, remotes)->next; } remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads); @@ -1366,7 +1366,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) for (p = remoteheads; p; p = p->next) { struct commit *commit = p->item; strbuf_addf(&buf, "GITHEAD_%s", - sha1_to_hex(commit->object.oid.hash)); + oid_to_hex(&commit->object.oid)); setenv(buf.buf, merge_remote_util(commit)->name, 1); strbuf_reset(&buf); if (fast_forward != FF_ONLY && @@ -1421,11 +1421,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * If head can reach all the merge then we are up to date. * but first the most common case of merging one remote. */ - finish_up_to_date("Already up-to-date."); + finish_up_to_date(_("Already up-to-date.")); goto done; } else if (fast_forward != FF_NO && !remoteheads->next && !common->next && - !hashcmp(common->item->object.oid.hash, head_commit->object.oid.hash)) { + !oidcmp(&common->item->object.oid, &head_commit->object.oid)) { /* Again the most common case of merging one remote. */ struct strbuf msg = STRBUF_INIT; struct commit *commit; @@ -1499,14 +1499,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * HEAD^^" would be missed. */ common_one = get_merge_bases(head_commit, j->item); - if (hashcmp(common_one->item->object.oid.hash, - j->item->object.oid.hash)) { + if (oidcmp(&common_one->item->object.oid, &j->item->object.oid)) { up_to_date = 0; break; } } if (up_to_date) { - finish_up_to_date("Already up-to-date. Yeeah!"); + finish_up_to_date(_("Already up-to-date. Yeeah!")); goto done; } } @@ -1530,7 +1529,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * Stash away the local changes so that we can try more than one. */ save_state(stash)) - hashcpy(stash, null_sha1); + hashclr(stash); for (i = 0; i < use_strategies_nr; i++) { int ret; diff --git a/builtin/notes.c b/builtin/notes.c index c65b59ad9a..0572051762 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -749,7 +749,7 @@ static int git_config_get_notes_strategy(const char *key, if (git_config_get_string(key, &value)) return 1; if (parse_notes_merge_strategy(value, strategy)) - git_die_config(key, "unknown notes merge strategy %s", value); + git_die_config(key, _("unknown notes merge strategy %s"), value); free(value); return 0; @@ -788,15 +788,15 @@ static int merge(int argc, const char **argv, const char *prefix) if (strategy || do_commit + do_abort == 0) do_merge = 1; if (do_merge + do_commit + do_abort != 1) { - error("cannot mix --commit, --abort or -s/--strategy"); + error(_("cannot mix --commit, --abort or -s/--strategy")); usage_with_options(git_notes_merge_usage, options); } if (do_merge && argc != 1) { - error("Must specify a notes ref to merge"); + error(_("Must specify a notes ref to merge")); usage_with_options(git_notes_merge_usage, options); } else if (!do_merge && argc) { - error("too many parameters"); + error(_("too many parameters")); usage_with_options(git_notes_merge_usage, options); } @@ -817,7 +817,7 @@ static int merge(int argc, const char **argv, const char *prefix) if (strategy) { if (parse_notes_merge_strategy(strategy, &o.strategy)) { - error("Unknown -s/--strategy: %s", strategy); + error(_("Unknown -s/--strategy: %s"), strategy); usage_with_options(git_notes_merge_usage, options); } } else { @@ -857,11 +857,11 @@ static int merge(int argc, const char **argv, const char *prefix) die(_("A notes merge into %s is already in-progress at %s"), default_notes_ref(), wt->path); if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL)) - die("Failed to store link to current notes ref (%s)", + die(_("Failed to store link to current notes ref (%s)"), default_notes_ref()); - printf("Automatic notes merge failed. Fix conflicts in %s and " - "commit the result with 'git notes merge --commit', or " - "abort the merge with 'git notes merge --abort'.\n", + printf(_("Automatic notes merge failed. Fix conflicts in %s and " + "commit the result with 'git notes merge --commit', or " + "abort the merge with 'git notes merge --abort'.\n"), git_path(NOTES_MERGE_WORKTREE)); } @@ -934,8 +934,8 @@ static int prune(int argc, const char **argv, const char *prefix) struct notes_tree *t; int show_only = 0, verbose = 0; struct option options[] = { - OPT__DRY_RUN(&show_only, "do not remove, show only"), - OPT__VERBOSE(&verbose, "report pruned notes"), + OPT__DRY_RUN(&show_only, N_("do not remove, show only")), + OPT__VERBOSE(&verbose, N_("report pruned notes")), OPT_END() }; @@ -964,7 +964,7 @@ static int get_ref(int argc, const char **argv, const char *prefix) git_notes_get_ref_usage, 0); if (argc) { - error("too many parameters"); + error(_("too many parameters")); usage_with_options(git_notes_get_ref_usage, options); } diff --git a/builtin/pull.c b/builtin/pull.c index 897a7f4e4e..398aae16c0 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -855,7 +855,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix) git_config(git_pull_config, NULL); if (read_cache_unmerged()) - die_resolve_conflict("Pull"); + die_resolve_conflict("pull"); if (file_exists(git_path("MERGE_HEAD"))) die_conclude_merge(); diff --git a/builtin/remote.c b/builtin/remote.c index 5ded3018af..a4d9c1a8e9 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -952,7 +952,7 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data) struct show_info *show_info = cb_data; struct branch_info *branch_info = item->util; struct string_list *merge = &branch_info->merge; - const char *also; + int width = show_info->width + 4; int i; if (branch_info->rebase && branch_info->merge.nr > 1) { @@ -963,19 +963,18 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data) printf(" %-*s ", show_info->width, item->string); if (branch_info->rebase) { - printf_ln(_(branch_info->rebase == INTERACTIVE_REBASE ? - "rebases interactively onto remote %s" : - "rebases onto remote %s"), merge->items[0].string); + printf_ln(branch_info->rebase == INTERACTIVE_REBASE + ? _("rebases interactively onto remote %s") + : _("rebases onto remote %s"), merge->items[0].string); return 0; } else if (show_info->any_rebase) { printf_ln(_(" merges with remote %s"), merge->items[0].string); - also = _(" and with remote"); + width++; } else { printf_ln(_("merges with remote %s"), merge->items[0].string); - also = _(" and with remote"); } for (i = 1; i < merge->nr; i++) - printf(" %-*s %s %s\n", show_info->width, "", also, + printf(_("%-*s and with remote %s\n"), width, "", merge->items[i].string); return 0; @@ -1158,11 +1157,11 @@ static int show(int argc, const char **argv) the one in " Fetch URL: %s" translation */ printf_ln(_(" Push URL: %s"), url[i]); if (!i) - printf_ln(_(" Push URL: %s"), "(no URL)"); + printf_ln(_(" Push URL: %s"), _("(no URL)")); if (no_query) - printf_ln(_(" HEAD branch: %s"), "(not queried)"); + printf_ln(_(" HEAD branch: %s"), _("(not queried)")); else if (!states.heads.nr) - printf_ln(_(" HEAD branch: %s"), "(unknown)"); + printf_ln(_(" HEAD branch: %s"), _("(unknown)")); else if (states.heads.nr == 1) printf_ln(_(" HEAD branch: %s"), states.heads.items[0].string); else { diff --git a/builtin/repack.c b/builtin/repack.c index f7b7409cb7..80dd06b4a2 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -388,7 +388,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) item->string, exts[ext].name); if (remove_path(fname)) - warning(_("removing '%s' failed"), fname); + warning(_("failed to remove '%s'"), fname); free(fname); } } diff --git a/builtin/reset.c b/builtin/reset.c index acd6278868..9020ec66c8 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -103,7 +103,7 @@ static void print_new_head_line(struct commit *commit) if (body) { const char *eol; size_t len; - body += 2; + body = skip_blank_lines(body + 2); eol = strchr(body, '\n'); len = eol ? eol - body : strlen(body); printf(" %.*s\n", (int) len, body); @@ -121,7 +121,7 @@ static void update_index_from_diff(struct diff_queue_struct *q, for (i = 0; i < q->nr; i++) { struct diff_filespec *one = q->queue[i]->one; - int is_missing = !(one->mode && !is_null_sha1(one->sha1)); + int is_missing = !(one->mode && !is_null_oid(&one->oid)); struct cache_entry *ce; if (is_missing && !intent_to_add) { @@ -129,7 +129,7 @@ static void update_index_from_diff(struct diff_queue_struct *q, continue; } - ce = make_cache_entry(one->mode, one->sha1, one->path, + ce = make_cache_entry(one->mode, one->oid.hash, one->path, 0, 0); if (!ce) die(_("make_cache_entry failed for path '%s'"), diff --git a/builtin/shortlog.c b/builtin/shortlog.c index f83984e8a1..25fa8a6aed 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -276,6 +276,7 @@ parse_done: log.user_format = rev.commit_format == CMIT_FMT_USERFORMAT; log.abbrev = rev.abbrev; + log.file = rev.diffopt.file; /* assume HEAD if from a tty */ if (!nongit && !rev.pending.nr && isatty(0)) @@ -289,6 +290,8 @@ parse_done: get_from_rev(&rev, &log); shortlog_output(&log); + if (log.file != stdout) + fclose(log.file); return 0; } @@ -310,22 +313,24 @@ void shortlog_output(struct shortlog *log) for (i = 0; i < log->list.nr; i++) { const struct string_list_item *item = &log->list.items[i]; if (log->summary) { - printf("%6d\t%s\n", (int)UTIL_TO_INT(item), item->string); + fprintf(log->file, "%6d\t%s\n", + (int)UTIL_TO_INT(item), item->string); } else { struct string_list *onelines = item->util; - printf("%s (%d):\n", item->string, onelines->nr); + fprintf(log->file, "%s (%d):\n", + item->string, onelines->nr); for (j = onelines->nr - 1; j >= 0; j--) { const char *msg = onelines->items[j].string; if (log->wrap_lines) { strbuf_reset(&sb); add_wrapped_shortlog_msg(&sb, msg, log); - fwrite(sb.buf, sb.len, 1, stdout); + fwrite(sb.buf, sb.len, 1, log->file); } else - printf(" %s\n", msg); + fprintf(log->file, " %s\n", msg); } - putchar('\n'); + putc('\n', log->file); onelines->strdup_strings = 1; string_list_clear(onelines, 0); free(onelines); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index c7deb55785..b22352b6e1 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -590,10 +590,14 @@ struct submodule_update_clone { /* If we want to stop as fast as possible and return an error */ unsigned quickstop : 1; + + /* failed clones to be retried again */ + const struct cache_entry **failed_clones; + int failed_clones_nr, failed_clones_alloc; }; #define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \ SUBMODULE_UPDATE_STRATEGY_INIT, 0, -1, NULL, NULL, NULL, NULL, \ - STRING_LIST_INIT_DUP, 0} + STRING_LIST_INIT_DUP, 0, NULL, 0, 0} static void next_submodule_warn_missing(struct submodule_update_clone *suc, @@ -718,23 +722,47 @@ cleanup: static int update_clone_get_next_task(struct child_process *child, struct strbuf *err, void *suc_cb, - void **void_task_cb) + void **idx_task_cb) { struct submodule_update_clone *suc = suc_cb; + const struct cache_entry *ce; + int index; for (; suc->current < suc->list.nr; suc->current++) { - const struct cache_entry *ce = suc->list.entries[suc->current]; + ce = suc->list.entries[suc->current]; if (prepare_to_clone_next_submodule(ce, child, suc, err)) { + int *p = xmalloc(sizeof(*p)); + *p = suc->current; + *idx_task_cb = p; suc->current++; return 1; } } + + /* + * The loop above tried cloning each submodule once, now try the + * stragglers again, which we can imagine as an extension of the + * entry list. + */ + index = suc->current - suc->list.nr; + if (index < suc->failed_clones_nr) { + int *p; + ce = suc->failed_clones[index]; + if (!prepare_to_clone_next_submodule(ce, child, suc, err)) + die("BUG: ce was a submodule before?"); + p = xmalloc(sizeof(*p)); + *p = suc->current; + *idx_task_cb = p; + suc->current ++; + return 1; + } + return 0; } static int update_clone_start_failure(struct strbuf *err, void *suc_cb, - void *void_task_cb) + void *idx_task_cb) { struct submodule_update_clone *suc = suc_cb; suc->quickstop = 1; @@ -744,15 +772,39 @@ static int update_clone_start_failure(struct strbuf *err, static int update_clone_task_finished(int result, struct strbuf *err, void *suc_cb, - void *void_task_cb) + void *idx_task_cb) { + const struct cache_entry *ce; struct submodule_update_clone *suc = suc_cb; + int *idxP = *(int**)idx_task_cb; + int idx = *idxP; + free(idxP); + if (!result) return 0; - suc->quickstop = 1; - return 1; + if (idx < suc->list.nr) { + ce = suc->list.entries[idx]; + strbuf_addf(err, _("Failed to clone '%s'. Retry scheduled"), + ce->name); + strbuf_addch(err, '\n'); + ALLOC_GROW(suc->failed_clones, + suc->failed_clones_nr + 1, + suc->failed_clones_alloc); + suc->failed_clones[suc->failed_clones_nr++] = ce; + return 0; + } else { + idx = suc->current - suc->list.nr; + ce = suc->failed_clones[idx]; + strbuf_addf(err, _("Failed to clone '%s' a second time, aborting"), + ce->name); + strbuf_addch(err, '\n'); + suc->quickstop = 1; + return 1; + } + + return 0; } static int update_clone(int argc, const char **argv, const char *prefix) diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 875e7ed998..172470bf24 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -355,7 +355,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size, return; /* we are done */ else { /* cannot resolve yet --- queue it */ - hashcpy(obj_list[nr].sha1, null_sha1); + hashclr(obj_list[nr].sha1); add_delta_to_list(nr, base_sha1, 0, delta_data, delta_size); return; } @@ -406,7 +406,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size, * The delta base object is itself a delta that * has not been resolved yet. */ - hashcpy(obj_list[nr].sha1, null_sha1); + hashclr(obj_list[nr].sha1); add_delta_to_list(nr, null_sha1, base_offset, delta_data, delta_size); return; } @@ -1193,6 +1193,7 @@ extern int get_oid_hex(const char *hex, struct object_id *sha1); * printf("%s -> %s", sha1_to_hex(one), sha1_to_hex(two)); */ extern char *sha1_to_hex_r(char *out, const unsigned char *sha1); +extern char *oid_to_hex_r(char *out, const struct object_id *oid); extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */ extern char *oid_to_hex(const struct object_id *oid); /* same static buffer as sha1_to_hex */ @@ -123,19 +123,34 @@ static int parse_color(struct color *out, const char *name, int len) return -1; } -static int parse_attr(const char *name, int len) +static int parse_attr(const char *name, size_t len) { - static const int attr_values[] = { 1, 2, 4, 5, 7, - 22, 22, 24, 25, 27 }; - static const char * const attr_names[] = { - "bold", "dim", "ul", "blink", "reverse", - "nobold", "nodim", "noul", "noblink", "noreverse" + static const struct { + const char *name; + size_t len; + int val, neg; + } attrs[] = { +#define ATTR(x, val, neg) { (x), sizeof(x)-1, (val), (neg) } + ATTR("bold", 1, 22), + ATTR("dim", 2, 22), + ATTR("italic", 3, 23), + ATTR("ul", 4, 24), + ATTR("blink", 5, 25), + ATTR("reverse", 7, 27), + ATTR("strike", 9, 29) +#undef ATTR }; + int negate = 0; int i; - for (i = 0; i < ARRAY_SIZE(attr_names); i++) { - const char *str = attr_names[i]; - if (!strncasecmp(name, str, len) && !str[len]) - return attr_values[i]; + + if (skip_prefix_mem(name, len, "no", &name, &len)) { + skip_prefix_mem(name, len, "-", &name, &len); + negate = 1; + } + + for (i = 0; i < ARRAY_SIZE(attrs); i++) { + if (attrs[i].len == len && !memcmp(attrs[i].name, name, len)) + return negate ? attrs[i].neg : attrs[i].val; } return -1; } @@ -3,26 +3,24 @@ struct strbuf; -/* 2 + (2 * num_attrs) + 8 + 1 + 8 + 'm' + NUL */ -/* "\033[1;2;4;5;7;38;5;2xx;48;5;2xxm\0" */ /* * The maximum length of ANSI color sequence we would generate: * - leading ESC '[' 2 - * - attr + ';' 3 * 10 (e.g. "1;") + * - attr + ';' 2 * num_attr (e.g. "1;") + * - no-attr + ';' 3 * num_attr (e.g. "22;") * - fg color + ';' 17 (e.g. "38;2;255;255;255;") * - bg color + ';' 17 (e.g. "48;2;255;255;255;") * - terminating 'm' NUL 2 * - * The above overcounts attr (we only use 5 not 8) and one semicolon - * but it is close enough. + * The above overcounts by one semicolon but it is close enough. + * + * The space for attributes is also slightly overallocated, as + * the negation for some attributes is the same (e.g., nobold and nodim). + * + * We allocate space for 7 attributes. */ -#define COLOR_MAXLEN 70 +#define COLOR_MAXLEN 75 -/* - * IMPORTANT: Due to the way these color codes are emulated on Windows, - * write them only using printf(), fprintf(), and fputs(). In particular, - * do not use puts() or write(). - */ #define GIT_COLOR_NORMAL "" #define GIT_COLOR_RESET "\033[m" #define GIT_COLOR_BOLD "\033[1m" diff --git a/combine-diff.c b/combine-diff.c index 5920df8b8d..8e2a577bdb 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -44,9 +44,9 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, memset(p->parent, 0, sizeof(p->parent[0]) * num_parent); - hashcpy(p->oid.hash, q->queue[i]->two->sha1); + oidcpy(&p->oid, &q->queue[i]->two->oid); p->mode = q->queue[i]->two->mode; - hashcpy(p->parent[n].oid.hash, q->queue[i]->one->sha1); + oidcpy(&p->parent[n].oid, &q->queue[i]->one->oid); p->parent[n].mode = q->queue[i]->one->mode; p->parent[n].status = q->queue[i]->status; *tail = p; @@ -77,7 +77,7 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, continue; } - hashcpy(p->parent[n].oid.hash, q->queue[i]->one->sha1); + oidcpy(&p->parent[n].oid, &q->queue[i]->one->oid); p->parent[n].mode = q->queue[i]->one->mode; p->parent[n].status = q->queue[i]->status; @@ -1268,16 +1268,16 @@ static struct diff_filepair *combined_pair(struct combine_diff_path *p, for (i = 0; i < num_parent; i++) { pair->one[i].path = p->path; pair->one[i].mode = p->parent[i].mode; - hashcpy(pair->one[i].sha1, p->parent[i].oid.hash); - pair->one[i].sha1_valid = !is_null_oid(&p->parent[i].oid); + oidcpy(&pair->one[i].oid, &p->parent[i].oid); + pair->one[i].oid_valid = !is_null_oid(&p->parent[i].oid); pair->one[i].has_more_entries = 1; } pair->one[num_parent - 1].has_more_entries = 0; pair->two->path = p->path; pair->two->mode = p->mode; - hashcpy(pair->two->sha1, p->oid.hash); - pair->two->sha1_valid = !is_null_oid(&p->oid); + oidcpy(&pair->two->oid, &p->oid); + pair->two->oid_valid = !is_null_oid(&p->oid); return pair; } @@ -414,7 +414,7 @@ int find_commit_subject(const char *commit_buffer, const char **subject) while (*p && (*p != '\n' || p[1] != '\n')) p++; if (*p) { - p += 2; + p = skip_blank_lines(p + 2); for (eol = p; *eol && *eol != '\n'; eol++) ; /* do nothing */ } else @@ -1092,9 +1092,14 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid) { struct strbuf sig = STRBUF_INIT; int inspos, copypos; + const char *eoh; /* find the end of the header */ - inspos = strstr(buf->buf, "\n\n") - buf->buf + 1; + eoh = strstr(buf->buf, "\n\n"); + if (!eoh) + inspos = buf->len; + else + inspos = eoh - buf->buf + 1; if (!keyid || !*keyid) keyid = get_signing_key(); @@ -184,6 +184,7 @@ extern const char *format_subject(struct strbuf *sb, const char *msg, const char *line_separator); extern void userformat_find_requirements(const char *fmt, struct userformat_want *w); extern int commit_format_is_empty(enum cmit_fmt); +extern const char *skip_blank_lines(const char *msg); extern void format_commit_message(const struct commit *commit, const char *format, struct strbuf *sb, const struct pretty_print_context *context); diff --git a/common-main.c b/common-main.c new file mode 100644 index 0000000000..44a29e8b13 --- /dev/null +++ b/common-main.c @@ -0,0 +1,41 @@ +#include "cache.h" +#include "exec_cmd.h" + +/* + * Many parts of Git have subprograms communicate via pipe, expect the + * upstream of a pipe to die with SIGPIPE when the downstream of a + * pipe does not need to read all that is written. Some third-party + * programs that ignore or block SIGPIPE for their own reason forget + * to restore SIGPIPE handling to the default before spawning Git and + * break this carefully orchestrated machinery. + * + * Restore the way SIGPIPE is handled to default, which is what we + * expect. + */ +static void restore_sigpipe_to_default(void) +{ + sigset_t unblock; + + sigemptyset(&unblock); + sigaddset(&unblock, SIGPIPE); + sigprocmask(SIG_UNBLOCK, &unblock, NULL); + signal(SIGPIPE, SIG_DFL); +} + +int main(int argc, const char **argv) +{ + /* + * Always open file descriptors 0/1/2 to avoid clobbering files + * in die(). It also avoids messing up when the pipes are dup'ed + * onto stdin/stdout/stderr in the child processes we spawn. + */ + sanitize_stdfds(); + + git_setup_gettext(); + + argv[0] = git_extract_argv0_path(argv[0]); + + restore_sigpipe_to_default(); + + return cmd_main(argc, argv); +} diff --git a/compat/mingw.h b/compat/mingw.h index 9a8803b876..233933ee86 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -535,7 +535,7 @@ extern CRITICAL_SECTION pinfo_cs; void mingw_startup(void); #define main(c,v) dummy_decl_mingw_main(void); \ static int mingw_main(c,v); \ -int main(int argc, char **argv) \ +int main(int argc, const char **argv) \ { \ mingw_startup(); \ return mingw_main(__argc, (void *)__argv); \ @@ -658,6 +658,19 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host, static struct child_process no_fork = CHILD_PROCESS_INIT; +static const char *get_ssh_command(void) +{ + const char *ssh; + + if ((ssh = getenv("GIT_SSH_COMMAND"))) + return ssh; + + if (!git_config_get_string_const("core.sshcommand", &ssh)) + return ssh; + + return NULL; +} + /* * This returns a dummy child_process if the transport protocol does not * need fork(2), or a struct child_process object if it does. Once done, @@ -758,7 +771,7 @@ struct child_process *git_connect(int fd[2], const char *url, return NULL; } - ssh = getenv("GIT_SSH_COMMAND"); + ssh = get_ssh_command(); if (!ssh) { const char *base; char *ssh_dup; diff --git a/contrib/coccinelle/README b/contrib/coccinelle/README new file mode 100644 index 0000000000..9c2f8879c2 --- /dev/null +++ b/contrib/coccinelle/README @@ -0,0 +1,2 @@ +This directory provides examples of Coccinelle (http://coccinelle.lip6.fr/) +semantic patches that might be useful to developers. diff --git a/contrib/coccinelle/object_id.cocci b/contrib/coccinelle/object_id.cocci new file mode 100644 index 0000000000..8ccdbb5666 --- /dev/null +++ b/contrib/coccinelle/object_id.cocci @@ -0,0 +1,95 @@ +@@ +expression E1; +@@ +- is_null_sha1(E1.hash) ++ is_null_oid(&E1) + +@@ +expression E1; +@@ +- is_null_sha1(E1->hash) ++ is_null_oid(E1) + +@@ +expression E1; +@@ +- sha1_to_hex(E1.hash) ++ oid_to_hex(&E1) + +@@ +expression E1; +@@ +- sha1_to_hex(E1->hash) ++ oid_to_hex(E1) + +@@ +expression E1; +@@ +- sha1_to_hex_r(E1.hash) ++ oid_to_hex_r(&E1) + +@@ +expression E1; +@@ +- sha1_to_hex_r(E1->hash) ++ oid_to_hex_r(E1) + +@@ +expression E1; +@@ +- hashclr(E1.hash) ++ oidclr(&E1) + +@@ +expression E1; +@@ +- hashclr(E1->hash) ++ oidclr(E1) + +@@ +expression E1, E2; +@@ +- hashcmp(E1.hash, E2.hash) ++ oidcmp(&E1, &E2) + +@@ +expression E1, E2; +@@ +- hashcmp(E1->hash, E2->hash) ++ oidcmp(E1, E2) + +@@ +expression E1, E2; +@@ +- hashcmp(E1->hash, E2.hash) ++ oidcmp(E1, &E2) + +@@ +expression E1, E2; +@@ +- hashcmp(E1.hash, E2->hash) ++ oidcmp(&E1, E2) + +@@ +expression E1, E2; +@@ +- hashcpy(E1.hash, E2.hash) ++ oidcpy(&E1, &E2) + +@@ +expression E1, E2; +@@ +- hashcpy(E1->hash, E2->hash) ++ oidcpy(E1, E2) + +@@ +expression E1, E2; +@@ +- hashcpy(E1->hash, E2.hash) ++ oidcpy(E1, &E2) + +@@ +expression E1, E2; +@@ +- hashcpy(E1.hash, E2->hash) ++ oidcpy(&E1, E2) diff --git a/credential-cache--daemon.c b/credential-cache--daemon.c index 1f14d56e98..1e5f16a3a1 100644 --- a/credential-cache--daemon.c +++ b/credential-cache--daemon.c @@ -257,7 +257,7 @@ static void init_socket_directory(const char *path) free(path_copy); } -int main(int argc, const char **argv) +int cmd_main(int argc, const char **argv) { const char *socket_path; int ignore_sighup = 0; diff --git a/credential-cache.c b/credential-cache.c index 86e21de49b..cc8a6ee192 100644 --- a/credential-cache.c +++ b/credential-cache.c @@ -83,7 +83,7 @@ static void do_cache(const char *socket, const char *action, int timeout, strbuf_release(&buf); } -int main(int argc, const char **argv) +int cmd_main(int argc, const char **argv) { char *socket_path = NULL; int timeout = 900; diff --git a/credential-store.c b/credential-store.c index 57141679ab..55ca1b1334 100644 --- a/credential-store.c +++ b/credential-store.c @@ -142,7 +142,7 @@ static void lookup_credential(const struct string_list *fns, struct credential * return; /* Found credential */ } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { const char * const usage[] = { "git credential-store [<options>] <action>", @@ -1,6 +1,5 @@ #include "cache.h" #include "pkt-line.h" -#include "exec_cmd.h" #include "run-command.h" #include "strbuf.h" #include "string-list.h" @@ -32,7 +31,7 @@ static const char daemon_usage[] = " [<directory>...]"; /* List of acceptable pathname prefixes */ -static char **ok_paths; +static const char **ok_paths; static int strict_paths; /* If this is set, git-daemon-export-ok is not required */ @@ -240,7 +239,7 @@ static const char *path_ok(const char *directory, struct hostinfo *hi) } if ( ok_paths && *ok_paths ) { - char **pp; + const char **pp; int pathlen = strlen(path); /* The validation is done on the paths after enter_repo @@ -1192,7 +1191,7 @@ static int serve(struct string_list *listen_addr, int listen_port, return service_loop(&socklist); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { int listen_port = 0; struct string_list listen_addr = STRING_LIST_INIT_NODUP; @@ -1202,12 +1201,8 @@ int main(int argc, char **argv) struct credentials *cred = NULL; int i; - git_setup_gettext(); - - git_extract_argv0_path(argv[0]); - for (i = 1; i < argc; i++) { - char *arg = argv[i]; + const char *arg = argv[i]; const char *v; if (skip_prefix(arg, "--listen=", &v)) { @@ -1381,8 +1376,7 @@ int main(int argc, char **argv) if (detach) { if (daemonize()) die("--detach not supported on this platform"); - } else - sanitize_stdfds(); + } if (pid_file) write_file(pid_file, "%"PRIuMAX, (uintmax_t) getpid()); @@ -1933,8 +1933,8 @@ static void show_dirstat(struct diff_options *options) name = p->two->path ? p->two->path : p->one->path; - if (p->one->sha1_valid && p->two->sha1_valid) - content_changed = hashcmp(p->one->sha1, p->two->sha1); + if (p->one->oid_valid && p->two->oid_valid) + content_changed = oidcmp(&p->one->oid, &p->two->oid); else content_changed = 1; @@ -2306,7 +2306,8 @@ static void builtin_diff(const char *name_a, const char *add = diff_get_color_opt(o, DIFF_FILE_NEW); show_submodule_summary(o->file, one->path ? one->path : two->path, line_prefix, - one->sha1, two->sha1, two->dirty_submodule, + one->oid.hash, two->oid.hash, + two->dirty_submodule, meta, del, add, reset); return; } @@ -2384,7 +2385,7 @@ static void builtin_diff(const char *name_a, if (!one->data && !two->data && S_ISREG(one->mode) && S_ISREG(two->mode) && !DIFF_OPT_TST(o, BINARY)) { - if (!hashcmp(one->sha1, two->sha1)) { + if (!oidcmp(&one->oid, &two->oid)) { if (must_show_header) fprintf(o->file, "%s", header.buf); goto free_ab_and_return; @@ -2505,7 +2506,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b, return; } - same_contents = !hashcmp(one->sha1, two->sha1); + same_contents = !oidcmp(&one->oid, &two->oid); if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) { data->is_binary = 1; @@ -2638,8 +2639,8 @@ void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1, { if (mode) { spec->mode = canon_mode(mode); - hashcpy(spec->sha1, sha1); - spec->sha1_valid = sha1_valid; + hashcpy(spec->oid.hash, sha1); + spec->oid_valid = sha1_valid; } } @@ -2721,7 +2722,8 @@ static int diff_populate_gitlink(struct diff_filespec *s, int size_only) if (s->dirty_submodule) dirty = "-dirty"; - strbuf_addf(&buf, "Subproject commit %s%s\n", sha1_to_hex(s->sha1), dirty); + strbuf_addf(&buf, "Subproject commit %s%s\n", + oid_to_hex(&s->oid), dirty); s->size = buf.len; if (size_only) { s->data = NULL; @@ -2764,8 +2766,8 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags) if (S_ISGITLINK(s->mode)) return diff_populate_gitlink(s, size_only); - if (!s->sha1_valid || - reuse_worktree_file(s->path, s->sha1, 0)) { + if (!s->oid_valid || + reuse_worktree_file(s->path, s->oid.hash, 0)) { struct strbuf buf = STRBUF_INIT; struct stat st; int fd; @@ -2822,9 +2824,10 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags) else { enum object_type type; if (size_only || (flags & CHECK_BINARY)) { - type = sha1_object_info(s->sha1, &s->size); + type = sha1_object_info(s->oid.hash, &s->size); if (type < 0) - die("unable to read %s", sha1_to_hex(s->sha1)); + die("unable to read %s", + oid_to_hex(&s->oid)); if (size_only) return 0; if (s->size > big_file_threshold && s->is_binary == -1) { @@ -2832,9 +2835,9 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags) return 0; } } - s->data = read_sha1_file(s->sha1, &type, &s->size); + s->data = read_sha1_file(s->oid.hash, &type, &s->size); if (!s->data) - die("unable to read %s", sha1_to_hex(s->sha1)); + die("unable to read %s", oid_to_hex(&s->oid)); s->should_free = 1; } return 0; @@ -2863,7 +2866,7 @@ void diff_free_filespec_data(struct diff_filespec *s) static void prep_temp_blob(const char *path, struct diff_tempfile *temp, void *blob, unsigned long size, - const unsigned char *sha1, + const struct object_id *oid, int mode) { int fd; @@ -2888,7 +2891,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp, die_errno("unable to write temp-file"); close_tempfile(&temp->tempfile); temp->name = get_tempfile_path(&temp->tempfile); - sha1_to_hex_r(temp->hex, sha1); + oid_to_hex_r(temp->hex, oid); xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode); strbuf_release(&buf); strbuf_release(&template); @@ -2912,8 +2915,8 @@ static struct diff_tempfile *prepare_temp_file(const char *name, } if (!S_ISGITLINK(one->mode) && - (!one->sha1_valid || - reuse_worktree_file(name, one->sha1, 1))) { + (!one->oid_valid || + reuse_worktree_file(name, one->oid.hash, 1))) { struct stat st; if (lstat(name, &st) < 0) { if (errno == ENOENT) @@ -2925,19 +2928,19 @@ static struct diff_tempfile *prepare_temp_file(const char *name, if (strbuf_readlink(&sb, name, st.st_size) < 0) die_errno("readlink(%s)", name); prep_temp_blob(name, temp, sb.buf, sb.len, - (one->sha1_valid ? - one->sha1 : null_sha1), - (one->sha1_valid ? + (one->oid_valid ? + &one->oid : &null_oid), + (one->oid_valid ? one->mode : S_IFLNK)); strbuf_release(&sb); } else { /* we can borrow from the file in the work tree */ temp->name = name; - if (!one->sha1_valid) + if (!one->oid_valid) sha1_to_hex_r(temp->hex, null_sha1); else - sha1_to_hex_r(temp->hex, one->sha1); + sha1_to_hex_r(temp->hex, one->oid.hash); /* Even though we may sometimes borrow the * contents from the work tree, we always want * one->mode. mode is trustworthy even when @@ -2952,7 +2955,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name, if (diff_populate_filespec(one, 0)) die("cannot read data blob for %s", one->path); prep_temp_blob(name, temp, one->data, one->size, - one->sha1, one->mode); + &one->oid, one->mode); } return temp; } @@ -3065,7 +3068,7 @@ static void fill_metainfo(struct strbuf *msg, default: *must_show_header = 0; } - if (one && two && hashcmp(one->sha1, two->sha1)) { + if (one && two && oidcmp(&one->oid, &two->oid)) { int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV; if (DIFF_OPT_TST(o, BINARY)) { @@ -3075,8 +3078,8 @@ static void fill_metainfo(struct strbuf *msg, abbrev = 40; } strbuf_addf(msg, "%s%sindex %s..", line_prefix, set, - find_unique_abbrev(one->sha1, abbrev)); - strbuf_addstr(msg, find_unique_abbrev(two->sha1, abbrev)); + find_unique_abbrev(one->oid.hash, abbrev)); + strbuf_addstr(msg, find_unique_abbrev(two->oid.hash, abbrev)); if (one->mode == two->mode) strbuf_addf(msg, " %06o", one->mode); strbuf_addf(msg, "%s\n", reset); @@ -3131,20 +3134,20 @@ static void run_diff_cmd(const char *pgm, static void diff_fill_sha1_info(struct diff_filespec *one) { if (DIFF_FILE_VALID(one)) { - if (!one->sha1_valid) { + if (!one->oid_valid) { struct stat st; if (one->is_stdin) { - hashcpy(one->sha1, null_sha1); + oidclr(&one->oid); return; } if (lstat(one->path, &st) < 0) die_errno("stat '%s'", one->path); - if (index_path(one->sha1, one->path, &st, 0)) + if (index_path(one->oid.hash, one->path, &st, 0)) die("cannot hash %s", one->path); } } else - hashclr(one->sha1); + oidclr(&one->oid); } static void strip_prefix(int prefix_length, const char **namep, const char **otherp) @@ -3977,6 +3980,8 @@ int diff_opt_parse(struct diff_options *options, if (!options->file) die_errno("Could not open '%s'", path); options->close_file = 1; + if (options->use_color != GIT_COLOR_ALWAYS) + options->use_color = GIT_COLOR_NEVER; return argcount; } else return 0; @@ -4118,8 +4123,9 @@ static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt) fprintf(opt->file, "%s", diff_line_prefix(opt)); if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) { fprintf(opt->file, ":%06o %06o %s ", p->one->mode, p->two->mode, - diff_unique_abbrev(p->one->sha1, opt->abbrev)); - fprintf(opt->file, "%s ", diff_unique_abbrev(p->two->sha1, opt->abbrev)); + diff_unique_abbrev(p->one->oid.hash, opt->abbrev)); + fprintf(opt->file, "%s ", + diff_unique_abbrev(p->two->oid.hash, opt->abbrev)); } if (p->score) { fprintf(opt->file, "%c%03d%c", p->status, similarity_index(p), @@ -4168,11 +4174,11 @@ int diff_unmodified_pair(struct diff_filepair *p) /* both are valid and point at the same path. that is, we are * dealing with a change. */ - if (one->sha1_valid && two->sha1_valid && - !hashcmp(one->sha1, two->sha1) && + if (one->oid_valid && two->oid_valid && + !oidcmp(&one->oid, &two->oid) && !one->dirty_submodule && !two->dirty_submodule) return 1; /* no change */ - if (!one->sha1_valid && !two->sha1_valid) + if (!one->oid_valid && !two->oid_valid) return 1; /* both look at the same file on the filesystem. */ return 0; } @@ -4233,7 +4239,7 @@ void diff_debug_filespec(struct diff_filespec *s, int x, const char *one) s->path, DIFF_FILE_VALID(s) ? "valid" : "invalid", s->mode, - s->sha1_valid ? sha1_to_hex(s->sha1) : ""); + s->oid_valid ? oid_to_hex(&s->oid) : ""); fprintf(stderr, "queue[%d] %s size %lu\n", x, one ? one : "", s->size); @@ -4303,11 +4309,11 @@ static void diff_resolve_rename_copy(void) else p->status = DIFF_STATUS_RENAMED; } - else if (hashcmp(p->one->sha1, p->two->sha1) || + else if (oidcmp(&p->one->oid, &p->two->oid) || p->one->mode != p->two->mode || p->one->dirty_submodule || p->two->dirty_submodule || - is_null_sha1(p->one->sha1)) + is_null_oid(&p->one->oid)) p->status = DIFF_STATUS_MODIFIED; else { /* This is a "no-change" entry and should not @@ -4523,8 +4529,10 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) if (diff_filespec_is_binary(p->one) || diff_filespec_is_binary(p->two)) { - git_SHA1_Update(&ctx, sha1_to_hex(p->one->sha1), 40); - git_SHA1_Update(&ctx, sha1_to_hex(p->two->sha1), 40); + git_SHA1_Update(&ctx, oid_to_hex(&p->one->oid), + 40); + git_SHA1_Update(&ctx, oid_to_hex(&p->two->oid), + 40); continue; } @@ -4816,7 +4824,7 @@ static int diff_filespec_check_stat_unmatch(struct diff_filepair *p) */ if (!DIFF_FILE_VALID(p->one) || /* (1) */ !DIFF_FILE_VALID(p->two) || - (p->one->sha1_valid && p->two->sha1_valid) || + (p->one->oid_valid && p->two->oid_valid) || (p->one->mode != p->two->mode) || diff_populate_filespec(p->one, CHECK_SIZE_ONLY) || diff_populate_filespec(p->two, CHECK_SIZE_ONLY) || @@ -5112,8 +5120,9 @@ size_t fill_textconv(struct userdiff_driver *driver, if (!driver->textconv) die("BUG: fill_textconv called with non-textconv driver"); - if (driver->textconv_cache && df->sha1_valid) { - *outbuf = notes_cache_get(driver->textconv_cache, df->sha1, + if (driver->textconv_cache && df->oid_valid) { + *outbuf = notes_cache_get(driver->textconv_cache, + df->oid.hash, &size); if (*outbuf) return size; @@ -5123,9 +5132,9 @@ size_t fill_textconv(struct userdiff_driver *driver, if (!*outbuf) die("unable to read files to diff"); - if (driver->textconv_cache && df->sha1_valid) { + if (driver->textconv_cache && df->oid_valid) { /* ignore errors, as we might be in a readonly repository */ - notes_cache_put(driver->textconv_cache, df->sha1, *outbuf, + notes_cache_put(driver->textconv_cache, df->oid.hash, *outbuf, size); /* * we could save up changes and flush them all at the end, diff --git a/diffcore-break.c b/diffcore-break.c index 5473493e10..881a74f29e 100644 --- a/diffcore-break.c +++ b/diffcore-break.c @@ -57,8 +57,8 @@ static int should_break(struct diff_filespec *src, return 1; /* even their types are different */ } - if (src->sha1_valid && dst->sha1_valid && - !hashcmp(src->sha1, dst->sha1)) + if (src->oid_valid && dst->oid_valid && + !oidcmp(&src->oid, &dst->oid)) return 0; /* they are the same */ if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0)) diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c index 7715c13ec4..55067cab6c 100644 --- a/diffcore-pickaxe.c +++ b/diffcore-pickaxe.c @@ -7,6 +7,8 @@ #include "diffcore.h" #include "xdiff-interface.h" #include "kwset.h" +#include "commit.h" +#include "quote.h" typedef int (*pickaxe_fn)(mmfile_t *one, mmfile_t *two, struct diff_options *o, @@ -198,6 +200,18 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o, *q = outq; } +static void regcomp_or_die(regex_t *regex, const char *needle, int cflags) +{ + int err = regcomp(regex, needle, cflags); + if (err) { + /* The POSIX.2 people are surely sick */ + char errbuf[1024]; + regerror(err, regex, errbuf, 1024); + regfree(regex); + die("invalid regex: %s", errbuf); + } +} + void diffcore_pickaxe(struct diff_options *o) { const char *needle = o->pickaxe; @@ -206,18 +220,19 @@ void diffcore_pickaxe(struct diff_options *o) kwset_t kws = NULL; if (opts & (DIFF_PICKAXE_REGEX | DIFF_PICKAXE_KIND_G)) { - int err; int cflags = REG_EXTENDED | REG_NEWLINE; if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)) cflags |= REG_ICASE; - err = regcomp(®ex, needle, cflags); - if (err) { - /* The POSIX.2 people are surely sick */ - char errbuf[1024]; - regerror(err, ®ex, errbuf, 1024); - regfree(®ex); - die("invalid regex: %s", errbuf); - } + regcomp_or_die(®ex, needle, cflags); + regexp = ®ex; + } else if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE) && + has_non_ascii(needle)) { + struct strbuf sb = STRBUF_INIT; + int cflags = REG_NEWLINE | REG_ICASE; + + basic_regex_quote_buf(&sb, needle); + regcomp_or_die(®ex, sb.buf, cflags); + strbuf_release(&sb); regexp = ®ex; } else { kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE) diff --git a/diffcore-rename.c b/diffcore-rename.c index 7f03eb5a04..58ac0a531b 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -60,7 +60,8 @@ static int add_rename_dst(struct diff_filespec *two) memmove(rename_dst + first + 1, rename_dst + first, (rename_dst_nr - first - 1) * sizeof(*rename_dst)); rename_dst[first].two = alloc_filespec(two->path); - fill_filespec(rename_dst[first].two, two->sha1, two->sha1_valid, two->mode); + fill_filespec(rename_dst[first].two, two->oid.hash, two->oid_valid, + two->mode); rename_dst[first].pair = NULL; return 0; } @@ -260,12 +261,13 @@ struct file_similarity { static unsigned int hash_filespec(struct diff_filespec *filespec) { - if (!filespec->sha1_valid) { + if (!filespec->oid_valid) { if (diff_populate_filespec(filespec, 0)) return 0; - hash_sha1_file(filespec->data, filespec->size, "blob", filespec->sha1); + hash_sha1_file(filespec->data, filespec->size, "blob", + filespec->oid.hash); } - return sha1hash(filespec->sha1); + return sha1hash(filespec->oid.hash); } static int find_identical_files(struct hashmap *srcs, @@ -287,7 +289,7 @@ static int find_identical_files(struct hashmap *srcs, struct diff_filespec *source = p->filespec; /* False hash collision? */ - if (hashcmp(source->sha1, target->sha1)) + if (oidcmp(&source->oid, &target->oid)) continue; /* Non-regular files? If so, the modes must match! */ if (!S_ISREG(source->mode) || !S_ISREG(target->mode)) { @@ -466,7 +468,7 @@ void diffcore_rename(struct diff_options *options) strcmp(options->single_follow, p->two->path)) continue; /* not interested */ else if (!DIFF_OPT_TST(options, RENAME_EMPTY) && - is_empty_blob_sha1(p->two->sha1)) + is_empty_blob_sha1(p->two->oid.hash)) continue; else if (add_rename_dst(p->two) < 0) { warning("skipping rename detection, detected" @@ -476,7 +478,7 @@ void diffcore_rename(struct diff_options *options) } } else if (!DIFF_OPT_TST(options, RENAME_EMPTY) && - is_empty_blob_sha1(p->one->sha1)) + is_empty_blob_sha1(p->one->oid.hash)) continue; else if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) { /* diff --git a/diffcore.h b/diffcore.h index 33ea2de348..c11b8465fc 100644 --- a/diffcore.h +++ b/diffcore.h @@ -25,7 +25,7 @@ struct userdiff_driver; struct diff_filespec { - unsigned char sha1[20]; + struct object_id oid; char *path; void *data; void *cnt_data; @@ -33,7 +33,7 @@ struct diff_filespec { int count; /* Reference count */ int rename_used; /* Count of rename users */ unsigned short mode; /* file mode */ - unsigned sha1_valid : 1; /* if true, use sha1 and trust mode; + unsigned oid_valid : 1; /* if true, use oid and trust mode; * if false, use the name and read from * the filesystem. */ diff --git a/fast-import.c b/fast-import.c index 59630cee14..bf53ac95da 100644 --- a/fast-import.c +++ b/fast-import.c @@ -164,7 +164,6 @@ Format of STDIN stream: #include "refs.h" #include "csum-file.h" #include "quote.h" -#include "exec_cmd.h" #include "dir.h" #include "run-command.h" @@ -302,7 +301,7 @@ static int failure; static FILE *pack_edges; static unsigned int show_stats = 1; static int global_argc; -static char **global_argv; +static const char **global_argv; /* Memory pools */ static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool); @@ -3445,14 +3444,10 @@ static void parse_argv(void) read_marks(); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { unsigned int i; - git_extract_argv0_path(argv[0]); - - git_setup_gettext(); - if (argc == 2 && !strcmp(argv[1], "-h")) usage(fast_import_usage); @@ -18,6 +18,8 @@ # endif #endif +static const char *charset; + /* * Guess the user's preferred languages from the value in LANGUAGE environment * variable and LC_MESSAGES locale category if NO_GETTEXT is not defined. @@ -65,7 +67,6 @@ static int test_vsnprintf(const char *fmt, ...) return ret; } -static const char *charset; static void init_gettext_charset(const char *domain) { /* @@ -172,8 +173,27 @@ int gettext_width(const char *s) { static int is_utf8 = -1; if (is_utf8 == -1) - is_utf8 = !strcmp(charset, "UTF-8"); + is_utf8 = is_utf8_locale(); return is_utf8 ? utf8_strwidth(s) : strlen(s); } #endif + +int is_utf8_locale(void) +{ +#ifdef NO_GETTEXT + if (!charset) { + const char *env = getenv("LC_ALL"); + if (!env || !*env) + env = getenv("LC_CTYPE"); + if (!env || !*env) + env = getenv("LANG"); + if (!env) + env = ""; + if (strchr(env, '.')) + env = strchr(env, '.') + 1; + charset = xstrdup(env); + } +#endif + return is_encoding_utf8(charset); +} @@ -90,5 +90,6 @@ const char *Q_(const char *msgid, const char *plu, unsigned long n) #endif const char *get_preferred_languages(void); +extern int is_utf8_locale(void); #endif diff --git a/git-bisect.sh b/git-bisect.sh index 5d1cb00d86..ae3cb013e7 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -33,7 +33,6 @@ Please use "git help bisect" to get the full man page.' OPTIONS_SPEC= . git-sh-setup -. git-sh-i18n _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" @@ -275,10 +274,11 @@ bisect_state() { check_and_set_terms $state case "$#,$state" in 0,*) - die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;; + die "Please call 'bisect_state' with at least one argument." ;; 1,"$TERM_BAD"|1,"$TERM_GOOD"|1,skip) - rev=$(git rev-parse --verify $(bisect_head)) || - die "$(gettext "Bad rev input: $(bisect_head)")" + bisected_head=$(bisect_head) + rev=$(git rev-parse --verify "$bisected_head") || + die "$(eval_gettext "Bad rev input: \$bisected_head")" bisect_write "$state" "$rev" check_expected_revs "$rev" ;; 2,"$TERM_BAD"|*,"$TERM_GOOD"|*,skip) diff --git a/git-compat-util.h b/git-compat-util.h index 49d4029b8d..590bfddf73 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -474,6 +474,23 @@ static inline int skip_prefix(const char *str, const char *prefix, } /* + * Like skip_prefix, but promises never to read past "len" bytes of the input + * buffer, and returns the remaining number of bytes in "out" via "outlen". + */ +static inline int skip_prefix_mem(const char *buf, size_t len, + const char *prefix, + const char **out, size_t *outlen) +{ + size_t prefix_len = strlen(prefix); + if (prefix_len <= len && !memcmp(buf, prefix, prefix_len)) { + *out = buf + prefix_len; + *outlen = len - prefix_len; + return 1; + } + return 0; +} + +/* * If buf ends with suffix, return 1 and subtract the length of the suffix * from *len. Otherwise, return 0 and leave *len untouched. */ @@ -1045,3 +1062,5 @@ struct tm *git_gmtime_r(const time_t *, struct tm *); #endif #endif + +extern int cmd_main(int, const char **); diff --git a/git-merge-octopus.sh b/git-merge-octopus.sh index dc2fd1b5a4..308eafd1d3 100755 --- a/git-merge-octopus.sh +++ b/git-merge-octopus.sh @@ -5,14 +5,11 @@ # Resolve two or more trees. # +. git-sh-setup + LF=' ' -die () { - echo >&2 "$*" - exit 1 -} - # The first parameters up to -- are merge bases; the rest are heads. bases= head= remotes= sep_seen= for arg @@ -46,7 +43,7 @@ esac if ! git diff-index --quiet --cached HEAD -- then - echo "Error: Your local changes to the following files would be overwritten by merge" + gettextln "Error: Your local changes to the following files would be overwritten by merge" git diff-index --cached --name-only HEAD -- | sed -e 's/^/ /' exit 2 fi @@ -61,8 +58,8 @@ do # We allow only last one to have a hand-resolvable # conflicts. Last round failed and we still had # a head to merge. - echo "Automated merge did not work." - echo "Should not be doing an Octopus." + gettextln "Automated merge did not work." + gettextln "Should not be doing an Octopus." exit 2 esac @@ -73,11 +70,11 @@ do eval pretty_name=\${GITHEAD_$SHA1_UP:-$pretty_name} fi common=$(git merge-base --all $SHA1 $MRC) || - die "Unable to find common commit with $pretty_name" + die "$(eval_gettext "Unable to find common commit with \$pretty_name")" case "$LF$common$LF" in *"$LF$SHA1$LF"*) - echo "Already up-to-date with $pretty_name" + eval_gettextln "Already up-to-date with \$pretty_name" continue ;; esac @@ -89,7 +86,7 @@ do # tree as the intermediate result of the merge. # We still need to count this as part of the parent set. - echo "Fast-forwarding to: $pretty_name" + eval_gettextln "Fast-forwarding to: \$pretty_name" git read-tree -u -m $head $SHA1 || exit MRC=$SHA1 MRT=$(git write-tree) continue @@ -97,12 +94,12 @@ do NON_FF_MERGE=1 - echo "Trying simple merge with $pretty_name" + eval_gettextln "Trying simple merge with \$pretty_name" git read-tree -u -m --aggressive $common $MRT $SHA1 || exit 2 next=$(git write-tree 2>/dev/null) if test $? -ne 0 then - echo "Simple merge did not work, trying automatic merge." + gettextln "Simple merge did not work, trying automatic merge." git-merge-index -o git-merge-one-file -a || OCTOPUS_FAILURE=1 next=$(git write-tree 2>/dev/null) diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 05f22e43cc..ded4595638 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -128,7 +128,7 @@ mark_action_done () { if test "$last_count" != "$new_count" then last_count=$new_count - printf "Rebasing (%d/%d)\r" $new_count $total + eval_gettext "Rebasing (\$new_count/\$total)"; printf "\r" test -z "$verbose" || echo fi } @@ -144,29 +144,28 @@ reschedule_last_action () { } append_todo_help () { - git stripspace --comment-lines >>"$todo" <<\EOF - + gettext " Commands: p, pick = use commit r, reword = use commit, but edit the commit message e, edit = use commit, but stop for amending s, squash = use commit, but meld into previous commit - f, fixup = like "squash", but discard this commit's log message + f, fixup = like \"squash\", but discard this commit's log message x, exec = run command (the rest of the line) using shell d, drop = remove commit These lines can be re-ordered; they are executed from top to bottom. +" | git stripspace --comment-lines >>"$todo" -EOF if test $(get_missing_commit_check_level) = error then - git stripspace --comment-lines >>"$todo" <<\EOF + gettext " Do not remove any line. Use 'drop' explicitly to remove a commit. -EOF +" | git stripspace --comment-lines >>"$todo" else - git stripspace --comment-lines >>"$todo" <<\EOF + gettext " If you remove a line here THAT COMMIT WILL BE LOST. -EOF +" | git stripspace --comment-lines >>"$todo" fi } @@ -200,18 +199,20 @@ exit_with_patch () { make_patch $1 git rev-parse --verify HEAD > "$amend" gpg_sign_opt_quoted=${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} - warn "You can amend the commit now, with" - warn - warn " git commit --amend $gpg_sign_opt_quoted" - warn - warn "Once you are satisfied with your changes, run" - warn - warn " git rebase --continue" + warn "$(eval_gettext "\ +You can amend the commit now, with + + git commit --amend \$gpg_sign_opt_quoted + +Once you are satisfied with your changes, run + + git rebase --continue")" warn exit $2 } die_abort () { + apply_autostash rm -rf "$state_dir" die "$1" } @@ -221,10 +222,12 @@ has_action () { } is_empty_commit() { - tree=$(git rev-parse -q --verify "$1"^{tree} 2>/dev/null || - die "$1: not a commit that can be picked") - ptree=$(git rev-parse -q --verify "$1"^^{tree} 2>/dev/null || - ptree=4b825dc642cb6eb9a060e54bf8d69288fbee4904) + tree=$(git rev-parse -q --verify "$1"^{tree} 2>/dev/null) || { + sha1=$1 + die "$(eval_gettext "\$sha1: not a commit that can be picked")" + } + ptree=$(git rev-parse -q --verify "$1"^^{tree} 2>/dev/null) || + ptree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 test "$tree" = "$ptree" } @@ -260,7 +263,7 @@ pick_one () { case "$1" in -n) sha1=$2; ff= ;; *) sha1=$1 ;; esac case "$force_rebase" in '') ;; ?*) ff= ;; esac - output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1" + output git rev-parse --verify $sha1 || die "$(eval_gettext "Invalid commit name: \$sha1")" if is_empty_commit "$sha1" then @@ -302,7 +305,7 @@ pick_one_preserving_merges () { git rev-parse HEAD > "$rewritten"/$current_commit done <"$state_dir"/current-commit rm "$state_dir"/current-commit || - die "Cannot write current commit's replacement sha1" + die "$(gettext "Cannot write current commit's replacement sha1")" fi fi @@ -354,9 +357,9 @@ pick_one_preserving_merges () { done case $fast_forward in t) - output warn "Fast-forward to $sha1" + output warn "$(eval_gettext "Fast-forward to \$sha1")" output git reset --hard $sha1 || - die "Cannot fast-forward to $sha1" + die "$(eval_gettext "Cannot fast-forward to \$sha1")" ;; f) first_parent=$(expr "$new_parents" : ' \([^ ]*\)') @@ -365,12 +368,12 @@ pick_one_preserving_merges () { then # detach HEAD to current parent output git checkout $first_parent 2> /dev/null || - die "Cannot move HEAD to $first_parent" + die "$(eval_gettext "Cannot move HEAD to \$first_parent")" fi case "$new_parents" in ' '*' '*) - test "a$1" = a-n && die "Refusing to squash a merge: $sha1" + test "a$1" = a-n && die "$(eval_gettext "Refusing to squash a merge: \$sha1")" # redo merge author_script_content=$(get_author_ident_from_commit $sha1) @@ -384,7 +387,7 @@ pick_one_preserving_merges () { $merge_args $strategy_args -m "$msg_content" $new_parents' then printf "%s\n" "$msg_content" > "$GIT_DIR"/MERGE_MSG - die_with_patch $sha1 "Error redoing merge $sha1" + die_with_patch $sha1 "$(eval_gettext "Error redoing merge \$sha1")" fi echo "$sha1 $(git rev-parse HEAD^0)" >> "$rewritten_list" ;; @@ -392,19 +395,59 @@ pick_one_preserving_merges () { output eval git cherry-pick \ ${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \ "$strategy_args" "$@" || - die_with_patch $sha1 "Could not pick $sha1" + die_with_patch $sha1 "$(eval_gettext "Could not pick \$sha1")" ;; esac ;; esac } -nth_string () { - case "$1" in - *1[0-9]|*[04-9]) echo "$1"th;; - *1) echo "$1"st;; - *2) echo "$1"nd;; - *3) echo "$1"rd;; +this_nth_commit_message () { + n=$1 + case "$n" in + 1) gettext "This is the 1st commit message:";; + 2) gettext "This is the 2nd commit message:";; + 3) gettext "This is the 3rd commit message:";; + 4) gettext "This is the 4th commit message:";; + 5) gettext "This is the 5th commit message:";; + 6) gettext "This is the 6th commit message:";; + 7) gettext "This is the 7th commit message:";; + 8) gettext "This is the 8th commit message:";; + 9) gettext "This is the 9th commit message:";; + 10) gettext "This is the 10th commit message:";; + # TRANSLATORS: if the language you are translating into + # doesn't allow you to compose a sentence in this fashion, + # consider translating as if this and the following few strings + # were "This is the commit message ${n}:" + *1[0-9]|*[04-9]) eval_gettext "This is the \${n}th commit message:";; + *1) eval_gettext "This is the \${n}st commit message:";; + *2) eval_gettext "This is the \${n}nd commit message:";; + *3) eval_gettext "This is the \${n}rd commit message:";; + *) eval_gettext "This is the commit message \${n}:";; + esac +} +skip_nth_commit_message () { + n=$1 + case "$n" in + 1) gettext "The 1st commit message will be skipped:";; + 2) gettext "The 2nd commit message will be skipped:";; + 3) gettext "The 3rd commit message will be skipped:";; + 4) gettext "The 4th commit message will be skipped:";; + 5) gettext "The 5th commit message will be skipped:";; + 6) gettext "The 6th commit message will be skipped:";; + 7) gettext "The 7th commit message will be skipped:";; + 8) gettext "The 8th commit message will be skipped:";; + 9) gettext "The 9th commit message will be skipped:";; + 10) gettext "The 10th commit message will be skipped:";; + # TRANSLATORS: if the language you are translating into + # doesn't allow you to compose a sentence in this fashion, + # consider translating as if this and the following few strings + # were "The commit message ${n} will be skipped:" + *1[0-9]|*[04-9]) eval_gettext "The \${n}th commit message will be skipped:";; + *1) eval_gettext "The \${n}st commit message will be skipped:";; + *2) eval_gettext "The \${n}nd commit message will be skipped:";; + *3) eval_gettext "The \${n}rd commit message will be skipped:";; + *) eval_gettext "The commit message \${n} will be skipped:";; esac } @@ -412,20 +455,23 @@ update_squash_messages () { if test -f "$squash_msg"; then mv "$squash_msg" "$squash_msg".bak || exit count=$(($(sed -n \ - -e "1s/^. This is a combination of \(.*\) commits\./\1/p" \ + -e "1s/^$comment_char.*\([0-9][0-9]*\).*/\1/p" \ -e "q" < "$squash_msg".bak)+1)) { - printf '%s\n' "$comment_char This is a combination of $count commits." + printf '%s\n' "$comment_char $(eval_ngettext \ + "This is a combination of \$count commit." \ + "This is a combination of \$count commits." \ + $count)" sed -e 1d -e '2,/^./{ /^$/d }' <"$squash_msg".bak } >"$squash_msg" else - commit_message HEAD > "$fixup_msg" || die "Cannot write $fixup_msg" + commit_message HEAD > "$fixup_msg" || die "$(gettext "Cannot write \$fixup_msg")" count=2 { - printf '%s\n' "$comment_char This is a combination of 2 commits." - printf '%s\n' "$comment_char The first commit's message is:" + printf '%s\n' "$comment_char $(gettext "This is a combination of 2 commits.")" + printf '%s\n' "$comment_char $(gettext "This is the 1st commit message:")" echo cat "$fixup_msg" } >"$squash_msg" @@ -434,13 +480,13 @@ update_squash_messages () { squash) rm -f "$fixup_msg" echo - printf '%s\n' "$comment_char This is the $(nth_string $count) commit message:" + printf '%s\n' "$comment_char $(this_nth_commit_message $count)" echo commit_message $2 ;; fixup) echo - printf '%s\n' "$comment_char The $(nth_string $count) commit message will be skipped:" + printf '%s\n' "$comment_char $(skip_nth_commit_message $count)" echo # Change the space after the comment character to TAB: commit_message $2 | git stripspace --comment-lines | sed -e 's/ / /' @@ -459,12 +505,14 @@ peek_next_command () { # messages, effectively causing the combined commit to be used as the # new basis for any further squash/fixups. Args: sha1 rest die_failed_squash() { + sha1=$1 + rest=$2 mv "$squash_msg" "$msg" || exit rm -f "$fixup_msg" cp "$msg" "$GIT_DIR"/MERGE_MSG || exit warn - warn "Could not apply $1... $2" - die_with_patch $1 "" + warn "$(eval_gettext "Could not apply \$sha1... \$rest")" + die_with_patch $sha1 "" } flush_rewritten_pending() { @@ -488,6 +536,8 @@ record_in_rewritten() { } do_pick () { + sha1=$1 + rest=$2 if test "$(git rev-parse HEAD)" = "$squash_onto" then # Set the correct commit message and author info on the @@ -499,15 +549,15 @@ do_pick () { # resolve before manually running git commit --amend then git # rebase --continue. git commit --allow-empty --allow-empty-message --amend \ - --no-post-rewrite -n -q -C $1 && - pick_one -n $1 && + --no-post-rewrite -n -q -C $sha1 && + pick_one -n $sha1 && git commit --allow-empty --allow-empty-message \ - --amend --no-post-rewrite -n -q -C $1 \ + --amend --no-post-rewrite -n -q -C $sha1 \ ${gpg_sign_opt:+"$gpg_sign_opt"} || - die_with_patch $1 "Could not apply $1... $2" + die_with_patch $sha1 "$(eval_gettext "Could not apply \$sha1... \$rest")" else - pick_one $1 || - die_with_patch $1 "Could not apply $1... $2" + pick_one $sha1 || + die_with_patch $sha1 "$(eval_gettext "Could not apply \$sha1... \$rest")" fi } @@ -535,10 +585,11 @@ do_next () { mark_action_done do_pick $sha1 "$rest" git commit --amend --no-post-rewrite ${gpg_sign_opt:+"$gpg_sign_opt"} || { - warn "Could not amend commit after successfully picking $sha1... $rest" - warn "This is most likely due to an empty commit message, or the pre-commit hook" - warn "failed. If the pre-commit hook failed, you may need to resolve the issue before" - warn "you are able to reword the commit." + warn "$(eval_gettext "\ +Could not amend commit after successfully picking \$sha1... \$rest +This is most likely due to an empty commit message, or the pre-commit hook +failed. If the pre-commit hook failed, you may need to resolve the issue before +you are able to reword the commit.")" exit_with_patch $sha1 1 } record_in_rewritten $sha1 @@ -549,7 +600,7 @@ do_next () { mark_action_done do_pick $sha1 "$rest" sha1_abbrev=$(git rev-parse --short $sha1) - warn "Stopped at $sha1_abbrev... $rest" + warn "$(eval_gettext "Stopped at \$sha1_abbrev... \$rest")" exit_with_patch $sha1 0 ;; squash|s|fixup|f) @@ -564,7 +615,7 @@ do_next () { comment_for_reflog $squash_style test -f "$done" && has_action "$done" || - die "Cannot '$squash_style' without a previous commit" + die "$(eval_gettext "Cannot '\$squash_style' without a previous commit")" mark_action_done update_squash_messages $squash_style $sha1 @@ -606,7 +657,7 @@ do_next () { x|"exec") read -r command rest < "$todo" mark_action_done - printf 'Executing: %s\n' "$rest" + eval_gettextln "Executing: \$rest" "${SHELL:-@SHELL_PATH@}" -c "$rest" # Actual execution status=$? # Run in subshell because require_clean_work_tree can die. @@ -614,13 +665,14 @@ do_next () { (require_clean_work_tree "rebase" 2>/dev/null) || dirty=t if test "$status" -ne 0 then - warn "Execution failed: $rest" + warn "$(eval_gettext "Execution failed: \$rest")" test "$dirty" = f || - warn "and made changes to the index and/or the working tree" + warn "$(gettext "and made changes to the index and/or the working tree")" - warn "You can fix the problem, and then run" - warn - warn " git rebase --continue" + warn "$(gettext "\ +You can fix the problem, and then run + + git rebase --continue")" warn if test $status -eq 127 # command not found then @@ -629,18 +681,20 @@ do_next () { exit "$status" elif test "$dirty" = t then - warn "Execution succeeded: $rest" - warn "but left changes to the index and/or the working tree" - warn "Commit or stash your changes, and then run" - warn - warn " git rebase --continue" + # TRANSLATORS: after these lines is a command to be issued by the user + warn "$(eval_gettext "\ +Execution succeeded: \$rest +but left changes to the index and/or the working tree +Commit or stash your changes, and then run + + git rebase --continue")" warn exit 1 fi ;; *) - warn "Unknown command: $command $sha1 $rest" - fixtodo="Please fix this using 'git rebase --edit-todo'." + warn "$(eval_gettext "Unknown command: \$command \$sha1 \$rest")" + fixtodo="$(gettext "Please fix this using 'git rebase --edit-todo'.")" if git rev-parse --verify -q "$sha1" >/dev/null then die_with_patch $sha1 "$fixtodo" @@ -675,7 +729,7 @@ do_next () { "$hook" rebase < "$rewritten_list" true # we don't care if this hook failed fi && - warn "Successfully rebased and updated $head_name." + warn "$(eval_gettext "Successfully rebased and updated \$head_name.")" return 1 # not failure; just to break the do_rest loop } @@ -722,7 +776,7 @@ skip_unnecessary_picks () { record_in_rewritten "$onto" ;; esac || - die "Could not skip unnecessary pick commands" + die "$(gettext "Could not skip unnecessary pick commands")" } transform_todo_ids () { @@ -880,9 +934,9 @@ check_commit_sha () { if test $badsha -ne 0 then line="$(sed -n -e "${2}p" "$3")" - warn "Warning: the SHA-1 is missing or isn't" \ - "a commit in the following line:" - warn " - $line" + warn "$(eval_gettext "\ +Warning: the SHA-1 is missing or isn't a commit in the following line: + - \$line")" warn fi @@ -913,9 +967,9 @@ check_bad_cmd_and_sha () { ;; *) line="$(sed -n -e "${lineno}p" "$1")" - warn "Warning: the command isn't recognized" \ - "in the following line:" - warn " - $line" + warn "$(eval_gettext "\ +Warning: the command isn't recognized in the following line: + - \$line")" warn retval=1 ;; @@ -952,7 +1006,7 @@ warn_lines () { # Switch to the branch in $into and notify it in the reflog checkout_onto () { GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" - output git checkout $onto || die_abort "could not detach HEAD" + output git checkout $onto || die_abort "$(gettext "could not detach HEAD")" git update-ref ORIG_HEAD $orig_head } @@ -990,28 +1044,26 @@ check_todo_list () { then test "$check_level" = error && raise_error=t - warn "Warning: some commits may have been dropped" \ - "accidentally." - warn "Dropped commits (newer to older):" + warn "$(gettext "\ +Warning: some commits may have been dropped accidentally. +Dropped commits (newer to older):")" # Make the list user-friendly and display opt="--no-walk=sorted --format=oneline --abbrev-commit --stdin" git rev-list $opt <"$todo".miss | warn_lines - warn "To avoid this message, use \"drop\" to" \ - "explicitly remove a commit." - warn - warn "Use 'git config rebase.missingCommitsCheck' to change" \ - "the level of warnings." - warn "The possible behaviours are: ignore, warn, error." + warn "$(gettext "\ +To avoid this message, use \"drop\" to explicitly remove a commit. + +Use 'git config rebase.missingCommitsCheck' to change the level of warnings. +The possible behaviours are: ignore, warn, error.")" warn fi ;; ignore) ;; *) - warn "Unrecognized setting $check_level for option" \ - "rebase.missingCommitsCheck. Ignoring." + warn "$(eval_gettext "Unrecognized setting \$check_level for option rebase.missingCommitsCheck. Ignoring.")" ;; esac @@ -1028,8 +1080,8 @@ check_todo_list () { # placed before the commit of the next action checkout_onto - warn "You can fix this with 'git rebase --edit-todo'." - die "Or you can abort the rebase with 'git rebase --abort'." + warn "$(gettext "You can fix this with 'git rebase --edit-todo'.")" + die "$(gettext "Or you can abort the rebase with 'git rebase --abort'.")" fi } @@ -1053,41 +1105,43 @@ continue) test ! -f "$GIT_DIR"/CHERRY_PICK_HEAD || rm "$GIT_DIR"/CHERRY_PICK_HEAD || - die "Could not remove CHERRY_PICK_HEAD" + die "$(gettext "Could not remove CHERRY_PICK_HEAD")" else if ! test -f "$author_script" then gpg_sign_opt_quoted=${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} - die "You have staged changes in your working tree. If these changes are meant to be + die "$(eval_gettext "\ +You have staged changes in your working tree. +If these changes are meant to be squashed into the previous commit, run: - git commit --amend $gpg_sign_opt_quoted + git commit --amend \$gpg_sign_opt_quoted If they are meant to go into a new commit, run: - git commit $gpg_sign_opt_quoted + git commit \$gpg_sign_opt_quoted In both case, once you're done, continue with: git rebase --continue -" +")" fi . "$author_script" || - die "Error trying to find the author identity to amend commit" + die "$(gettext "Error trying to find the author identity to amend commit")" if test -f "$amend" then current_head=$(git rev-parse --verify HEAD) test "$current_head" = $(cat "$amend") || - die "\ -You have uncommitted changes in your working tree. Please, commit them -first and then run 'git rebase --continue' again." + die "$(gettext "\ +You have uncommitted changes in your working tree. Please commit them +first and then run 'git rebase --continue' again.")" do_with_author git commit --amend --no-verify -F "$msg" -e \ ${gpg_sign_opt:+"$gpg_sign_opt"} || - die "Could not commit staged changes." + die "$(gettext "Could not commit staged changes.")" else do_with_author git commit --no-verify -F "$msg" -e \ ${gpg_sign_opt:+"$gpg_sign_opt"} || - die "Could not commit staged changes." + die "$(gettext "Could not commit staged changes.")" fi fi @@ -1111,16 +1165,15 @@ edit-todo) mv -f "$todo".new "$todo" collapse_todo_ids append_todo_help - git stripspace --comment-lines >>"$todo" <<\EOF - + gettext " You are editing the todo file of an ongoing interactive rebase. To continue rebase after editing, run: git rebase --continue -EOF +" | git stripspace --comment-lines >>"$todo" git_sequence_editor "$todo" || - die "Could not execute editor" + die "$(gettext "Could not execute editor")" expand_todo_ids exit @@ -1128,7 +1181,7 @@ EOF esac git var GIT_COMMITTER_IDENT >/dev/null || - die "You need to set your committer info first" + die "$(gettext "You need to set your committer info first")" comment_for_reflog start @@ -1136,15 +1189,15 @@ if test ! -z "$switch_to" then GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to" output git checkout "$switch_to" -- || - die "Could not checkout $switch_to" + die "$(eval_gettext "Could not checkout \$switch_to")" comment_for_reflog start fi -orig_head=$(git rev-parse --verify HEAD) || die "No HEAD?" -mkdir -p "$state_dir" || die "Could not create temporary $state_dir" +orig_head=$(git rev-parse --verify HEAD) || die "$(gettext "No HEAD?")" +mkdir -p "$state_dir" || die "$(eval_gettext "Could not create temporary \$state_dir")" -: > "$state_dir"/interactive || die "Could not mark as interactive" +: > "$state_dir"/interactive || die "$(gettext "Could not mark as interactive")" write_basic_state if test t = "$preserve_merges" then @@ -1154,12 +1207,12 @@ then for c in $(git merge-base --all $orig_head $upstream) do echo $onto > "$rewritten"/$c || - die "Could not init rewritten commits" + die "$(gettext "Could not init rewritten commits")" done else mkdir "$rewritten" && echo $onto > "$rewritten"/root || - die "Could not init rewritten commits" + die "$(gettext "Could not init rewritten commits")" fi # No cherry-pick because our first pass is to determine # parents to rewrite and skipping dropped commits would @@ -1258,18 +1311,20 @@ todocount=${todocount##* } cat >>"$todo" <<EOF -$comment_char Rebase $shortrevisions onto $shortonto ($todocount command(s)) +$comment_char $(eval_ngettext \ + "Rebase \$shortrevisions onto \$shortonto (\$todocount command)" \ + "Rebase \$shortrevisions onto \$shortonto (\$todocount commands)" \ + "$todocount") EOF append_todo_help -git stripspace --comment-lines >>"$todo" <<\EOF - +gettext " However, if you remove everything, the rebase will be aborted. -EOF +" | git stripspace --comment-lines >>"$todo" if test -z "$keep_empty" then - printf '%s\n' "$comment_char Note that empty commits are commented out" >>"$todo" + printf '%s\n' "$comment_char $(gettext "Note that empty commits are commented out")" >>"$todo" fi @@ -1279,7 +1334,7 @@ has_action "$todo" || cp "$todo" "$todo".backup collapse_todo_ids git_sequence_editor "$todo" || - die_abort "Could not execute editor" + die_abort "$(gettext "Could not execute editor")" has_action "$todo" || return 2 diff --git a/git-rebase.sh b/git-rebase.sh index 44ede367ae..04f6e44bc8 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -45,7 +45,6 @@ skip! skip current patch and continue edit-todo! edit the todo list during an interactive rebase " . git-sh-setup -. git-sh-i18n set_reflog_action rebase require_work_tree_exists cd_to_toplevel @@ -154,7 +153,7 @@ move_to_original_branch () { git symbolic-ref \ -m "rebase finished: returning to $head_name" \ HEAD $head_name || - die "$(gettext "Could not move back to $head_name")" + die "$(eval_gettext "Could not move back to \$head_name")" ;; esac } @@ -449,7 +448,7 @@ then then . git-parse-remote error_on_missing_default_upstream "rebase" "rebase" \ - "against" "git rebase <branch>" + "against" "git rebase $(gettext '<branch>')" fi test "$fork_point" = auto && fork_point=t diff --git a/git-send-email.perl b/git-send-email.perl index 69587856df..da81be40cb 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -621,6 +621,8 @@ if (@rev_list_opts) { push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts); } +@files = handle_backup_files(@files); + if ($validate) { foreach my $f (@files) { unless (-p $f) { @@ -1727,6 +1729,44 @@ sub validate_patch { return; } +sub handle_backup { + my ($last, $lastlen, $file, $known_suffix) = @_; + my ($suffix, $skip); + + $skip = 0; + if (defined $last && + ($lastlen < length($file)) && + (substr($file, 0, $lastlen) eq $last) && + ($suffix = substr($file, $lastlen)) !~ /^[a-z0-9]/i) { + if (defined $known_suffix && $suffix eq $known_suffix) { + print "Skipping $file with backup suffix '$known_suffix'.\n"; + $skip = 1; + } else { + my $answer = ask("Do you really want to send $file? (y|N): ", + valid_re => qr/^(?:y|n)/i, + default => 'n'); + $skip = ($answer ne 'y'); + if ($skip) { + $known_suffix = $suffix; + } + } + } + return ($skip, $known_suffix); +} + +sub handle_backup_files { + my @file = @_; + my ($last, $lastlen, $known_suffix, $skip, @result); + for my $file (@file) { + ($skip, $known_suffix) = handle_backup($last, $lastlen, + $file, $known_suffix); + push @result, $file unless $skip; + $last = $file; + $lastlen = length($file); + } + return @result; +} + sub file_has_nonascii { my $fn = shift; open(my $fh, '<', $fn) diff --git a/git-sh-i18n.sh b/git-sh-i18n.sh index e6c3116e18..1ef1889dbd 100644 --- a/git-sh-i18n.sh +++ b/git-sh-i18n.sh @@ -53,6 +53,13 @@ gettext_without_eval_gettext) git sh-i18n--envsubst "$1" ) } + + eval_ngettext () { + ngettext "$1" "$2" "$3" | ( + export PATH $(git sh-i18n--envsubst --variables "$2"); + git sh-i18n--envsubst "$2" + ) + } ;; poison) # Emit garbage so that tests that incorrectly rely on translatable @@ -64,6 +71,10 @@ poison) eval_gettext () { printf "%s" "# GETTEXT POISON #" } + + eval_ngettext () { + printf "%s" "# GETTEXT POISON #" + } ;; *) gettext () { @@ -76,6 +87,13 @@ poison) git sh-i18n--envsubst "$1" ) } + + eval_ngettext () { + (test "$3" = 1 && printf "%s" "$1" || printf "%s" "$2") | ( + export PATH $(git sh-i18n--envsubst --variables "$2"); + git sh-i18n--envsubst "$2" + ) + } ;; esac diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 85db5f1c63..0c34aa62f6 100644 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -2,6 +2,9 @@ # to set up some variables pointing at the normal git directories and # a few helper shell functions. +# Source git-sh-i18n for gettext support. +. git-sh-i18n + # Having this variable in your environment would break scripts because # you would cause "cd" to be taken to unexpected places. If you # like CDPATH, define it for your interactive shell sessions without @@ -83,16 +86,16 @@ if test -n "$OPTIONS_SPEC"; then else dashless=$(basename -- "$0" | sed -e 's/-/ /') usage() { - die "usage: $dashless $USAGE" + die "$(eval_gettext "usage: \$dashless \$USAGE")" } if [ -z "$LONG_USAGE" ] then - LONG_USAGE="usage: $dashless $USAGE" + LONG_USAGE="$(eval_gettext "usage: \$dashless \$USAGE")" else - LONG_USAGE="usage: $dashless $USAGE + LONG_USAGE="$(eval_gettext "usage: \$dashless \$USAGE -$LONG_USAGE" +$LONG_USAGE")" fi case "$1" in @@ -182,7 +185,7 @@ is_bare_repository () { cd_to_toplevel () { cdup=$(git rev-parse --show-toplevel) && cd "$cdup" || { - echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree" + gettextln "Cannot chdir to \$cdup, the toplevel of the working tree" >&2 exit 1 } } @@ -190,13 +193,16 @@ cd_to_toplevel () { require_work_tree_exists () { if test "z$(git rev-parse --is-bare-repository)" != zfalse then - die "fatal: $0 cannot be used without a working tree." + program_name=$0 + die "$(gettext "fatal: \$program_name cannot be used without a working tree.")" fi } require_work_tree () { - test "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = true || - die "fatal: $0 cannot be used without a working tree." + test "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = true || { + program_name=$0 + die "$(gettext "fatal: \$program_name cannot be used without a working tree.")" + } } require_clean_work_tree () { @@ -206,24 +212,49 @@ require_clean_work_tree () { if ! git diff-files --quiet --ignore-submodules then - echo >&2 "Cannot $1: You have unstaged changes." + action=$1 + case "$action" in + rebase) + gettextln "Cannot rebase: You have unstaged changes." >&2 + ;; + "rewrite branches") + gettextln "Cannot rewrite branches: You have unstaged changes." >&2 + ;; + "pull with rebase") + gettextln "Cannot pull with rebase: You have unstaged changes." >&2 + ;; + *) + eval_gettextln "Cannot \$action: You have unstaged changes." >&2 + ;; + esac err=1 fi if ! git diff-index --cached --quiet --ignore-submodules HEAD -- then - if [ $err = 0 ] + if test $err = 0 then - echo >&2 "Cannot $1: Your index contains uncommitted changes." + action=$1 + case "$action" in + rebase) + gettextln "Cannot rebase: Your index contains uncommitted changes." >&2 + ;; + "pull with rebase") + gettextln "Cannot pull with rebase: Your index contains uncommitted changes." >&2 + ;; + *) + eval_gettextln "Cannot \$action: Your index contains uncommitted changes." >&2 + ;; + esac else - echo >&2 "Additionally, your index contains uncommitted changes." + gettextln "Additionally, your index contains uncommitted changes." >&2 fi err=1 fi - if [ $err = 1 ] + if test $err = 1 then - test -n "$2" && echo >&2 "$2" + test -n "$2" && echo "$2" >&2 exit 1 fi } @@ -336,12 +367,12 @@ git_dir_init () { then test -z "$(git rev-parse --show-cdup)" || { exit=$? - echo >&2 "You need to run this command from the toplevel of the working tree." + gettextln "You need to run this command from the toplevel of the working tree." >&2 exit $exit } fi test -n "$GIT_DIR" && GIT_DIR=$(cd "$GIT_DIR" && pwd) || { - echo >&2 "Unable to determine absolute path of git directory" + gettextln "Unable to determine absolute path of git directory" >&2 exit 1 } : "${GIT_OBJECT_DIRECTORY="$(git rev-parse --git-path objects)"}" diff --git a/git-stash.sh b/git-stash.sh index c7509e8da4..22fb8bcba6 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -15,7 +15,6 @@ SUBDIRECTORY_OK=Yes OPTIONS_SPEC= START_DIR=$(pwd) . git-sh-setup -. git-sh-i18n require_work_tree cd_to_toplevel diff --git a/git-submodule.sh b/git-submodule.sh index b39ac106ec..4ec7546f1e 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -16,7 +16,6 @@ USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re OPTIONS_SPEC= SUBDIRECTORY_OK=Yes . git-sh-setup -. git-sh-i18n . git-parse-remote require_work_tree wt_prefix=$(git rev-parse --show-prefix) @@ -240,14 +239,15 @@ Use -f if you really want to add it." >&2 then if test -z "$force" then - echo >&2 "$(eval_gettext "A git directory for '\$sm_name' is found locally with remote(s):")" + eval_gettextln >&2 "A git directory for '\$sm_name' is found locally with remote(s):" GIT_DIR=".git/modules/$sm_name" GIT_WORK_TREE=. git remote -v | grep '(fetch)' | sed -e s,^," ", -e s,' (fetch)',, >&2 - echo >&2 "$(eval_gettext "If you want to reuse this local git directory instead of cloning again from")" - echo >&2 " $realrepo" - echo >&2 "$(eval_gettext "use the '--force' option. If the local git directory is not the correct repo")" - die "$(eval_gettext "or you are unsure what this means choose another name with the '--name' option.")" + die "$(eval_gettextln "\ +If you want to reuse this local git directory instead of cloning again from + \$realrepo +use the '--force' option. If the local git directory is not the correct repo +or you are unsure what this means choose another name with the '--name' option.")" else - echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")" + eval_gettextln "Reactivating local git directory for submodule '\$sm_name'." fi fi git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${depth:+"$depth"} || exit @@ -438,8 +438,9 @@ cmd_deinit() # Protect submodules containing a .git directory if test -d "$sm_path/.git" then - echo >&2 "$(eval_gettext "Submodule work tree '\$displaypath' contains a .git directory")" - die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")" + die "$(eval_gettext "\ +Submodule work tree '\$displaypath' contains a .git directory +(use 'rm -rf' if you really want to remove it including all of its history)")" fi if test -z "$force" @@ -624,7 +625,7 @@ cmd_update() remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote) sha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify "${remote_name}/${branch}") || - die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")" + die "$(eval_gettext "Unable to find current \${remote_name}/\${branch} revision in submodule path '\$sm_path'")" fi if test "$subsha1" != "$sha1" || test -n "$force" @@ -648,7 +649,7 @@ cmd_update() # not be reachable from any of the refs is_tip_reachable "$sm_path" "$sha1" || fetch_in_submodule "$sm_path" "$sha1" || - die "$(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain $sha1. Direct fetching of that commit failed.")" + die "$(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain \$sha1. Direct fetching of that commit failed.")" fi must_die_on_failure= @@ -705,7 +706,7 @@ cmd_update() if test $res -gt 0 then die_msg="$(eval_gettext "Failed to recurse into submodule path '\$displaypath'")" - if test $res -eq 1 + if test $res -ne 2 then err="${err};$die_msg" continue diff --git a/git-svn.perl b/git-svn.perl index 05eced06cd..f609e54ce3 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -507,7 +507,10 @@ sub init_subdir { sub cmd_clone { my ($url, $path) = @_; - if (!defined $path && + if (!$url) { + die "SVN repository location required ", + "as a command-line argument\n"; + } elsif (!defined $path && (defined $_trunk || @_branches || @_tags || defined $_stdlayout) && $url !~ m#^[a-z\+]+://#) { @@ -609,48 +609,15 @@ static int run_argv(int *argcp, const char ***argv) return done_alias; } -/* - * Many parts of Git have subprograms communicate via pipe, expect the - * upstream of a pipe to die with SIGPIPE when the downstream of a - * pipe does not need to read all that is written. Some third-party - * programs that ignore or block SIGPIPE for their own reason forget - * to restore SIGPIPE handling to the default before spawning Git and - * break this carefully orchestrated machinery. - * - * Restore the way SIGPIPE is handled to default, which is what we - * expect. - */ -static void restore_sigpipe_to_default(void) -{ - sigset_t unblock; - - sigemptyset(&unblock); - sigaddset(&unblock, SIGPIPE); - sigprocmask(SIG_UNBLOCK, &unblock, NULL); - signal(SIGPIPE, SIG_DFL); -} - -int main(int argc, char **av) +int cmd_main(int argc, const char **argv) { - const char **argv = (const char **) av; const char *cmd; int done_help = 0; - cmd = git_extract_argv0_path(argv[0]); + cmd = argv[0]; if (!cmd) cmd = "git-help"; - /* - * Always open file descriptors 0/1/2 to avoid clobbering files - * in die(). It also avoids messing up when the pipes are dup'ed - * onto stdin/stdout/stderr in the child processes we spawn. - */ - sanitize_stdfds(); - - restore_sigpipe_to_default(); - - git_setup_gettext(); - trace_command_performance(argv); /* @@ -17,8 +17,8 @@ static void graph_padding_line(struct git_graph *graph, struct strbuf *sb); /* - * Print a strbuf to stdout. If the graph is non-NULL, all lines but the - * first will be prefixed with the graph output. + * Print a strbuf. If the graph is non-NULL, all lines but the first will be + * prefixed with the graph output. * * If the strbuf ends with a newline, the output will end after this * newline. A new graph line will not be printed after the final newline. @@ -1200,9 +1200,10 @@ void graph_show_commit(struct git_graph *graph) while (!shown_commit_line && !graph_is_commit_finished(graph)) { shown_commit_line = graph_next_line(graph, &msgbuf); - fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); + fwrite(msgbuf.buf, sizeof(char), msgbuf.len, + graph->revs->diffopt.file); if (!shown_commit_line) - putchar('\n'); + putc('\n', graph->revs->diffopt.file); strbuf_setlen(&msgbuf, 0); } @@ -1217,7 +1218,7 @@ void graph_show_oneline(struct git_graph *graph) return; graph_next_line(graph, &msgbuf); - fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); + fwrite(msgbuf.buf, sizeof(char), msgbuf.len, graph->revs->diffopt.file); strbuf_release(&msgbuf); } @@ -1229,7 +1230,7 @@ void graph_show_padding(struct git_graph *graph) return; graph_padding_line(graph, &msgbuf); - fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); + fwrite(msgbuf.buf, sizeof(char), msgbuf.len, graph->revs->diffopt.file); strbuf_release(&msgbuf); } @@ -1246,12 +1247,13 @@ int graph_show_remainder(struct git_graph *graph) for (;;) { graph_next_line(graph, &msgbuf); - fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); + fwrite(msgbuf.buf, sizeof(char), msgbuf.len, + graph->revs->diffopt.file); strbuf_setlen(&msgbuf, 0); shown = 1; if (!graph_is_commit_finished(graph)) - putchar('\n'); + putc('\n', graph->revs->diffopt.file); else break; } @@ -1266,7 +1268,8 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb) char *p; if (!graph) { - fwrite(sb->buf, sizeof(char), sb->len, stdout); + fwrite(sb->buf, sizeof(char), sb->len, + graph->revs->diffopt.file); return; } @@ -1284,7 +1287,7 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb) } else { len = (sb->buf + sb->len) - p; } - fwrite(p, sizeof(char), len, stdout); + fwrite(p, sizeof(char), len, graph->revs->diffopt.file); if (next_p && *next_p != '\0') graph_show_oneline(graph); p = next_p; @@ -1304,7 +1307,8 @@ void graph_show_commit_msg(struct git_graph *graph, * CMIT_FMT_USERFORMAT are already missing a terminating * newline. All of the other formats should have it. */ - fwrite(sb->buf, sizeof(char), sb->len, stdout); + fwrite(sb->buf, sizeof(char), sb->len, + graph->revs->diffopt.file); return; } @@ -1325,7 +1329,7 @@ void graph_show_commit_msg(struct git_graph *graph, * new line. */ if (!newline_terminated) - putchar('\n'); + putc('\n', graph->revs->diffopt.file); graph_show_remainder(graph); @@ -1333,6 +1337,6 @@ void graph_show_commit_msg(struct git_graph *graph, * If sb ends with a newline, our output should too. */ if (newline_terminated) - putchar('\n'); + putc('\n', graph->revs->diffopt.file); } } @@ -4,6 +4,8 @@ #include "xdiff-interface.h" #include "diff.h" #include "diffcore.h" +#include "commit.h" +#include "quote.h" static int grep_source_load(struct grep_source *gs); static int grep_source_is_binary(struct grep_source *gs); @@ -322,11 +324,16 @@ static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt) int erroffset; int options = PCRE_MULTILINE; - if (opt->ignore_case) + if (opt->ignore_case) { + if (has_non_ascii(p->pattern)) + p->pcre_tables = pcre_maketables(); options |= PCRE_CASELESS; + } + if (is_utf8_locale() && has_non_ascii(p->pattern)) + options |= PCRE_UTF8; p->pcre_regexp = pcre_compile(p->pattern, options, &error, &erroffset, - NULL); + p->pcre_tables); if (!p->pcre_regexp) compile_regexp_failed(p, error); @@ -360,6 +367,7 @@ static void free_pcre_regexp(struct grep_pat *p) { pcre_free(p->pcre_regexp); pcre_free(p->pcre_extra_info); + pcre_free((void *)p->pcre_tables); } #else /* !USE_LIBPCRE */ static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt) @@ -396,26 +404,68 @@ static int is_fixed(const char *s, size_t len) return 1; } +static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt) +{ + struct strbuf sb = STRBUF_INIT; + int err; + int regflags; + + basic_regex_quote_buf(&sb, p->pattern); + regflags = opt->regflags & ~REG_EXTENDED; + if (opt->ignore_case) + regflags |= REG_ICASE; + err = regcomp(&p->regexp, sb.buf, regflags); + if (opt->debug) + fprintf(stderr, "fixed %s\n", sb.buf); + strbuf_release(&sb); + if (err) { + char errbuf[1024]; + regerror(err, &p->regexp, errbuf, sizeof(errbuf)); + regfree(&p->regexp); + compile_regexp_failed(p, errbuf); + } +} + static void compile_regexp(struct grep_pat *p, struct grep_opt *opt) { + int icase, ascii_only; int err; p->word_regexp = opt->word_regexp; p->ignore_case = opt->ignore_case; + icase = opt->regflags & REG_ICASE || p->ignore_case; + ascii_only = !has_non_ascii(p->pattern); + /* + * Even when -F (fixed) asks us to do a non-regexp search, we + * may not be able to correctly case-fold when -i + * (ignore-case) is asked (in which case, we'll synthesize a + * regexp to match the pattern that matches regexp special + * characters literally, while ignoring case differences). On + * the other hand, even without -F, if the pattern does not + * have any regexp special characters and there is no need for + * case-folding search, we can internally turn it into a + * simple string match using kws. p->fixed tells us if we + * want to use kws. + */ if (opt->fixed || is_fixed(p->pattern, p->patternlen)) - p->fixed = 1; + p->fixed = !icase || ascii_only; else p->fixed = 0; if (p->fixed) { - if (opt->regflags & REG_ICASE || p->ignore_case) - p->kws = kwsalloc(tolower_trans_tbl); - else - p->kws = kwsalloc(NULL); + p->kws = kwsalloc(icase ? tolower_trans_tbl : NULL); kwsincr(p->kws, p->pattern, p->patternlen); kwsprep(p->kws); return; + } else if (opt->fixed) { + /* + * We come here when the pattern has the non-ascii + * characters we cannot case-fold, and asked to + * ignore-case. + */ + compile_fixed_regexp(p, opt); + return; } if (opt->pcre) { @@ -48,6 +48,7 @@ struct grep_pat { regex_t regexp; pcre *pcre_regexp; pcre_extra *pcre_extra_info; + const unsigned char *pcre_tables; kwset_t kws; unsigned fixed:1; unsigned ignore_case:1; @@ -419,6 +419,12 @@ int cmd_version(int argc, const char **argv, const char *prefix) * with external projects that rely on the output of "git version". */ printf("git version %s\n", git_version_string); + while (*++argv) { + if (!strcmp(*argv, "--build-options")) { + printf("sizeof-long: %d\n", (int)sizeof(long)); + /* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */ + } + } return 0; } @@ -77,6 +77,11 @@ char *sha1_to_hex_r(char *buffer, const unsigned char *sha1) return buffer; } +char *oid_to_hex_r(char *buffer, const struct object_id *oid) +{ + return sha1_to_hex_r(buffer, oid->hash); +} + char *sha1_to_hex(const unsigned char *sha1) { static int bufno; diff --git a/http-backend.c b/http-backend.c index 214881459d..0d59499a51 100644 --- a/http-backend.c +++ b/http-backend.c @@ -632,7 +632,7 @@ static struct service_cmd { {"POST", "/git-receive-pack$", service_rpc} }; -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { char *method = getenv("REQUEST_METHOD"); char *dir; @@ -640,9 +640,6 @@ int main(int argc, char **argv) char *cmd_arg = NULL; int i; - git_setup_gettext(); - - git_extract_argv0_path(argv[0]); set_die_routine(die_webcgi); set_die_is_recursing_routine(die_webcgi_recursing); diff --git a/http-fetch.c b/http-fetch.c index ba3ea10670..3b556d6619 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -6,7 +6,7 @@ static const char http_fetch_usage[] = "git http-fetch " "[-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url"; -int main(int argc, const char **argv) +int cmd_main(int argc, const char **argv) { struct walker *walker; int commits_on_stdin = 0; @@ -22,10 +22,6 @@ int main(int argc, const char **argv) int get_verbosely = 0; int get_recover = 0; - git_setup_gettext(); - - git_extract_argv0_path(argv[0]); - while (arg < argc && argv[arg][0] == '-') { if (argv[arg][1] == 't') { get_tree = 1; diff --git a/http-push.c b/http-push.c index a092f0288b..dacada9094 100644 --- a/http-push.c +++ b/http-push.c @@ -1692,12 +1692,12 @@ static void run_request_queue(void) #endif } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct transfer_request *request; struct transfer_request *next_request; int nr_refspec = 0; - char **refspec = NULL; + const char **refspec = NULL; struct remote_lock *ref_lock = NULL; struct remote_lock *info_ref_lock = NULL; struct rev_info revs; @@ -1709,15 +1709,11 @@ int main(int argc, char **argv) int new_refs; struct ref *ref, *local_refs; - git_setup_gettext(); - - git_extract_argv0_path(argv[0]); - repo = xcalloc(1, sizeof(*repo)); argv++; for (i = 1; i < argc; i++, argv++) { - char *arg = *argv; + const char *arg = *argv; if (*arg == '-') { if (!strcmp(arg, "--all")) { diff --git a/imap-send.c b/imap-send.c index 50377c5b88..db0fafee99 100644 --- a/imap-send.c +++ b/imap-send.c @@ -1495,16 +1495,12 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server, } #endif -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct strbuf all_msgs = STRBUF_INIT; int total; int nongit_ok; - git_extract_argv0_path(argv[0]); - - git_setup_gettext(); - setup_git_directory_gently(&nongit_ok); git_imap_config(); diff --git a/line-log.c b/line-log.c index 1fbbe4f0af..916e724870 100644 --- a/line-log.c +++ b/line-log.c @@ -519,7 +519,7 @@ static void fill_line_ends(struct diff_filespec *spec, long *lines, char *data = NULL; if (diff_populate_filespec(spec, 0)) - die("Cannot read blob %s", sha1_to_hex(spec->sha1)); + die("Cannot read blob %s", oid_to_hex(&spec->oid)); ALLOC_ARRAY(ends, size); ends[cur++] = 0; @@ -840,7 +840,7 @@ static char *get_nth_line(long line, unsigned long *ends, void *data) static void print_line(const char *prefix, char first, long line, unsigned long *ends, void *data, - const char *color, const char *reset) + const char *color, const char *reset, FILE *file) { char *begin = get_nth_line(line, ends, data); char *end = get_nth_line(line+1, ends, data); @@ -851,14 +851,14 @@ static void print_line(const char *prefix, char first, had_nl = 1; } - fputs(prefix, stdout); - fputs(color, stdout); - putchar(first); - fwrite(begin, 1, end-begin, stdout); - fputs(reset, stdout); - putchar('\n'); + fputs(prefix, file); + fputs(color, file); + putc(first, file); + fwrite(begin, 1, end-begin, file); + fputs(reset, file); + putc('\n', file); if (!had_nl) - fputs("\\ No newline at end of file\n", stdout); + fputs("\\ No newline at end of file\n", file); } static char *output_prefix(struct diff_options *opt) @@ -893,16 +893,16 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang if (!pair || !diff) return; - if (pair->one->sha1_valid) + if (pair->one->oid_valid) fill_line_ends(pair->one, &p_lines, &p_ends); fill_line_ends(pair->two, &t_lines, &t_ends); - printf("%s%sdiff --git a/%s b/%s%s\n", prefix, c_meta, pair->one->path, pair->two->path, c_reset); - printf("%s%s--- %s%s%s\n", prefix, c_meta, - pair->one->sha1_valid ? "a/" : "", - pair->one->sha1_valid ? pair->one->path : "/dev/null", + fprintf(opt->file, "%s%sdiff --git a/%s b/%s%s\n", prefix, c_meta, pair->one->path, pair->two->path, c_reset); + fprintf(opt->file, "%s%s--- %s%s%s\n", prefix, c_meta, + pair->one->oid_valid ? "a/" : "", + pair->one->oid_valid ? pair->one->path : "/dev/null", c_reset); - printf("%s%s+++ b/%s%s\n", prefix, c_meta, pair->two->path, c_reset); + fprintf(opt->file, "%s%s+++ b/%s%s\n", prefix, c_meta, pair->two->path, c_reset); for (i = 0; i < range->ranges.nr; i++) { long p_start, p_end; long t_start = range->ranges.ranges[i].start; @@ -944,7 +944,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang } /* Now output a diff hunk for this range */ - printf("%s%s@@ -%ld,%ld +%ld,%ld @@%s\n", + fprintf(opt->file, "%s%s@@ -%ld,%ld +%ld,%ld @@%s\n", prefix, c_frag, p_start+1, p_end-p_start, t_start+1, t_end-t_start, c_reset); @@ -952,18 +952,18 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang int k; for (; t_cur < diff->target.ranges[j].start; t_cur++) print_line(prefix, ' ', t_cur, t_ends, pair->two->data, - c_context, c_reset); + c_context, c_reset, opt->file); for (k = diff->parent.ranges[j].start; k < diff->parent.ranges[j].end; k++) print_line(prefix, '-', k, p_ends, pair->one->data, - c_old, c_reset); + c_old, c_reset, opt->file); for (; t_cur < diff->target.ranges[j].end && t_cur < t_end; t_cur++) print_line(prefix, '+', t_cur, t_ends, pair->two->data, - c_new, c_reset); + c_new, c_reset, opt->file); j++; } for (; t_cur < t_end; t_cur++) print_line(prefix, ' ', t_cur, t_ends, pair->two->data, - c_context, c_reset); + c_context, c_reset, opt->file); } free(p_ends); @@ -976,7 +976,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang */ static void dump_diff_hacky(struct rev_info *rev, struct line_log_data *range) { - puts(output_prefix(&rev->diffopt)); + fprintf(rev->diffopt.file, "%s\n", output_prefix(&rev->diffopt)); while (range) { dump_diff_hacky_one(rev, range); range = range->next; @@ -1010,12 +1010,12 @@ static int process_diff_filepair(struct rev_info *rev, if (rg->ranges.nr == 0) return 0; - assert(pair->two->sha1_valid); + assert(pair->two->oid_valid); diff_populate_filespec(pair->two, 0); file_target.ptr = pair->two->data; file_target.size = pair->two->size; - if (pair->one->sha1_valid) { + if (pair->one->oid_valid) { diff_populate_filespec(pair->one, 0); file_parent.ptr = pair->one->data; file_parent.size = pair->one->size; diff --git a/log-tree.c b/log-tree.c index 9f678abc92..d0062e6788 100644 --- a/log-tree.c +++ b/log-tree.c @@ -159,12 +159,12 @@ void load_ref_decorations(int flags) } } -static void show_parents(struct commit *commit, int abbrev) +static void show_parents(struct commit *commit, int abbrev, FILE *file) { struct commit_list *p; for (p = commit->parents; p ; p = p->next) { struct commit *parent = p->item; - printf(" %s", find_unique_abbrev(parent->object.oid.hash, abbrev)); + fprintf(file, " %s", find_unique_abbrev(parent->object.oid.hash, abbrev)); } } @@ -172,7 +172,7 @@ static void show_children(struct rev_info *opt, struct commit *commit, int abbre { struct commit_list *p = lookup_decoration(&opt->children, &commit->object); for ( ; p; p = p->next) { - printf(" %s", find_unique_abbrev(p->item->object.oid.hash, abbrev)); + fprintf(opt->diffopt.file, " %s", find_unique_abbrev(p->item->object.oid.hash, abbrev)); } } @@ -286,11 +286,11 @@ void show_decorations(struct rev_info *opt, struct commit *commit) struct strbuf sb = STRBUF_INIT; if (opt->show_source && commit->util) - printf("\t%s", (char *) commit->util); + fprintf(opt->diffopt.file, "\t%s", (char *) commit->util); if (!opt->show_decorations) return; format_decorations(&sb, commit, opt->diffopt.use_color); - fputs(sb.buf, stdout); + fputs(sb.buf, opt->diffopt.file); strbuf_release(&sb); } @@ -364,18 +364,18 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, subject = "Subject: "; } - printf("From %s Mon Sep 17 00:00:00 2001\n", name); + fprintf(opt->diffopt.file, "From %s Mon Sep 17 00:00:00 2001\n", name); graph_show_oneline(opt->graph); if (opt->message_id) { - printf("Message-Id: <%s>\n", opt->message_id); + fprintf(opt->diffopt.file, "Message-Id: <%s>\n", opt->message_id); graph_show_oneline(opt->graph); } if (opt->ref_message_ids && opt->ref_message_ids->nr > 0) { int i, n; n = opt->ref_message_ids->nr; - printf("In-Reply-To: <%s>\n", opt->ref_message_ids->items[n-1].string); + fprintf(opt->diffopt.file, "In-Reply-To: <%s>\n", opt->ref_message_ids->items[n-1].string); for (i = 0; i < n; i++) - printf("%s<%s>\n", (i > 0 ? "\t" : "References: "), + fprintf(opt->diffopt.file, "%s<%s>\n", (i > 0 ? "\t" : "References: "), opt->ref_message_ids->items[i].string); graph_show_oneline(opt->graph); } @@ -432,7 +432,7 @@ static void show_sig_lines(struct rev_info *opt, int status, const char *bol) reset = diff_get_color_opt(&opt->diffopt, DIFF_RESET); while (*bol) { eol = strchrnul(bol, '\n'); - printf("%s%.*s%s%s", color, (int)(eol - bol), bol, reset, + fprintf(opt->diffopt.file, "%s%.*s%s%s", color, (int)(eol - bol), bol, reset, *eol ? "\n" : ""); graph_show_oneline(opt->graph); bol = (*eol) ? (eol + 1) : eol; @@ -553,17 +553,17 @@ void show_log(struct rev_info *opt) if (!opt->graph) put_revision_mark(opt, commit); - fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit), stdout); + fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit), opt->diffopt.file); if (opt->print_parents) - show_parents(commit, abbrev_commit); + show_parents(commit, abbrev_commit, opt->diffopt.file); if (opt->children.name) show_children(opt, commit, abbrev_commit); show_decorations(opt, commit); if (opt->graph && !graph_is_commit_finished(opt->graph)) { - putchar('\n'); + putc('\n', opt->diffopt.file); graph_show_remainder(opt->graph); } - putchar(opt->diffopt.line_termination); + putc(opt->diffopt.line_termination, opt->diffopt.file); return; } @@ -589,7 +589,7 @@ void show_log(struct rev_info *opt) if (opt->diffopt.line_termination == '\n' && !opt->missing_newline) graph_show_padding(opt->graph); - putchar(opt->diffopt.line_termination); + putc(opt->diffopt.line_termination, opt->diffopt.file); } opt->shown_one = 1; @@ -607,28 +607,28 @@ void show_log(struct rev_info *opt) log_write_email_headers(opt, commit, &ctx.subject, &extra_headers, &ctx.need_8bit_cte); } else if (opt->commit_format != CMIT_FMT_USERFORMAT) { - fputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), stdout); + fputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), opt->diffopt.file); if (opt->commit_format != CMIT_FMT_ONELINE) - fputs("commit ", stdout); + fputs("commit ", opt->diffopt.file); if (!opt->graph) put_revision_mark(opt, commit); fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit), - stdout); + opt->diffopt.file); if (opt->print_parents) - show_parents(commit, abbrev_commit); + show_parents(commit, abbrev_commit, opt->diffopt.file); if (opt->children.name) show_children(opt, commit, abbrev_commit); if (parent) - printf(" (from %s)", + fprintf(opt->diffopt.file, " (from %s)", find_unique_abbrev(parent->object.oid.hash, abbrev_commit)); - fputs(diff_get_color_opt(&opt->diffopt, DIFF_RESET), stdout); + fputs(diff_get_color_opt(&opt->diffopt, DIFF_RESET), opt->diffopt.file); show_decorations(opt, commit); if (opt->commit_format == CMIT_FMT_ONELINE) { - putchar(' '); + putc(' ', opt->diffopt.file); } else { - putchar('\n'); + putc('\n', opt->diffopt.file); graph_show_oneline(opt->graph); } if (opt->reflog_info) { @@ -704,7 +704,7 @@ void show_log(struct rev_info *opt) } if (opt->show_log_size) { - printf("log size %i\n", (int)msgbuf.len); + fprintf(opt->diffopt.file, "log size %i\n", (int)msgbuf.len); graph_show_oneline(opt->graph); } @@ -720,11 +720,11 @@ void show_log(struct rev_info *opt) if (opt->graph) graph_show_commit_msg(opt->graph, &msgbuf); else - fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); + fwrite(msgbuf.buf, sizeof(char), msgbuf.len, opt->diffopt.file); if (opt->use_terminator && !commit_format_is_empty(opt->commit_format)) { if (!opt->missing_newline) graph_show_padding(opt->graph); - putchar(opt->diffopt.line_termination); + putc(opt->diffopt.line_termination, opt->diffopt.file); } strbuf_release(&msgbuf); @@ -761,7 +761,7 @@ int log_tree_diff_flush(struct rev_info *opt) struct strbuf *msg = NULL; msg = opt->diffopt.output_prefix(&opt->diffopt, opt->diffopt.output_prefix_data); - fwrite(msg->buf, msg->len, 1, stdout); + fwrite(msg->buf, msg->len, 1, opt->diffopt.file); } /* @@ -776,8 +776,8 @@ int log_tree_diff_flush(struct rev_info *opt) */ if (!opt->shown_dashes && (pch & opt->diffopt.output_format) == pch) - printf("---"); - putchar('\n'); + fprintf(opt->diffopt.file, "---"); + putc('\n', opt->diffopt.file); } } diff_flush(&opt->diffopt); @@ -864,17 +864,18 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log int log_tree_commit(struct rev_info *opt, struct commit *commit) { struct log_info log; - int shown; + int shown, close_file = opt->diffopt.close_file; log.commit = commit; log.parent = NULL; opt->loginfo = &log; + opt->diffopt.close_file = 0; if (opt->line_level_traverse) return line_log_print(opt, commit); if (opt->track_linear && !opt->linear && !opt->reverse_output_stage) - printf("\n%s\n", opt->break_bar); + fprintf(opt->diffopt.file, "\n%s\n", opt->break_bar); shown = log_tree_diff(opt, commit, &log); if (!shown && opt->loginfo && opt->always_show_header) { log.parent = NULL; @@ -882,8 +883,10 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit) shown = 1; } if (opt->track_linear && !opt->linear && opt->reverse_output_stage) - printf("\n%s\n", opt->break_bar); + fprintf(opt->diffopt.file, "\n%s\n", opt->break_bar); opt->loginfo = NULL; - maybe_flush_or_die(stdout, "stdout"); + maybe_flush_or_die(opt->diffopt.file, "stdout"); + if (close_file) + fclose(opt->diffopt.file); return shown; } diff --git a/merge-recursive.c b/merge-recursive.c index 65cb5d6c1f..48fe7e7386 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -56,11 +56,11 @@ static struct commit *make_virtual_commit(struct tree *tree, const char *comment * Since we use get_tree_entry(), which does not put the read object into * the object pool, we cannot rely on a == b. */ -static int sha_eq(const unsigned char *a, const unsigned char *b) +static int oid_eq(const struct object_id *a, const struct object_id *b) { if (!a && !b) return 2; - return a && b && hashcmp(a, b) == 0; + return a && b && oidcmp(a, b) == 0; } enum rename_type { @@ -90,7 +90,7 @@ struct rename_conflict_info { struct stage_data { struct { unsigned mode; - unsigned char sha[20]; + struct object_id oid; } stages[4]; struct rename_conflict_info *rename_conflict_info; unsigned processed:1; @@ -134,11 +134,11 @@ static inline void setup_rename_conflict_info(enum rename_type rename_type, int ostage2 = ostage1 ^ 1; ci->ren1_other.path = pair1->one->path; - hashcpy(ci->ren1_other.sha1, src_entry1->stages[ostage1].sha); + oidcpy(&ci->ren1_other.oid, &src_entry1->stages[ostage1].oid); ci->ren1_other.mode = src_entry1->stages[ostage1].mode; ci->ren2_other.path = pair2->one->path; - hashcpy(ci->ren2_other.sha1, src_entry2->stages[ostage2].sha); + oidcpy(&ci->ren2_other.oid, &src_entry2->stages[ostage2].oid); ci->ren2_other.mode = src_entry2->stages[ostage2].mode; } } @@ -198,11 +198,11 @@ static void output_commit_title(struct merge_options *o, struct commit *commit) } } -static int add_cacheinfo(unsigned int mode, const unsigned char *sha1, +static int add_cacheinfo(unsigned int mode, const struct object_id *oid, const char *path, int stage, int refresh, int options) { struct cache_entry *ce; - ce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage, + ce = make_cache_entry(mode, oid ? oid->hash : null_sha1, path, stage, (refresh ? (CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING) : 0 )); if (!ce) @@ -314,11 +314,11 @@ static struct stage_data *insert_stage_data(const char *path, struct string_list_item *item; struct stage_data *e = xcalloc(1, sizeof(struct stage_data)); get_tree_entry(o->object.oid.hash, path, - e->stages[1].sha, &e->stages[1].mode); + e->stages[1].oid.hash, &e->stages[1].mode); get_tree_entry(a->object.oid.hash, path, - e->stages[2].sha, &e->stages[2].mode); + e->stages[2].oid.hash, &e->stages[2].mode); get_tree_entry(b->object.oid.hash, path, - e->stages[3].sha, &e->stages[3].mode); + e->stages[3].oid.hash, &e->stages[3].mode); item = string_list_insert(entries, path); item->util = e; return e; @@ -349,7 +349,7 @@ static struct string_list *get_unmerged(void) } e = item->util; e->stages[ce_stage(ce)].mode = ce->ce_mode; - hashcpy(e->stages[ce_stage(ce)].sha, ce->sha1); + hashcpy(e->stages[ce_stage(ce)].oid.hash, ce->sha1); } return unmerged; @@ -552,13 +552,13 @@ static int update_stages(const char *path, const struct diff_filespec *o, if (remove_file_from_cache(path)) return -1; if (o) - if (add_cacheinfo(o->mode, o->sha1, path, 1, 0, options)) + if (add_cacheinfo(o->mode, &o->oid, path, 1, 0, options)) return -1; if (a) - if (add_cacheinfo(a->mode, a->sha1, path, 2, 0, options)) + if (add_cacheinfo(a->mode, &a->oid, path, 2, 0, options)) return -1; if (b) - if (add_cacheinfo(b->mode, b->sha1, path, 3, 0, options)) + if (add_cacheinfo(b->mode, &b->oid, path, 3, 0, options)) return -1; return 0; } @@ -572,9 +572,9 @@ static void update_entry(struct stage_data *entry, entry->stages[1].mode = o->mode; entry->stages[2].mode = a->mode; entry->stages[3].mode = b->mode; - hashcpy(entry->stages[1].sha, o->sha1); - hashcpy(entry->stages[2].sha, a->sha1); - hashcpy(entry->stages[3].sha, b->sha1); + oidcpy(&entry->stages[1].oid, &o->oid); + oidcpy(&entry->stages[2].oid, &a->oid); + oidcpy(&entry->stages[3].oid, &b->oid); } static int remove_file(struct merge_options *o, int clean, @@ -736,7 +736,7 @@ static int make_room_for_path(struct merge_options *o, const char *path) } static void update_file_flags(struct merge_options *o, - const unsigned char *sha, + const struct object_id *oid, unsigned mode, const char *path, int update_cache, @@ -760,11 +760,11 @@ static void update_file_flags(struct merge_options *o, goto update_index; } - buf = read_sha1_file(sha, &type, &size); + buf = read_sha1_file(oid->hash, &type, &size); if (!buf) - die(_("cannot read object %s '%s'"), sha1_to_hex(sha), path); + die(_("cannot read object %s '%s'"), oid_to_hex(oid), path); if (type != OBJ_BLOB) - die(_("blob expected for %s '%s'"), sha1_to_hex(sha), path); + die(_("blob expected for %s '%s'"), oid_to_hex(oid), path); if (S_ISREG(mode)) { struct strbuf strbuf = STRBUF_INIT; if (convert_to_working_tree(path, buf, size, &strbuf)) { @@ -799,27 +799,27 @@ static void update_file_flags(struct merge_options *o, free(lnk); } else die(_("do not know what to do with %06o %s '%s'"), - mode, sha1_to_hex(sha), path); + mode, oid_to_hex(oid), path); free(buf); } update_index: if (update_cache) - add_cacheinfo(mode, sha, path, 0, update_wd, ADD_CACHE_OK_TO_ADD); + add_cacheinfo(mode, oid, path, 0, update_wd, ADD_CACHE_OK_TO_ADD); } static void update_file(struct merge_options *o, int clean, - const unsigned char *sha, + const struct object_id *oid, unsigned mode, const char *path) { - update_file_flags(o, sha, mode, path, o->call_depth || clean, !o->call_depth); + update_file_flags(o, oid, mode, path, o->call_depth || clean, !o->call_depth); } /* Low level file merging, update and removal */ struct merge_file_info { - unsigned char sha[20]; + struct object_id oid; unsigned mode; unsigned clean:1, merge:1; @@ -871,9 +871,9 @@ static int merge_3way(struct merge_options *o, name2 = mkpathdup("%s", branch2); } - read_mmblob(&orig, one->sha1); - read_mmblob(&src1, a->sha1); - read_mmblob(&src2, b->sha1); + read_mmblob(&orig, one->oid.hash); + read_mmblob(&src1, a->oid.hash); + read_mmblob(&src2, b->oid.hash); merge_status = ll_merge(result_buf, a->path, &orig, base_name, &src1, name1, &src2, name2, &ll_opts); @@ -902,13 +902,13 @@ static struct merge_file_info merge_file_1(struct merge_options *o, result.clean = 0; if (S_ISREG(a->mode)) { result.mode = a->mode; - hashcpy(result.sha, a->sha1); + oidcpy(&result.oid, &a->oid); } else { result.mode = b->mode; - hashcpy(result.sha, b->sha1); + oidcpy(&result.oid, &b->oid); } } else { - if (!sha_eq(a->sha1, one->sha1) && !sha_eq(b->sha1, one->sha1)) + if (!oid_eq(&a->oid, &one->oid) && !oid_eq(&b->oid, &one->oid)) result.merge = 1; /* @@ -924,10 +924,10 @@ static struct merge_file_info merge_file_1(struct merge_options *o, } } - if (sha_eq(a->sha1, b->sha1) || sha_eq(a->sha1, one->sha1)) - hashcpy(result.sha, b->sha1); - else if (sha_eq(b->sha1, one->sha1)) - hashcpy(result.sha, a->sha1); + if (oid_eq(&a->oid, &b->oid) || oid_eq(&a->oid, &one->oid)) + oidcpy(&result.oid, &b->oid); + else if (oid_eq(&b->oid, &one->oid)) + oidcpy(&result.oid, &a->oid); else if (S_ISREG(a->mode)) { mmbuffer_t result_buf; int merge_status; @@ -939,21 +939,23 @@ static struct merge_file_info merge_file_1(struct merge_options *o, die(_("Failed to execute internal merge")); if (write_sha1_file(result_buf.ptr, result_buf.size, - blob_type, result.sha)) + blob_type, result.oid.hash)) die(_("Unable to add %s to database"), a->path); free(result_buf.ptr); result.clean = (merge_status == 0); } else if (S_ISGITLINK(a->mode)) { - result.clean = merge_submodule(result.sha, - one->path, one->sha1, - a->sha1, b->sha1, + result.clean = merge_submodule(result.oid.hash, + one->path, + one->oid.hash, + a->oid.hash, + b->oid.hash, !o->call_depth); } else if (S_ISLNK(a->mode)) { - hashcpy(result.sha, a->sha1); + oidcpy(&result.oid, &a->oid); - if (!sha_eq(a->sha1, b->sha1)) + if (!oid_eq(&a->oid, &b->oid)) result.clean = 0; } else { die(_("unsupported object type in the tree")); @@ -991,34 +993,34 @@ merge_file_special_markers(struct merge_options *o, static struct merge_file_info merge_file_one(struct merge_options *o, const char *path, - const unsigned char *o_sha, int o_mode, - const unsigned char *a_sha, int a_mode, - const unsigned char *b_sha, int b_mode, + const struct object_id *o_oid, int o_mode, + const struct object_id *a_oid, int a_mode, + const struct object_id *b_oid, int b_mode, const char *branch1, const char *branch2) { struct diff_filespec one, a, b; one.path = a.path = b.path = (char *)path; - hashcpy(one.sha1, o_sha); + oidcpy(&one.oid, o_oid); one.mode = o_mode; - hashcpy(a.sha1, a_sha); + oidcpy(&a.oid, a_oid); a.mode = a_mode; - hashcpy(b.sha1, b_sha); + oidcpy(&b.oid, b_oid); b.mode = b_mode; return merge_file_1(o, &one, &a, &b, branch1, branch2); } static void handle_change_delete(struct merge_options *o, const char *path, - const unsigned char *o_sha, int o_mode, - const unsigned char *a_sha, int a_mode, - const unsigned char *b_sha, int b_mode, + const struct object_id *o_oid, int o_mode, + const struct object_id *a_oid, int a_mode, + const struct object_id *b_oid, int b_mode, const char *change, const char *change_past) { char *renamed = NULL; if (dir_in_way(path, !o->call_depth)) { - renamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2); + renamed = unique_path(o, path, a_oid ? o->branch1 : o->branch2); } if (o->call_depth) { @@ -1028,20 +1030,20 @@ static void handle_change_delete(struct merge_options *o, * them, simply reuse the base version for virtual merge base. */ remove_file_from_cache(path); - update_file(o, 0, o_sha, o_mode, renamed ? renamed : path); - } else if (!a_sha) { + update_file(o, 0, o_oid, o_mode, renamed ? renamed : path); + } else if (!a_oid) { if (!renamed) { output(o, 1, _("CONFLICT (%s/delete): %s deleted in %s " "and %s in %s. Version %s of %s left in tree."), change, path, o->branch1, change_past, o->branch2, o->branch2, path); - update_file(o, 0, b_sha, b_mode, path); + update_file(o, 0, b_oid, b_mode, path); } else { output(o, 1, _("CONFLICT (%s/delete): %s deleted in %s " "and %s in %s. Version %s of %s left in tree at %s."), change, path, o->branch1, change_past, o->branch2, o->branch2, path, renamed); - update_file(o, 0, b_sha, b_mode, renamed); + update_file(o, 0, b_oid, b_mode, renamed); } } else { if (!renamed) { @@ -1054,7 +1056,7 @@ static void handle_change_delete(struct merge_options *o, "and %s in %s. Version %s of %s left in tree at %s."), change, path, o->branch2, change_past, o->branch1, o->branch1, path, renamed); - update_file(o, 0, a_sha, a_mode, renamed); + update_file(o, 0, a_oid, a_mode, renamed); } /* * No need to call update_file() on path when !renamed, since @@ -1073,24 +1075,24 @@ static void conflict_rename_delete(struct merge_options *o, { const struct diff_filespec *orig = pair->one; const struct diff_filespec *dest = pair->two; - const unsigned char *a_sha = NULL; - const unsigned char *b_sha = NULL; + const struct object_id *a_oid = NULL; + const struct object_id *b_oid = NULL; int a_mode = 0; int b_mode = 0; if (rename_branch == o->branch1) { - a_sha = dest->sha1; + a_oid = &dest->oid; a_mode = dest->mode; } else { - b_sha = dest->sha1; + b_oid = &dest->oid; b_mode = dest->mode; } handle_change_delete(o, o->call_depth ? orig->path : dest->path, - orig->sha1, orig->mode, - a_sha, a_mode, - b_sha, b_mode, + &orig->oid, orig->mode, + a_oid, a_mode, + b_oid, b_mode, _("rename"), _("renamed")); if (o->call_depth) { @@ -1107,11 +1109,11 @@ static struct diff_filespec *filespec_from_entry(struct diff_filespec *target, struct stage_data *entry, int stage) { - unsigned char *sha = entry->stages[stage].sha; + struct object_id *oid = &entry->stages[stage].oid; unsigned mode = entry->stages[stage].mode; - if (mode == 0 || is_null_sha1(sha)) + if (mode == 0 || is_null_oid(oid)) return NULL; - hashcpy(target->sha1, sha); + oidcpy(&target->oid, oid); target->mode = mode; return target; } @@ -1140,7 +1142,7 @@ static void handle_file(struct merge_options *o, add = filespec_from_entry(&other, dst_entry, stage ^ 1); if (add) { char *add_name = unique_path(o, rename->path, other_branch); - update_file(o, 0, add->sha1, add->mode, add_name); + update_file(o, 0, &add->oid, add->mode, add_name); remove_file(o, 0, rename->path, 0); dst_name = unique_path(o, rename->path, cur_branch); @@ -1151,7 +1153,7 @@ static void handle_file(struct merge_options *o, rename->path, other_branch, dst_name); } } - update_file(o, 0, rename->sha1, rename->mode, dst_name); + update_file(o, 0, &rename->oid, rename->mode, dst_name); if (stage == 2) update_stages(rename->path, NULL, rename, add); else @@ -1180,9 +1182,9 @@ static void conflict_rename_rename_1to2(struct merge_options *o, struct diff_filespec other; struct diff_filespec *add; mfi = merge_file_one(o, one->path, - one->sha1, one->mode, - a->sha1, a->mode, - b->sha1, b->mode, + &one->oid, one->mode, + &a->oid, a->mode, + &b->oid, b->mode, ci->branch1, ci->branch2); /* * FIXME: For rename/add-source conflicts (if we could detect @@ -1190,7 +1192,7 @@ static void conflict_rename_rename_1to2(struct merge_options *o, * pathname and then either rename the add-source file to that * unique path, or use that unique path instead of src here. */ - update_file(o, 0, mfi.sha, mfi.mode, one->path); + update_file(o, 0, &mfi.oid, mfi.mode, one->path); /* * Above, we put the merged content at the merge-base's @@ -1202,12 +1204,12 @@ static void conflict_rename_rename_1to2(struct merge_options *o, */ add = filespec_from_entry(&other, ci->dst_entry1, 2 ^ 1); if (add) - update_file(o, 0, add->sha1, add->mode, a->path); + update_file(o, 0, &add->oid, add->mode, a->path); else remove_file_from_cache(a->path); add = filespec_from_entry(&other, ci->dst_entry2, 3 ^ 1); if (add) - update_file(o, 0, add->sha1, add->mode, b->path); + update_file(o, 0, &add->oid, add->mode, b->path); else remove_file_from_cache(b->path); } else { @@ -1253,16 +1255,16 @@ static void conflict_rename_rename_2to1(struct merge_options *o, * again later for the non-recursive merge. */ remove_file(o, 0, path, 0); - update_file(o, 0, mfi_c1.sha, mfi_c1.mode, a->path); - update_file(o, 0, mfi_c2.sha, mfi_c2.mode, b->path); + update_file(o, 0, &mfi_c1.oid, mfi_c1.mode, a->path); + update_file(o, 0, &mfi_c2.oid, mfi_c2.mode, b->path); } else { char *new_path1 = unique_path(o, path, ci->branch1); char *new_path2 = unique_path(o, path, ci->branch2); output(o, 1, _("Renaming %s to %s and %s to %s instead"), a->path, new_path1, b->path, new_path2); remove_file(o, 0, path, 0); - update_file(o, 0, mfi_c1.sha, mfi_c1.mode, new_path1); - update_file(o, 0, mfi_c2.sha, mfi_c2.mode, new_path2); + update_file(o, 0, &mfi_c1.oid, mfi_c1.mode, new_path1); + update_file(o, 0, &mfi_c2.oid, mfi_c2.mode, new_path2); free(new_path2); free(new_path1); } @@ -1421,13 +1423,15 @@ static int process_renames(struct merge_options *o, remove_file(o, 1, ren1_src, renamed_stage == 2 || !was_tracked(ren1_src)); - hashcpy(src_other.sha1, ren1->src_entry->stages[other_stage].sha); + oidcpy(&src_other.oid, + &ren1->src_entry->stages[other_stage].oid); src_other.mode = ren1->src_entry->stages[other_stage].mode; - hashcpy(dst_other.sha1, ren1->dst_entry->stages[other_stage].sha); + oidcpy(&dst_other.oid, + &ren1->dst_entry->stages[other_stage].oid); dst_other.mode = ren1->dst_entry->stages[other_stage].mode; try_merge = 0; - if (sha_eq(src_other.sha1, null_sha1)) { + if (oid_eq(&src_other.oid, &null_oid)) { setup_rename_conflict_info(RENAME_DELETE, ren1->pair, NULL, @@ -1439,7 +1443,7 @@ static int process_renames(struct merge_options *o, NULL, NULL); } else if ((dst_other.mode == ren1->pair->two->mode) && - sha_eq(dst_other.sha1, ren1->pair->two->sha1)) { + oid_eq(&dst_other.oid, &ren1->pair->two->oid)) { /* * Added file on the other side identical to * the file being renamed: clean merge. @@ -1449,12 +1453,12 @@ static int process_renames(struct merge_options *o, * update_file(). */ update_file_flags(o, - ren1->pair->two->sha1, + &ren1->pair->two->oid, ren1->pair->two->mode, ren1_dst, 1, /* update_cache */ 0 /* update_wd */); - } else if (!sha_eq(dst_other.sha1, null_sha1)) { + } else if (!oid_eq(&dst_other.oid, &null_oid)) { clean_merge = 0; try_merge = 1; output(o, 1, _("CONFLICT (rename/add): Rename %s->%s in %s. " @@ -1463,17 +1467,21 @@ static int process_renames(struct merge_options *o, ren1_dst, branch2); if (o->call_depth) { struct merge_file_info mfi; - mfi = merge_file_one(o, ren1_dst, null_sha1, 0, - ren1->pair->two->sha1, ren1->pair->two->mode, - dst_other.sha1, dst_other.mode, + mfi = merge_file_one(o, ren1_dst, &null_oid, 0, + &ren1->pair->two->oid, + ren1->pair->two->mode, + &dst_other.oid, + dst_other.mode, branch1, branch2); output(o, 1, _("Adding merged %s"), ren1_dst); - update_file(o, 0, mfi.sha, mfi.mode, ren1_dst); + update_file(o, 0, &mfi.oid, + mfi.mode, ren1_dst); try_merge = 0; } else { char *new_path = unique_path(o, ren1_dst, branch2); output(o, 1, _("Adding as %s instead"), new_path); - update_file(o, 0, dst_other.sha1, dst_other.mode, new_path); + update_file(o, 0, &dst_other.oid, + dst_other.mode, new_path); free(new_path); } } else @@ -1511,30 +1519,30 @@ static int process_renames(struct merge_options *o, return clean_merge; } -static unsigned char *stage_sha(const unsigned char *sha, unsigned mode) +static struct object_id *stage_oid(const struct object_id *oid, unsigned mode) { - return (is_null_sha1(sha) || mode == 0) ? NULL: (unsigned char *)sha; + return (is_null_oid(oid) || mode == 0) ? NULL: (struct object_id *)oid; } -static int read_sha1_strbuf(const unsigned char *sha1, struct strbuf *dst) +static int read_oid_strbuf(const struct object_id *oid, struct strbuf *dst) { void *buf; enum object_type type; unsigned long size; - buf = read_sha1_file(sha1, &type, &size); + buf = read_sha1_file(oid->hash, &type, &size); if (!buf) - return error(_("cannot read object %s"), sha1_to_hex(sha1)); + return error(_("cannot read object %s"), oid_to_hex(oid)); if (type != OBJ_BLOB) { free(buf); - return error(_("object %s is not a blob"), sha1_to_hex(sha1)); + return error(_("object %s is not a blob"), oid_to_hex(oid)); } strbuf_attach(dst, buf, size, size + 1); return 0; } -static int blob_unchanged(const unsigned char *o_sha, +static int blob_unchanged(const struct object_id *o_oid, unsigned o_mode, - const unsigned char *a_sha, + const struct object_id *a_oid, unsigned a_mode, int renormalize, const char *path) { @@ -1544,13 +1552,13 @@ static int blob_unchanged(const unsigned char *o_sha, if (a_mode != o_mode) return 0; - if (sha_eq(o_sha, a_sha)) + if (oid_eq(o_oid, a_oid)) return 1; if (!renormalize) return 0; - assert(o_sha && a_sha); - if (read_sha1_strbuf(o_sha, &o) || read_sha1_strbuf(a_sha, &a)) + assert(o_oid && a_oid); + if (read_oid_strbuf(o_oid, &o) || read_oid_strbuf(a_oid, &a)) goto error_return; /* * Note: binary | is used so that both renormalizations are @@ -1569,23 +1577,23 @@ error_return: static void handle_modify_delete(struct merge_options *o, const char *path, - unsigned char *o_sha, int o_mode, - unsigned char *a_sha, int a_mode, - unsigned char *b_sha, int b_mode) + struct object_id *o_oid, int o_mode, + struct object_id *a_oid, int a_mode, + struct object_id *b_oid, int b_mode) { handle_change_delete(o, path, - o_sha, o_mode, - a_sha, a_mode, - b_sha, b_mode, + o_oid, o_mode, + a_oid, a_mode, + b_oid, b_mode, _("modify"), _("modified")); } static int merge_content(struct merge_options *o, const char *path, - unsigned char *o_sha, int o_mode, - unsigned char *a_sha, int a_mode, - unsigned char *b_sha, int b_mode, + struct object_id *o_oid, int o_mode, + struct object_id *a_oid, int a_mode, + struct object_id *b_oid, int b_mode, struct rename_conflict_info *rename_conflict_info) { const char *reason = _("content"); @@ -1594,16 +1602,16 @@ static int merge_content(struct merge_options *o, struct diff_filespec one, a, b; unsigned df_conflict_remains = 0; - if (!o_sha) { + if (!o_oid) { reason = _("add/add"); - o_sha = (unsigned char *)null_sha1; + o_oid = (struct object_id *)&null_oid; } one.path = a.path = b.path = (char *)path; - hashcpy(one.sha1, o_sha); + oidcpy(&one.oid, o_oid); one.mode = o_mode; - hashcpy(a.sha1, a_sha); + oidcpy(&a.oid, a_oid); a.mode = a_mode; - hashcpy(b.sha1, b_sha); + oidcpy(&b.oid, b_oid); b.mode = b_mode; if (rename_conflict_info) { @@ -1627,7 +1635,7 @@ static int merge_content(struct merge_options *o, o->branch2, path2); if (mfi.clean && !df_conflict_remains && - sha_eq(mfi.sha, a_sha) && mfi.mode == a_mode) { + oid_eq(&mfi.oid, a_oid) && mfi.mode == a_mode) { int path_renamed_outside_HEAD; output(o, 3, _("Skipped %s (merged same as existing)"), path); /* @@ -1638,7 +1646,7 @@ static int merge_content(struct merge_options *o, */ path_renamed_outside_HEAD = !path2 || !strcmp(path, path2); if (!path_renamed_outside_HEAD) { - add_cacheinfo(mfi.mode, mfi.sha, path, + add_cacheinfo(mfi.mode, &mfi.oid, path, 0, (!o->call_depth), 0); return mfi.clean; } @@ -1664,7 +1672,7 @@ static int merge_content(struct merge_options *o, else { int file_from_stage2 = was_tracked(path); struct diff_filespec merged; - hashcpy(merged.sha1, mfi.sha); + oidcpy(&merged.oid, &mfi.oid); merged.mode = mfi.mode; update_stages(path, NULL, @@ -1675,11 +1683,11 @@ static int merge_content(struct merge_options *o, } new_path = unique_path(o, path, rename_conflict_info->branch1); output(o, 1, _("Adding as %s instead"), new_path); - update_file(o, 0, mfi.sha, mfi.mode, new_path); + update_file(o, 0, &mfi.oid, mfi.mode, new_path); free(new_path); mfi.clean = 0; } else { - update_file(o, mfi.clean, mfi.sha, mfi.mode, path); + update_file(o, mfi.clean, &mfi.oid, mfi.mode, path); } return mfi.clean; @@ -1694,9 +1702,9 @@ static int process_entry(struct merge_options *o, unsigned o_mode = entry->stages[1].mode; unsigned a_mode = entry->stages[2].mode; unsigned b_mode = entry->stages[3].mode; - unsigned char *o_sha = stage_sha(entry->stages[1].sha, o_mode); - unsigned char *a_sha = stage_sha(entry->stages[2].sha, a_mode); - unsigned char *b_sha = stage_sha(entry->stages[3].sha, b_mode); + struct object_id *o_oid = stage_oid(&entry->stages[1].oid, o_mode); + struct object_id *a_oid = stage_oid(&entry->stages[2].oid, a_mode); + struct object_id *b_oid = stage_oid(&entry->stages[3].oid, b_mode); entry->processed = 1; if (entry->rename_conflict_info) { @@ -1705,7 +1713,7 @@ static int process_entry(struct merge_options *o, case RENAME_NORMAL: case RENAME_ONE_FILE_TO_ONE: clean_merge = merge_content(o, path, - o_sha, o_mode, a_sha, a_mode, b_sha, b_mode, + o_oid, o_mode, a_oid, a_mode, b_oid, b_mode, conflict_info); break; case RENAME_DELETE: @@ -1726,45 +1734,45 @@ static int process_entry(struct merge_options *o, entry->processed = 0; break; } - } else if (o_sha && (!a_sha || !b_sha)) { + } else if (o_oid && (!a_oid || !b_oid)) { /* Case A: Deleted in one */ - if ((!a_sha && !b_sha) || - (!b_sha && blob_unchanged(o_sha, o_mode, a_sha, a_mode, normalize, path)) || - (!a_sha && blob_unchanged(o_sha, o_mode, b_sha, b_mode, normalize, path))) { + if ((!a_oid && !b_oid) || + (!b_oid && blob_unchanged(o_oid, o_mode, a_oid, a_mode, normalize, path)) || + (!a_oid && blob_unchanged(o_oid, o_mode, b_oid, b_mode, normalize, path))) { /* Deleted in both or deleted in one and * unchanged in the other */ - if (a_sha) + if (a_oid) output(o, 2, _("Removing %s"), path); /* do not touch working file if it did not exist */ - remove_file(o, 1, path, !a_sha); + remove_file(o, 1, path, !a_oid); } else { /* Modify/delete; deleted side may have put a directory in the way */ clean_merge = 0; - handle_modify_delete(o, path, o_sha, o_mode, - a_sha, a_mode, b_sha, b_mode); + handle_modify_delete(o, path, o_oid, o_mode, + a_oid, a_mode, b_oid, b_mode); } - } else if ((!o_sha && a_sha && !b_sha) || - (!o_sha && !a_sha && b_sha)) { + } else if ((!o_oid && a_oid && !b_oid) || + (!o_oid && !a_oid && b_oid)) { /* Case B: Added in one. */ /* [nothing|directory] -> ([nothing|directory], file) */ const char *add_branch; const char *other_branch; unsigned mode; - const unsigned char *sha; + const struct object_id *oid; const char *conf; - if (a_sha) { + if (a_oid) { add_branch = o->branch1; other_branch = o->branch2; mode = a_mode; - sha = a_sha; + oid = a_oid; conf = _("file/directory"); } else { add_branch = o->branch2; other_branch = o->branch1; mode = b_mode; - sha = b_sha; + oid = b_oid; conf = _("directory/file"); } if (dir_in_way(path, !o->call_depth)) { @@ -1773,22 +1781,22 @@ static int process_entry(struct merge_options *o, output(o, 1, _("CONFLICT (%s): There is a directory with name %s in %s. " "Adding %s as %s"), conf, path, other_branch, path, new_path); - update_file(o, 0, sha, mode, new_path); + update_file(o, 0, oid, mode, new_path); if (o->call_depth) remove_file_from_cache(path); free(new_path); } else { output(o, 2, _("Adding %s"), path); /* do not overwrite file if already present */ - update_file_flags(o, sha, mode, path, 1, !a_sha); + update_file_flags(o, oid, mode, path, 1, !a_oid); } - } else if (a_sha && b_sha) { + } else if (a_oid && b_oid) { /* Case C: Added in both (check for same permissions) and */ /* case D: Modified in both, but differently. */ clean_merge = merge_content(o, path, - o_sha, o_mode, a_sha, a_mode, b_sha, b_mode, + o_oid, o_mode, a_oid, a_mode, b_oid, b_mode, NULL); - } else if (!o_sha && !a_sha && !b_sha) { + } else if (!o_oid && !a_oid && !b_oid) { /* * this entry was deleted altogether. a_mode == 0 means * we had that path and want to actively remove it. @@ -1813,7 +1821,7 @@ int merge_trees(struct merge_options *o, common = shift_tree_object(head, common, o->subtree_shift); } - if (sha_eq(common->object.oid.hash, merge->object.oid.hash)) { + if (oid_eq(&common->object.oid, &merge->object.oid)) { output(o, 0, _("Already up-to-date!")); *result = head; return 1; @@ -1974,11 +1982,11 @@ int merge_recursive(struct merge_options *o, return clean; } -static struct commit *get_ref(const unsigned char *sha1, const char *name) +static struct commit *get_ref(const struct object_id *oid, const char *name) { struct object *object; - object = deref_tag(parse_object(sha1), name, strlen(name)); + object = deref_tag(parse_object(oid->hash), name, strlen(name)); if (!object) return NULL; if (object->type == OBJ_TREE) @@ -1991,10 +1999,10 @@ static struct commit *get_ref(const unsigned char *sha1, const char *name) } int merge_recursive_generic(struct merge_options *o, - const unsigned char *head, - const unsigned char *merge, + const struct object_id *head, + const struct object_id *merge, int num_base_list, - const unsigned char **base_list, + const struct object_id **base_list, struct commit **result) { int clean; @@ -2007,9 +2015,9 @@ int merge_recursive_generic(struct merge_options *o, int i; for (i = 0; i < num_base_list; ++i) { struct commit *base; - if (!(base = get_ref(base_list[i], sha1_to_hex(base_list[i])))) + if (!(base = get_ref(base_list[i], oid_to_hex(base_list[i])))) return error(_("Could not parse object '%s'"), - sha1_to_hex(base_list[i])); + oid_to_hex(base_list[i])); commit_list_insert(base, &ca); } } diff --git a/merge-recursive.h b/merge-recursive.h index 52f0201f68..d415724aea 100644 --- a/merge-recursive.h +++ b/merge-recursive.h @@ -49,10 +49,10 @@ int merge_trees(struct merge_options *o, * virtual commits and call merge_recursive() proper. */ int merge_recursive_generic(struct merge_options *o, - const unsigned char *head, - const unsigned char *merge, + const struct object_id *head, + const struct object_id *merge, int num_ca, - const unsigned char **ca, + const struct object_id **ca, struct commit **result); void init_merge_options(struct merge_options *o); diff --git a/notes-merge.c b/notes-merge.c index b7814c9b64..1b58a14ebc 100644 --- a/notes-merge.c +++ b/notes-merge.c @@ -41,14 +41,14 @@ static int verify_notes_filepair(struct diff_filepair *p, unsigned char *sha1) switch (p->status) { case DIFF_STATUS_MODIFIED: assert(p->one->mode == p->two->mode); - assert(!is_null_sha1(p->one->sha1)); - assert(!is_null_sha1(p->two->sha1)); + assert(!is_null_oid(&p->one->oid)); + assert(!is_null_oid(&p->two->oid)); break; case DIFF_STATUS_ADDED: - assert(is_null_sha1(p->one->sha1)); + assert(is_null_oid(&p->one->oid)); break; case DIFF_STATUS_DELETED: - assert(is_null_sha1(p->two->sha1)); + assert(is_null_oid(&p->two->oid)); break; default: return -1; @@ -142,27 +142,27 @@ static struct notes_merge_pair *diff_tree_remote(struct notes_merge_options *o, if (verify_notes_filepair(p, obj)) { trace_printf("\t\tCannot merge entry '%s' (%c): " "%.7s -> %.7s. Skipping!\n", p->one->path, - p->status, sha1_to_hex(p->one->sha1), - sha1_to_hex(p->two->sha1)); + p->status, oid_to_hex(&p->one->oid), + oid_to_hex(&p->two->oid)); continue; } mp = find_notes_merge_pair_pos(changes, len, obj, 1, &occupied); if (occupied) { /* We've found an addition/deletion pair */ assert(!hashcmp(mp->obj, obj)); - if (is_null_sha1(p->one->sha1)) { /* addition */ + if (is_null_oid(&p->one->oid)) { /* addition */ assert(is_null_sha1(mp->remote)); - hashcpy(mp->remote, p->two->sha1); - } else if (is_null_sha1(p->two->sha1)) { /* deletion */ + hashcpy(mp->remote, p->two->oid.hash); + } else if (is_null_oid(&p->two->oid)) { /* deletion */ assert(is_null_sha1(mp->base)); - hashcpy(mp->base, p->one->sha1); + hashcpy(mp->base, p->one->oid.hash); } else assert(!"Invalid existing change recorded"); } else { hashcpy(mp->obj, obj); - hashcpy(mp->base, p->one->sha1); + hashcpy(mp->base, p->one->oid.hash); hashcpy(mp->local, uninitialized); - hashcpy(mp->remote, p->two->sha1); + hashcpy(mp->remote, p->two->oid.hash); len++; } trace_printf("\t\tStored remote change for %s: %.7s -> %.7s\n", @@ -203,21 +203,21 @@ static void diff_tree_local(struct notes_merge_options *o, if (verify_notes_filepair(p, obj)) { trace_printf("\t\tCannot merge entry '%s' (%c): " "%.7s -> %.7s. Skipping!\n", p->one->path, - p->status, sha1_to_hex(p->one->sha1), - sha1_to_hex(p->two->sha1)); + p->status, oid_to_hex(&p->one->oid), + oid_to_hex(&p->two->oid)); continue; } mp = find_notes_merge_pair_pos(changes, len, obj, 0, &match); if (!match) { trace_printf("\t\tIgnoring local-only change for %s: " "%.7s -> %.7s\n", sha1_to_hex(obj), - sha1_to_hex(p->one->sha1), - sha1_to_hex(p->two->sha1)); + oid_to_hex(&p->one->oid), + oid_to_hex(&p->two->oid)); continue; } assert(!hashcmp(mp->obj, obj)); - if (is_null_sha1(p->two->sha1)) { /* deletion */ + if (is_null_oid(&p->two->oid)) { /* deletion */ /* * Either this is a true deletion (1), or it is part * of an A/D pair (2), or D/A pair (3): @@ -229,7 +229,7 @@ static void diff_tree_local(struct notes_merge_options *o, */ if (!hashcmp(mp->local, uninitialized)) hashclr(mp->local); - } else if (is_null_sha1(p->one->sha1)) { /* addition */ + } else if (is_null_oid(&p->one->oid)) { /* addition */ /* * Either this is a true addition (1), or it is part * of an A/D pair (2), or D/A pair (3): @@ -240,16 +240,16 @@ static void diff_tree_local(struct notes_merge_options *o, */ assert(is_null_sha1(mp->local) || !hashcmp(mp->local, uninitialized)); - hashcpy(mp->local, p->two->sha1); + hashcpy(mp->local, p->two->oid.hash); } else { /* modification */ /* * This is a true modification. p->one->sha1 shall * match mp->base, and mp->local shall be uninitialized. * Set mp->local to p->two->sha1. */ - assert(!hashcmp(p->one->sha1, mp->base)); + assert(!hashcmp(p->one->oid.hash, mp->base)); assert(!hashcmp(mp->local, uninitialized)); - hashcpy(mp->local, p->two->sha1); + hashcpy(mp->local, p->two->oid.hash); } trace_printf("\t\tStored local change for %s: %.7s -> %.7s\n", sha1_to_hex(mp->obj), sha1_to_hex(mp->base), diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm index bee1e7d1cb..018beb85a0 100644 --- a/perl/Git/SVN.pm +++ b/perl/Git/SVN.pm @@ -97,8 +97,12 @@ sub resolve_local_globs { "existing: $existing\n", " globbed: $refname\n"; } - my $u = (::cmt_metadata("$refname"))[0] or die - "$refname: no associated commit metadata\n"; + my $u = (::cmt_metadata("$refname"))[0]; + if (!defined($u)) { + warn +"W: $refname: no associated commit metadata from SVN, skipping\n"; + next; + } $u =~ s!^\Q$url\E(/|$)!! or die "$refname: '$url' not found in '$u'\n"; if ($pathname ne $u) { @@ -7,14 +7,15 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2010-09-20 14:44+0000\n" -"PO-Revision-Date: 2010-06-05 19:06 +0000\n" -"Last-Translator: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n" +"POT-Creation-Date: 2016-06-17 18:55+0000\n" +"PO-Revision-Date: 2016-06-17 19:17+0000\n" +"Last-Translator: Vasco Almeida <vascomalmeida@sapo.pt>\n" "Language-Team: Git Mailing List <git@vger.kernel.org>\n" "Language: is\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.5\n" #. TRANSLATORS: This is a test. You don't need to translate it. #: t/t0200/test.c:5 @@ -72,22 +73,31 @@ msgstr "TILRAUN: Perl tilraunastrengur" msgid "TEST: A Perl test variable %s" msgstr "TILRAUN: Perl tilraunastrengur með breytunni %s" -#. TRANSLATORS: The first '%s' is either "Reinitialized -#. existing" or "Initialized empty", the second " shared" or -#. "", and the last '%s%s' is the verbatim directory name. -#: builtin/init-db.c:355 +#: builtin/init-db.c:402 #, c-format -msgid "%s%s Git repository in %s%s\n" -msgstr "%s%s Git lind à %s%s\n" +msgid "Reinitialized existing shared Git repository in %s%s\n" +msgstr "Endurgerði Git lind à %s%s\n" -#: builtin/init-db.c:356 -msgid "Reinitialized existing" -msgstr "Endurgerði" +#: builtin/init-db.c:403 +#, c-format +msgid "Reinitialized existing Git repository in %s%s\n" +msgstr "Endurgerði Git lind à %s%s\n" + +#: builtin/init-db.c:407 +#, c-format +msgid "Initialized empty shared Git repository in %s%s\n" +msgstr "Bjó til tóma sameiginlega Git lind à %s%s\n" + +#: builtin/init-db.c:408 +#, c-format +msgid "Initialized empty Git repository in %s%s\n" +msgstr "Bjó til tóma Git lind à %s%s\n" + +#~ msgid "Reinitialized existing" +#~ msgstr "Endurgerði" -#: builtin/init-db.c:356 -msgid "Initialized empty" -msgstr "Bjó til tóma" +#~ msgid "Initialized empty" +#~ msgstr "Bjó til tóma" -#: builtin/init-db.c:357 -msgid " shared" -msgstr " sameiginlega" +#~ msgid " shared" +#~ msgstr " sameiginlega" @@ -509,7 +509,7 @@ void pp_user_info(struct pretty_print_context *pp, } } -static int is_empty_line(const char *line, int *len_p) +static int is_blank_line(const char *line, int *len_p) { int len = *len_p; while (len && isspace(line[len - 1])) @@ -518,14 +518,14 @@ static int is_empty_line(const char *line, int *len_p) return !len; } -static const char *skip_empty_lines(const char *msg) +const char *skip_blank_lines(const char *msg) { for (;;) { int linelen = get_one_line(msg); int ll = linelen; if (!linelen) break; - if (!is_empty_line(msg, &ll)) + if (!is_blank_line(msg, &ll)) break; msg += linelen; } @@ -877,7 +877,7 @@ const char *format_subject(struct strbuf *sb, const char *msg, int linelen = get_one_line(line); msg += linelen; - if (!linelen || is_empty_line(line, &linelen)) + if (!linelen || is_blank_line(line, &linelen)) break; if (!sb) @@ -896,11 +896,11 @@ static void parse_commit_message(struct format_commit_context *c) const char *msg = c->message + c->message_off; const char *start = c->message; - msg = skip_empty_lines(msg); + msg = skip_blank_lines(msg); c->subject_off = msg - start; msg = format_subject(NULL, msg, NULL); - msg = skip_empty_lines(msg); + msg = skip_blank_lines(msg); c->body_off = msg - start; c->commit_message_parsed = 1; @@ -1730,7 +1730,7 @@ void pp_remainder(struct pretty_print_context *pp, if (!linelen) break; - if (is_empty_line(line, &linelen)) { + if (is_blank_line(line, &linelen)) { if (first) continue; if (pp->fmt == CMIT_FMT_SHORT) @@ -1806,7 +1806,7 @@ void pretty_print_commit(struct pretty_print_context *pp, } /* Skip excess blank lines at the beginning of body, if any... */ - msg = skip_empty_lines(msg); + msg = skip_blank_lines(msg); /* These formats treat the title line specially. */ if (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt)) @@ -453,3 +453,40 @@ void tcl_quote_buf(struct strbuf *sb, const char *src) } strbuf_addch(sb, '"'); } + +void basic_regex_quote_buf(struct strbuf *sb, const char *src) +{ + char c; + + if (*src == '^') { + /* only beginning '^' is special and needs quoting */ + strbuf_addch(sb, '\\'); + strbuf_addch(sb, *src++); + } + if (*src == '*') + /* beginning '*' is not special, no quoting */ + strbuf_addch(sb, *src++); + + while ((c = *src++)) { + switch (c) { + case '[': + case '.': + case '\\': + case '*': + strbuf_addch(sb, '\\'); + strbuf_addch(sb, c); + break; + + case '$': + /* only the end '$' is special and needs quoting */ + if (*src == '\0') + strbuf_addch(sb, '\\'); + strbuf_addch(sb, c); + break; + + default: + strbuf_addch(sb, c); + break; + } + } +} @@ -70,5 +70,6 @@ extern char *quote_path_relative(const char *in, const char *prefix, extern void perl_quote_buf(struct strbuf *sb, const char *src); extern void python_quote_buf(struct strbuf *sb, const char *src); extern void tcl_quote_buf(struct strbuf *sb, const char *src); +extern void basic_regex_quote_buf(struct strbuf *sb, const char *src); #endif diff --git a/refs/files-backend.c b/refs/files-backend.c index 1f38076411..dac3a22297 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1725,14 +1725,14 @@ static int verify_lock(struct ref_lock *lock, errno = save_errno; return -1; } else { - hashclr(lock->old_oid.hash); + oidclr(&lock->old_oid); return 0; } } if (old_sha1 && hashcmp(lock->old_oid.hash, old_sha1)) { strbuf_addf(err, "ref %s is at %s but expected %s", lock->ref_name, - sha1_to_hex(lock->old_oid.hash), + oid_to_hex(&lock->old_oid), sha1_to_hex(old_sha1)); errno = EBUSY; return -1; diff --git a/remote-curl.c b/remote-curl.c index 672b382e5a..6b83b7783e 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -984,14 +984,11 @@ static void parse_push(struct strbuf *buf) free(specs); } -int main(int argc, const char **argv) +int cmd_main(int argc, const char **argv) { struct strbuf buf = STRBUF_INIT; int nongit; - git_setup_gettext(); - - git_extract_argv0_path(argv[0]); setup_git_directory_gently(&nongit); if (argc < 2) { error("remote-curl: usage: git remote-curl <remote> [<url>]"); diff --git a/remote-testsvn.c b/remote-testsvn.c index f05ff45298..f87bf851ba 100644 --- a/remote-testsvn.c +++ b/remote-testsvn.c @@ -284,7 +284,7 @@ static int do_command(struct strbuf *line) return 0; } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct strbuf buf = STRBUF_INIT, url_sb = STRBUF_INIT, private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT, @@ -292,7 +292,6 @@ int main(int argc, char **argv) static struct remote *remote; const char *url_in; - git_extract_argv0_path(argv[0]); setup_git_directory(); if (argc < 2 || argc > 3) { usage("git-remote-svn <remote-name> [<url>]"); diff --git a/revision.c b/revision.c index 2f60062876..edba5b79bc 100644 --- a/revision.c +++ b/revision.c @@ -1871,6 +1871,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->notes_opt.use_default_notes = 1; } else if (!strcmp(arg, "--show-signature")) { revs->show_signature = 1; + } else if (!strcmp(arg, "--no-show-signature")) { + revs->show_signature = 0; } else if (!strcmp(arg, "--show-linear-break") || starts_with(arg, "--show-linear-break=")) { if (starts_with(arg, "--show-linear-break=")) diff --git a/sequencer.c b/sequencer.c index c6362d63f3..cdfac82b11 100644 --- a/sequencer.c +++ b/sequencer.c @@ -190,7 +190,7 @@ static void write_message(struct strbuf *msgbuf, const char *filename) die_errno(_("Could not write to %s"), filename); strbuf_release(msgbuf); if (commit_lock_file(&msg_file) < 0) - die(_("Error wrapping up %s"), filename); + die(_("Error wrapping up %s."), filename); } static struct tree *empty_tree(void) @@ -225,7 +225,7 @@ static int fast_forward_to(const unsigned char *to, const unsigned char *from, if (checkout_fast_forward(from, to, 1)) exit(128); /* the callee should have complained already */ - strbuf_addf(&sb, "%s: fast-forward", action_name(opts)); + strbuf_addf(&sb, _("%s: fast-forward"), action_name(opts)); transaction = ref_transaction_begin(&err); if (!transaction || @@ -544,10 +544,8 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts) * information followed by "\n\n". */ p = strstr(msg.message, "\n\n"); - if (p) { - p += 2; - strbuf_addstr(&msgbuf, p); - } + if (p) + strbuf_addstr(&msgbuf, skip_blank_lines(p + 2)); if (opts->record_origin) { if (!has_conforming_footer(&msgbuf, NULL, 0)) @@ -697,9 +695,14 @@ static struct commit *parse_insn_line(char *bol, char *eol, struct replay_opts * * opts; we don't support arbitrary instructions */ if (action != opts->action) { - const char *action_str; - action_str = action == REPLAY_REVERT ? "revert" : "cherry-pick"; - error(_("Cannot %s during a %s"), action_str, action_name(opts)); + if (action == REPLAY_REVERT) + error((opts->action == REPLAY_REVERT) + ? _("Cannot revert during a another revert.") + : _("Cannot revert during a cherry-pick.")); + else + error((opts->action == REPLAY_REVERT) + ? _("Cannot cherry-pick during a revert.") + : _("Cannot cherry-pick during another cherry-pick.")); return NULL; } @@ -157,8 +157,8 @@ static void NORETURN die_verify_filename(const char *prefix, int diagnose_misspelt_rev) { if (!diagnose_misspelt_rev) - die("%s: no such path in the working tree.\n" - "Use 'git <command> -- <path>...' to specify paths that do not exist locally.", + die(_("%s: no such path in the working tree.\n" + "Use 'git <command> -- <path>...' to specify paths that do not exist locally."), arg); /* * Saying "'(icase)foo' does not exist in the index" when the @@ -170,9 +170,9 @@ static void NORETURN die_verify_filename(const char *prefix, maybe_die_on_misspelt_object_name(arg, prefix); /* ... or fall back the most general message. */ - die("ambiguous argument '%s': unknown revision or path not in the working tree.\n" - "Use '--' to separate paths from revisions, like this:\n" - "'git <command> [<revision>...] -- [<file>...]'", arg); + die(_("ambiguous argument '%s': unknown revision or path not in the working tree.\n" + "Use '--' to separate paths from revisions, like this:\n" + "'git <command> [<revision>...] -- [<file>...]'"), arg); } @@ -220,9 +220,9 @@ void verify_non_filename(const char *prefix, const char *arg) return; /* flag */ if (!check_filename(prefix, arg)) return; - die("ambiguous argument '%s': both revision and filename\n" - "Use '--' to separate paths from revisions, like this:\n" - "'git <command> [<revision>...] -- [<file>...]'", arg); + die(_("ambiguous argument '%s': both revision and filename\n" + "Use '--' to separate paths from revisions, like this:\n" + "'git <command> [<revision>...] -- [<file>...]'"), arg); } int get_common_dir(struct strbuf *sb, const char *gitdir) diff --git a/sh-i18n--envsubst.c b/sh-i18n--envsubst.c index 2842a22d7f..e06b2c1311 100644 --- a/sh-i18n--envsubst.c +++ b/sh-i18n--envsubst.c @@ -64,7 +64,7 @@ static void note_variables (const char *string); static void subst_from_stdin (void); int -main (int argc, char *argv[]) +cmd_main (int argc, const char *argv[]) { /* Default values for command line options. */ /* unsigned short int show_variables = 0; */ @@ -138,24 +138,13 @@ static struct commands { { NULL }, }; -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { char *prog; const char **user_argv; struct commands *cmd; int count; - git_setup_gettext(); - - git_extract_argv0_path(argv[0]); - - /* - * Always open file descriptors 0/1/2 to avoid clobbering files - * in die(). It also avoids messing up when the pipes are dup'ed - * onto stdin/stdout/stderr in the child processes we spawn. - */ - sanitize_stdfds(); - /* * Special hack to pretend to be a CVS server */ diff --git a/shortlog.h b/shortlog.h index de4f86fb97..5a326c6860 100644 --- a/shortlog.h +++ b/shortlog.h @@ -17,6 +17,7 @@ struct shortlog { char *common_repo_prefix; int email; struct string_list mailmap; + FILE *file; }; void shortlog_init(struct shortlog *log); diff --git a/show-index.c b/show-index.c index acf8d5445a..1ead41e211 100644 --- a/show-index.c +++ b/show-index.c @@ -4,15 +4,13 @@ static const char show_index_usage[] = "git show-index"; -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { int i; unsigned nr; unsigned int version; static unsigned int top_index[256]; - git_setup_gettext(); - if (argc != 1) usage(show_index_usage); if (fread(top_index, 2 * 4, 1, stdin) != 1) diff --git a/sideband.c b/sideband.c index c09929dafa..1e4d684d6c 100644 --- a/sideband.c +++ b/sideband.c @@ -13,111 +13,95 @@ * the remote died unexpectedly. A flush() concludes the stream. */ -#define PREFIX "remote:" +#define PREFIX "remote: " #define ANSI_SUFFIX "\033[K" #define DUMB_SUFFIX " " -#define FIX_SIZE 10 /* large enough for any of the above */ - int recv_sideband(const char *me, int in_stream, int out) { - unsigned pf = strlen(PREFIX); - unsigned sf; - char buf[LARGE_PACKET_MAX + 2*FIX_SIZE]; - char *suffix, *term; - int skip_pf = 0; + const char *term, *suffix; + char buf[LARGE_PACKET_MAX + 1]; + struct strbuf outbuf = STRBUF_INIT; + int retval = 0; - memcpy(buf, PREFIX, pf); term = getenv("TERM"); if (isatty(2) && term && strcmp(term, "dumb")) suffix = ANSI_SUFFIX; else suffix = DUMB_SUFFIX; - sf = strlen(suffix); - while (1) { + while (!retval) { + const char *b, *brk; int band, len; - len = packet_read(in_stream, NULL, NULL, buf + pf, LARGE_PACKET_MAX, 0); + len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX, 0); if (len == 0) break; if (len < 1) { - fprintf(stderr, "%s: protocol error: no band designator\n", me); - return SIDEBAND_PROTOCOL_ERROR; + strbuf_addf(&outbuf, + "%s%s: protocol error: no band designator", + outbuf.len ? "\n" : "", me); + retval = SIDEBAND_PROTOCOL_ERROR; + break; } - band = buf[pf] & 0xff; + band = buf[0] & 0xff; + buf[len] = '\0'; len--; switch (band) { case 3: - buf[pf] = ' '; - buf[pf+1+len] = '\0'; - fprintf(stderr, "%s\n", buf); - return SIDEBAND_REMOTE_ERROR; + strbuf_addf(&outbuf, "%s%s%s", outbuf.len ? "\n" : "", + PREFIX, buf + 1); + retval = SIDEBAND_REMOTE_ERROR; + break; case 2: - buf[pf] = ' '; - do { - char *b = buf; - int brk = 0; + b = buf + 1; - /* - * If the last buffer didn't end with a line - * break then we should not print a prefix - * this time around. - */ - if (skip_pf) { - b += pf+1; - } else { - len += pf+1; - brk += pf+1; - } - - /* Look for a line break. */ - for (;;) { - brk++; - if (brk > len) { - brk = 0; - break; - } - if (b[brk-1] == '\n' || - b[brk-1] == '\r') - break; - } + /* + * Append a suffix to each nonempty line to clear the + * end of the screen line. + * + * The output is accumulated in a buffer and + * each line is printed to stderr using + * write(2) to ensure inter-process atomicity. + */ + while ((brk = strpbrk(b, "\n\r"))) { + int linelen = brk - b; - /* - * Let's insert a suffix to clear the end - * of the screen line if a line break was - * found. Also, if we don't skip the - * prefix, then a non-empty string must be - * present too. - */ - if (brk > (skip_pf ? 0 : (pf+1 + 1))) { - char save[FIX_SIZE]; - memcpy(save, b + brk, sf); - b[brk + sf - 1] = b[brk - 1]; - memcpy(b + brk - 1, suffix, sf); - fprintf(stderr, "%.*s", brk + sf, b); - memcpy(b + brk, save, sf); - len -= brk; + if (!outbuf.len) + strbuf_addstr(&outbuf, PREFIX); + if (linelen > 0) { + strbuf_addf(&outbuf, "%.*s%s%c", + linelen, b, suffix, *brk); } else { - int l = brk ? brk : len; - fprintf(stderr, "%.*s", l, b); - len -= l; + strbuf_addch(&outbuf, *brk); } + xwrite(2, outbuf.buf, outbuf.len); + strbuf_reset(&outbuf); - skip_pf = !brk; - memmove(buf + pf+1, b + brk, len); - } while (len); - continue; + b = brk + 1; + } + + if (*b) + strbuf_addf(&outbuf, "%s%s", + outbuf.len ? "" : PREFIX, b); + break; case 1: - write_or_die(out, buf + pf+1, len); - continue; + write_or_die(out, buf + 1, len); + break; default: - fprintf(stderr, "%s: protocol error: bad band #%d\n", - me, band); - return SIDEBAND_PROTOCOL_ERROR; + strbuf_addf(&outbuf, "%s%s: protocol error: bad band #%d", + outbuf.len ? "\n" : "", me, band); + retval = SIDEBAND_PROTOCOL_ERROR; + break; } } - return 0; + + if (outbuf.len) { + strbuf_addch(&outbuf, '\n'); + xwrite(2, outbuf.buf, outbuf.len); + } + strbuf_release(&outbuf); + return retval; } /* diff --git a/submodule-config.c b/submodule-config.c index db1847ff68..077db4054f 100644 --- a/submodule-config.c +++ b/submodule-config.c @@ -377,7 +377,7 @@ static int gitmodule_sha1_from_commit(const unsigned char *commit_sha1, int ret = 0; if (is_null_sha1(commit_sha1)) { - hashcpy(gitmodules_sha1, null_sha1); + hashclr(gitmodules_sha1); return 1; } diff --git a/submodule.c b/submodule.c index abc2ac2a10..1b5cdfb7e7 100644 --- a/submodule.c +++ b/submodule.c @@ -445,7 +445,7 @@ static void collect_submodules_from_diff(struct diff_queue_struct *q, struct diff_filepair *p = q->queue[i]; if (!S_ISGITLINK(p->two->mode)) continue; - if (submodule_needs_pushing(p->two->path, p->two->sha1)) + if (submodule_needs_pushing(p->two->path, p->two->oid.hash)) string_list_insert(needs_pushing, p->two->path); } } @@ -577,7 +577,7 @@ static void submodule_collect_changed_cb(struct diff_queue_struct *q, * being moved around. */ struct string_list_item *path; path = unsorted_string_list_lookup(&changed_submodule_paths, p->two->path); - if (!path && !is_submodule_commit_present(p->two->path, p->two->sha1)) + if (!path && !is_submodule_commit_present(p->two->path, p->two->oid.hash)) string_list_append(&changed_submodule_paths, xstrdup(p->two->path)); } else { /* Submodule is new or was moved here */ diff --git a/t/helper/test-chmtime.c b/t/helper/test-chmtime.c index dfe8a83261..e760256406 100644 --- a/t/helper/test-chmtime.c +++ b/t/helper/test-chmtime.c @@ -56,7 +56,7 @@ static int timespec_arg(const char *arg, long int *set_time, int *set_eq) return 1; } -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { static int verbose; diff --git a/t/helper/test-config.c b/t/helper/test-config.c index 509aeef400..3c6d08cd09 100644 --- a/t/helper/test-config.c +++ b/t/helper/test-config.c @@ -66,7 +66,7 @@ static int iterate_cb(const char *var, const char *value, void *data) return 0; } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { int i, val; const char *v; diff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c index 707a821f03..bb72c47df5 100644 --- a/t/helper/test-ctype.c +++ b/t/helper/test-ctype.c @@ -28,7 +28,7 @@ static int is_in(const char *s, int ch) #define LOWER "abcdefghijklmnopqrstuvwxyz" #define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { TEST_CLASS(isdigit, DIGIT); TEST_CLASS(isspace, " \n\r\t"); diff --git a/t/helper/test-date.c b/t/helper/test-date.c index d9ab360909..506054bcd5 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -6,7 +6,7 @@ static const char *usage_msg = "\n" " test-date parse [date]...\n" " test-date approxidate [date]...\n"; -static void show_relative_dates(char **argv, struct timeval *now) +static void show_relative_dates(const char **argv, struct timeval *now) { struct strbuf buf = STRBUF_INIT; @@ -18,13 +18,13 @@ static void show_relative_dates(char **argv, struct timeval *now) strbuf_release(&buf); } -static void show_dates(char **argv, const char *format) +static void show_dates(const char **argv, const char *format) { struct date_mode mode; parse_date_format(format, &mode); for (; *argv; argv++) { - char *arg = *argv; + char *arg; time_t t; int tz; @@ -32,7 +32,7 @@ static void show_dates(char **argv, const char *format) * Do not use our normal timestamp parsing here, as the point * is to test the formatting code in isolation. */ - t = strtol(arg, &arg, 10); + t = strtol(*argv, &arg, 10); while (*arg == ' ') arg++; tz = atoi(arg); @@ -41,7 +41,7 @@ static void show_dates(char **argv, const char *format) } } -static void parse_dates(char **argv, struct timeval *now) +static void parse_dates(const char **argv, struct timeval *now) { struct strbuf result = STRBUF_INIT; @@ -60,7 +60,7 @@ static void parse_dates(char **argv, struct timeval *now) strbuf_release(&result); } -static void parse_approxidate(char **argv, struct timeval *now) +static void parse_approxidate(const char **argv, struct timeval *now) { for (; *argv; argv++) { time_t t; @@ -69,7 +69,7 @@ static void parse_approxidate(char **argv, struct timeval *now) } } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct timeval now; const char *x; diff --git a/t/helper/test-delta.c b/t/helper/test-delta.c index 4595cd6433..59937dc1be 100644 --- a/t/helper/test-delta.c +++ b/t/helper/test-delta.c @@ -15,7 +15,7 @@ static const char usage_str[] = "test-delta (-d|-p) <from_file> <data_file> <out_file>"; -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { int fd; struct stat st; diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c index bb53c0aa65..44f3290258 100644 --- a/t/helper/test-dump-cache-tree.c +++ b/t/helper/test-dump-cache-tree.c @@ -54,7 +54,7 @@ static int dump_cache_tree(struct cache_tree *it, return errs; } -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { struct index_state istate; struct cache_tree *another = cache_tree(); diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c index 861d28c9b6..d1689248b4 100644 --- a/t/helper/test-dump-split-index.c +++ b/t/helper/test-dump-split-index.c @@ -7,7 +7,7 @@ static void show_bit(size_t pos, void *data) printf(" %d", (int)pos); } -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { struct split_index *si; int i; diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c index 0a1c285246..50112cc858 100644 --- a/t/helper/test-dump-untracked-cache.c +++ b/t/helper/test-dump-untracked-cache.c @@ -40,7 +40,7 @@ static void dump(struct untracked_cache_dir *ucd, struct strbuf *base) strbuf_setlen(base, len); } -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { struct untracked_cache *uc; struct strbuf base = STRBUF_INIT; diff --git a/t/helper/test-fake-ssh.c b/t/helper/test-fake-ssh.c index 980de216e1..12beee99ad 100644 --- a/t/helper/test-fake-ssh.c +++ b/t/helper/test-fake-ssh.c @@ -2,7 +2,7 @@ #include "run-command.h" #include "strbuf.h" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { const char *trash_directory = getenv("TRASH_DIRECTORY"); struct strbuf buf = STRBUF_INIT; diff --git a/t/helper/test-genrandom.c b/t/helper/test-genrandom.c index 54824d0754..8d11d22d98 100644 --- a/t/helper/test-genrandom.c +++ b/t/helper/test-genrandom.c @@ -6,7 +6,7 @@ #include "git-compat-util.h" -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { unsigned long count, next = 0; unsigned char *c; diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c index cc2891dd97..7aa9440e27 100644 --- a/t/helper/test-hashmap.c +++ b/t/helper/test-hashmap.c @@ -138,7 +138,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds) * * perfhashmap method rounds -> test hashmap.[ch] performance */ -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { char line[1024]; struct hashmap map; diff --git a/t/helper/test-index-version.c b/t/helper/test-index-version.c index 05d4699c4a..f569f6b7ef 100644 --- a/t/helper/test-index-version.c +++ b/t/helper/test-index-version.c @@ -1,6 +1,6 @@ #include "cache.h" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct cache_header hdr; int version; diff --git a/t/helper/test-line-buffer.c b/t/helper/test-line-buffer.c index 1e58f0476f..81575fe2ab 100644 --- a/t/helper/test-line-buffer.c +++ b/t/helper/test-line-buffer.c @@ -50,7 +50,7 @@ static void handle_line(const char *line, struct line_buffer *stdin_buf) handle_command(line, arg + 1, stdin_buf); } -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { struct line_buffer stdin_buf = LINE_BUFFER_INIT; struct line_buffer file_buf = LINE_BUFFER_INIT; diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c index d446b8eaca..e939502863 100644 --- a/t/helper/test-match-trees.c +++ b/t/helper/test-match-trees.c @@ -1,7 +1,7 @@ #include "cache.h" #include "tree.h" -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { struct object_id hash1, hash2, shifted; struct tree *one, *two; diff --git a/t/helper/test-mergesort.c b/t/helper/test-mergesort.c index ea3b959e94..335cf6b626 100644 --- a/t/helper/test-mergesort.c +++ b/t/helper/test-mergesort.c @@ -22,7 +22,7 @@ static int compare_strings(const void *a, const void *b) return strcmp(x->text, y->text); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct line *line, *p = NULL, *lines = NULL; struct strbuf sb = STRBUF_INIT; diff --git a/t/helper/test-mktemp.c b/t/helper/test-mktemp.c index c8c54213a3..89d9b2f7be 100644 --- a/t/helper/test-mktemp.c +++ b/t/helper/test-mktemp.c @@ -3,7 +3,7 @@ */ #include "git-compat-util.h" -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { if (argc != 2) usage("Expected 1 parameter defining the temporary file template"); diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index 2c63298fab..a01430c24b 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -94,7 +94,7 @@ static void show(struct string_list *expect, int *status, const char *fmt, ...) strbuf_release(&buf); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { const char *prefix = "prefix/"; const char *usage[] = { diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c index ba805b374c..1ebe0f750c 100644 --- a/t/helper/test-path-utils.c +++ b/t/helper/test-path-utils.c @@ -156,7 +156,7 @@ static struct test_data dirname_data[] = { { NULL, NULL } }; -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) { char *buf = xmallocz(strlen(argv[2])); @@ -213,7 +213,7 @@ int main(int argc, char **argv) } if (argc >= 4 && !strcmp(argv[1], "prefix_path")) { - char *prefix = argv[2]; + const char *prefix = argv[2]; int prefix_len = strlen(prefix); int nongit_ok; setup_git_directory_gently(&nongit_ok); diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c index 7be72f0086..ae58fff359 100644 --- a/t/helper/test-prio-queue.c +++ b/t/helper/test-prio-queue.c @@ -16,7 +16,7 @@ static void show(int *v) free(v); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct prio_queue pq = { intcmp }; diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c index b25bcf139b..2a7990efc3 100644 --- a/t/helper/test-read-cache.c +++ b/t/helper/test-read-cache.c @@ -1,6 +1,6 @@ #include "cache.h" -int main (int argc, char **argv) +int cmd_main(int argc, const char **argv) { int i, cnt = 1; if (argc == 2) diff --git a/t/helper/test-regex.c b/t/helper/test-regex.c index 0dc598ecdc..b5ea8a97c5 100644 --- a/t/helper/test-regex.c +++ b/t/helper/test-regex.c @@ -1,6 +1,23 @@ #include "git-compat-util.h" +#include "gettext.h" -int main(int argc, char **argv) +struct reg_flag { + const char *name; + int flag; +}; + +static struct reg_flag reg_flags[] = { + { "EXTENDED", REG_EXTENDED }, + { "NEWLINE", REG_NEWLINE }, + { "ICASE", REG_ICASE }, + { "NOTBOL", REG_NOTBOL }, +#ifdef REG_STARTEND + { "STARTEND", REG_STARTEND }, +#endif + { NULL, 0 } +}; + +static int test_regex_bug(void) { char *pat = "[^={} \t]+"; char *str = "={}\nfred"; @@ -16,5 +33,43 @@ int main(int argc, char **argv) if (m[0].rm_so == 3) /* matches '\n' when it should not */ die("regex bug confirmed: re-build git with NO_REGEX=1"); - exit(0); + return 0; +} + +int cmd_main(int argc, const char **argv) +{ + const char *pat; + const char *str; + int flags = 0; + regex_t r; + regmatch_t m[1]; + + if (argc == 2 && !strcmp(argv[1], "--bug")) + return test_regex_bug(); + else if (argc < 3) + usage("test-regex --bug\n" + "test-regex <pattern> <string> [<options>]"); + + argv++; + pat = *argv++; + str = *argv++; + while (*argv) { + struct reg_flag *rf; + for (rf = reg_flags; rf->name; rf++) + if (!strcmp(*argv, rf->name)) { + flags |= rf->flag; + break; + } + if (!rf->name) + die("do not recognize %s", *argv); + argv++; + } + git_setup_gettext(); + + if (regcomp(&r, pat, flags)) + die("failed regcomp() for pattern '%s'", pat); + if (regexec(&r, str, 1, m, 0)) + return 1; + + return 0; } diff --git a/t/helper/test-revision-walking.c b/t/helper/test-revision-walking.c index 3d0313354b..b8e6fe1d00 100644 --- a/t/helper/test-revision-walking.c +++ b/t/helper/test-revision-walking.c @@ -45,7 +45,7 @@ static int run_revision_walk(void) return got_revision; } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { if (argc < 2) return 1; diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c index 30a64a98dc..c71ea4f759 100644 --- a/t/helper/test-run-command.c +++ b/t/helper/test-run-command.c @@ -49,7 +49,7 @@ static int task_finished(int result, return 1; } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct child_process proc = CHILD_PROCESS_INIT; int jobs; diff --git a/t/helper/test-scrap-cache-tree.c b/t/helper/test-scrap-cache-tree.c index 6efee31a48..5b2fd09908 100644 --- a/t/helper/test-scrap-cache-tree.c +++ b/t/helper/test-scrap-cache-tree.c @@ -5,7 +5,7 @@ static struct lock_file index_lock; -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { hold_locked_index(&index_lock, 1); if (read_cache() < 0) diff --git a/t/helper/test-sha1-array.c b/t/helper/test-sha1-array.c index 60ea1d5f14..09f7790971 100644 --- a/t/helper/test-sha1-array.c +++ b/t/helper/test-sha1-array.c @@ -6,7 +6,7 @@ static void print_sha1(const unsigned char sha1[20], void *data) puts(sha1_to_hex(sha1)); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct sha1_array array = SHA1_ARRAY_INIT; struct strbuf line = STRBUF_INIT; diff --git a/t/helper/test-sha1.c b/t/helper/test-sha1.c index e57eae10bf..a1c13f54ec 100644 --- a/t/helper/test-sha1.c +++ b/t/helper/test-sha1.c @@ -1,6 +1,6 @@ #include "cache.h" -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { git_SHA_CTX ctx; unsigned char sha1[20]; diff --git a/t/helper/test-sigchain.c b/t/helper/test-sigchain.c index e499fce60f..b71edbd442 100644 --- a/t/helper/test-sigchain.c +++ b/t/helper/test-sigchain.c @@ -13,7 +13,7 @@ X(two) X(three) #undef X -int main(int argc, char **argv) { +int cmd_main(int argc, const char **argv) { sigchain_push(SIGTERM, one); sigchain_push(SIGTERM, two); sigchain_push(SIGTERM, three); diff --git a/t/helper/test-string-list.c b/t/helper/test-string-list.c index 14bdf9d215..4a68967bd1 100644 --- a/t/helper/test-string-list.c +++ b/t/helper/test-string-list.c @@ -41,7 +41,7 @@ static int prefix_cb(struct string_list_item *item, void *cb_data) return starts_with(item->string, prefix); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { if (argc == 5 && !strcmp(argv[1], "split")) { struct string_list list = STRING_LIST_INIT_DUP; diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c index dab8c27768..61049b87a0 100644 --- a/t/helper/test-submodule-config.c +++ b/t/helper/test-submodule-config.c @@ -2,7 +2,7 @@ #include "submodule-config.h" #include "submodule.h" -static void die_usage(int argc, char **argv, const char *msg) +static void die_usage(int argc, const char **argv, const char *msg) { fprintf(stderr, "%s\n", msg); fprintf(stderr, "Usage: %s [<commit> <submodulepath>] ...\n", argv[0]); @@ -14,9 +14,9 @@ static int git_test_config(const char *var, const char *value, void *cb) return parse_submodule_config_option(var, value); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { - char **arg = argv; + const char **arg = argv; int my_argc = argc; int output_url = 0; int lookup_name = 0; @@ -49,7 +49,7 @@ int main(int argc, char **argv) path_or_name = arg[1]; if (commit[0] == '\0') - hashcpy(commit_sha1, null_sha1); + hashclr(commit_sha1); else if (get_sha1(commit, commit_sha1) < 0) die_usage(argc, argv, "Commit not found."); diff --git a/t/helper/test-subprocess.c b/t/helper/test-subprocess.c index 56881a0324..30c5765bfc 100644 --- a/t/helper/test-subprocess.c +++ b/t/helper/test-subprocess.c @@ -1,7 +1,7 @@ #include "cache.h" #include "run-command.h" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct child_process cp = CHILD_PROCESS_INIT; int nogit = 0; diff --git a/t/helper/test-svn-fe.c b/t/helper/test-svn-fe.c index 120ec96b0d..7667c0803f 100644 --- a/t/helper/test-svn-fe.c +++ b/t/helper/test-svn-fe.c @@ -11,7 +11,7 @@ static const char test_svnfe_usage[] = "test-svn-fe (<dumpfile> | [-d] <preimage> <delta> <len>)"; -static int apply_delta(int argc, char *argv[]) +static int apply_delta(int argc, const char **argv) { struct line_buffer preimage = LINE_BUFFER_INIT; struct line_buffer delta = LINE_BUFFER_INIT; @@ -35,7 +35,7 @@ static int apply_delta(int argc, char *argv[]) return 0; } -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { if (argc == 2) { if (svndump_init(argv[1])) diff --git a/t/helper/test-urlmatch-normalization.c b/t/helper/test-urlmatch-normalization.c index 090bf219a7..49b6e836be 100644 --- a/t/helper/test-urlmatch-normalization.c +++ b/t/helper/test-urlmatch-normalization.c @@ -1,7 +1,7 @@ #include "git-compat-util.h" #include "urlmatch.h" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { const char usage[] = "test-urlmatch-normalization [-p | -l] <url1> | <url1> <url2>"; char *url1, *url2; diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c index 578b164fe6..52be876fed 100644 --- a/t/helper/test-wildmatch.c +++ b/t/helper/test-wildmatch.c @@ -1,6 +1,6 @@ #include "cache.h" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { int i; for (i = 2; i < argc; i++) { diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh index 340534c064..f9cbd47931 100644 --- a/t/lib-git-daemon.sh +++ b/t/lib-git-daemon.sh @@ -82,8 +82,7 @@ stop_git_daemon() { kill "$GIT_DAEMON_PID" wait "$GIT_DAEMON_PID" >&3 2>&4 ret=$? - # expect exit with status 143 = 128+15 for signal TERM=15 - if test $ret -ne 143 + if test_match_signal 15 $? then error "git daemon exited with status: $ret" fi diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index 9a96e1566d..25a77ee5cb 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -29,6 +29,7 @@ set_fake_editor () { */COMMIT_EDITMSG) test -z "$EXPECT_HEADER_COUNT" || test "$EXPECT_HEADER_COUNT" = "$(sed -n '1s/^# This is a combination of \(.*\) commits\./\1/p' < "$1")" || + test "# # GETTEXT POISON #" = "$(sed -n '1p' < "$1")" || exit test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1" test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1" diff --git a/t/perf/README b/t/perf/README index 8848c14619..49ea4349be 100644 --- a/t/perf/README +++ b/t/perf/README @@ -115,8 +115,16 @@ After that you will want to use some of the following: At least one of the first two is required! -You can use test_expect_success as usual. For actual performance -tests, use +You can use test_expect_success as usual. In both test_expect_success +and in test_perf, running "git" points to the version that is being +perf-tested. The $MODERN_GIT variable points to the git wrapper for the +currently checked-out version (i.e., the one that matches the t/perf +scripts you are running). This is useful if your setup uses commands +that only work with newer versions of git than what you might want to +test (but obviously your new commands must still create a state that can +be used by the older version of git you are testing). + +For actual performance tests, use test_perf 'descriptive string' ' command1 && diff --git a/t/perf/p4211-line-log.sh b/t/perf/p4211-line-log.sh index 3d074b0e41..b7ff68d4fa 100755 --- a/t/perf/p4211-line-log.sh +++ b/t/perf/p4211-line-log.sh @@ -23,11 +23,11 @@ test_perf 'git log --follow (baseline for -M)' ' git log --oneline --follow -- "$file" >/dev/null ' -test_perf 'git log -L' ' - git log -L 1:"$file" >/dev/null +test_perf 'git log -L (renames off)' ' + git log --no-renames -L 1:"$file" >/dev/null ' -test_perf 'git log -M -L' ' +test_perf 'git log -L (renames on)' ' git log -M -L 1:"$file" >/dev/null ' diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index 773f955d4a..46f08ee087 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -52,6 +52,9 @@ TEST_NO_MALLOC_CHECK=t # need to export them for test_perf subshells export TEST_DIRECTORY TRASH_DIRECTORY GIT_BUILD_DIR GIT_TEST_CMP +MODERN_GIT=$GIT_BUILD_DIR/bin-wrappers/git +export MODERN_GIT + perf_results_dir=$TEST_OUTPUT_DIRECTORY/test-results mkdir -p "$perf_results_dir" rm -f "$perf_results_dir"/$(basename "$0" .sh).subtests @@ -81,7 +84,7 @@ test_perf_create_repo_from () { repo="$1" source="$2" source_git="$(git -C "$source" rev-parse --git-dir)" - objects_dir="$(git -C "$source" rev-parse --git-path objects)" + objects_dir="$("$MODERN_GIT" -C "$source" rev-parse --git-path objects)" mkdir -p "$repo/.git" ( cd "$source" && diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh index e7f27ebbc1..46042f1f13 100755 --- a/t/t0005-signals.sh +++ b/t/t0005-signals.sh @@ -11,12 +11,13 @@ EOF test_expect_success 'sigchain works' ' { test-sigchain >actual; ret=$?; } && - case "$ret" in - 143) true ;; # POSIX w/ SIGTERM=15 - 271) true ;; # ksh w/ SIGTERM=15 - 3) true ;; # Windows - *) false ;; - esac && + { + # Signal death by raise() on Windows acts like exit(3), + # regardless of the signal number. So we must allow that + # as well as the normal signal check. + test_match_signal 15 "$ret" || + test "$ret" = 3 + } && test_cmp expect actual ' @@ -41,12 +42,12 @@ test_expect_success 'create blob' ' test_expect_success !MINGW 'a constipated git dies with SIGPIPE' ' OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) && - test "$OUT" -eq 141 + test_match_signal 13 "$OUT" ' test_expect_success !MINGW 'a constipated git dies with SIGPIPE even if parent ignores it' ' OUT=$( ((trap "" PIPE; large_git; echo $? 1>&3) | :) 3>&1 ) && - test "$OUT" -eq 141 + test_match_signal 13 "$OUT" ' test_done diff --git a/t/t0006-date.sh b/t/t0006-date.sh index 04ce53509c..4c8cf58512 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -31,7 +31,7 @@ check_show () { format=$1 time=$2 expect=$3 - test_expect_${4:-success} "show date ($format:$time)" ' + test_expect_success $4 "show date ($format:$time)" ' echo "$time -> $expect" >expect && test-date show:$format "$time" >actual && test_cmp expect actual @@ -50,8 +50,8 @@ check_show iso-local "$TIME" '2016-06-15 14:13:20 +0000' # arbitrary time absurdly far in the future FUTURE="5758122296 -0400" -check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" -check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +0000" +check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" LONG_IS_64BIT +check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +0000" LONG_IS_64BIT check_parse() { echo "$1 -> $2" >expect diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh index b425f3a0d2..d27f438bf4 100755 --- a/t/t0008-ignores.sh +++ b/t/t0008-ignores.sh @@ -34,7 +34,7 @@ expect_from_stdin () { test_stderr () { expected="$1" expect_in stderr "$1" && - test_cmp "$HOME/expected-stderr" "$HOME/stderr" + test_i18ncmp "$HOME/expected-stderr" "$HOME/stderr" } broken_c_unquote () { @@ -47,7 +47,7 @@ broken_c_unquote_verbose () { stderr_contains () { regexp="$1" - if grep "$regexp" "$HOME/stderr" + if test_i18ngrep "$regexp" "$HOME/stderr" then return 0 else diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh index 5ed69a6f56..991ed2a48d 100755 --- a/t/t0070-fundamental.sh +++ b/t/t0070-fundamental.sh @@ -31,7 +31,7 @@ test_expect_success 'git_mkstemps_mode does not fail if fd 0 is not open' ' test_expect_success 'check for a bug in the regex routines' ' # if this test fails, re-build git with NO_REGEX=1 - test-regex + test-regex --bug ' test_done diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index 0c74beedd2..e5fa235d3a 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -244,10 +244,10 @@ test_expect_success 'print errors when failed to update worktree' ' error: The following untracked working tree files would be overwritten by checkout: sub/added sub/addedtoo -Please move or remove them before you can switch branches. +Please move or remove them before you switch branches. Aborting EOF - test_cmp expected actual + test_i18ncmp expected actual ' test_expect_success 'checkout without --ignore-skip-worktree-bits' ' diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index d934a24417..923bfc5a26 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -886,7 +886,7 @@ test_expect_success !MINGW 'get --path copes with unset $HOME' ' git config --get --path path.normal >>result && git config --get --path path.trailingtilde >>result ) && - grep "[Ff]ailed to expand.*~/" msg && + test_i18ngrep "[Ff]ailed to expand.*~/" msg && test_cmp expect result ' @@ -1126,7 +1126,7 @@ test_expect_success 'barf on syntax error' ' key garbage EOF test_must_fail git config --get section.key >actual 2>error && - grep " line 3 " error + test_i18ngrep " line 3 " error ' test_expect_success 'barf on incomplete section header' ' @@ -1136,7 +1136,7 @@ test_expect_success 'barf on incomplete section header' ' key = value EOF test_must_fail git config --get section.key >actual 2>error && - grep " line 2 " error + test_i18ngrep " line 2 " error ' test_expect_success 'barf on incomplete string' ' @@ -1146,7 +1146,7 @@ test_expect_success 'barf on incomplete string' ' key = "value string EOF test_must_fail git config --get section.key >actual 2>error && - grep " line 3 " error + test_i18ngrep " line 3 " error ' test_expect_success 'urlmatch' ' diff --git a/t/t1307-config-blob.sh b/t/t1307-config-blob.sh index 3c6791e6be..eed31ffa30 100755 --- a/t/t1307-config-blob.sh +++ b/t/t1307-config-blob.sh @@ -61,10 +61,7 @@ test_expect_success 'parse errors in blobs are properly attributed' ' git commit -m broken && test_must_fail git config --blob=HEAD:config some.value 2>err && - - # just grep for our token as the exact error message is likely to - # change or be internationalized - grep "HEAD:config" err + test_i18ngrep "HEAD:config" err ' test_expect_success 'can parse blob ending with CR' ' diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh index cf716b469f..7655c94c28 100755 --- a/t/t1308-config-set.sh +++ b/t/t1308-config-set.sh @@ -197,14 +197,14 @@ test_expect_success 'proper error on error in default config files' ' echo "[" >>.git/config && echo "fatal: bad config line 34 in file .git/config" >expect && test_expect_code 128 test-config get_value foo.bar 2>actual && - test_cmp expect actual + test_i18ncmp expect actual ' test_expect_success 'proper error on error in custom config files' ' echo "[" >>syntax-error && echo "fatal: bad config line 1 in file syntax-error" >expect && test_expect_code 128 test-config configset_get_value foo.bar syntax-error 2>actual && - test_cmp expect actual + test_i18ncmp expect actual ' test_expect_success 'check line errors for malformed values' ' @@ -233,11 +233,19 @@ cmdline_config="'foo.bar=from-cmdline'" test_expect_success 'iteration shows correct origins' ' echo "[foo]bar = from-repo" >.git/config && echo "[foo]bar = from-home" >.gitconfig && + if test_have_prereq MINGW + then + # Use Windows path (i.e. *not* $HOME) + HOME_GITCONFIG=$(pwd)/.gitconfig + else + # Do not get fooled by symbolic links, i.e. $HOME != $(pwd) + HOME_GITCONFIG=$HOME/.gitconfig + fi && cat >expect <<-EOF && key=foo.bar value=from-home origin=file - name=$HOME/.gitconfig + name=$HOME_GITCONFIG scope=global key=foo.bar diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index af1b20dd5c..75fa6548c4 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -361,7 +361,7 @@ test_expect_success 'stdin test setup' ' test_expect_success '-z fails without --stdin' ' test_must_fail git update-ref -z $m $m $m 2>err && - grep "usage: git update-ref" err + test_i18ngrep "usage: git update-ref" err ' test_expect_success 'stdin works with no input' ' diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh index 86c2ff255d..79a0251efa 100755 --- a/t/t1506-rev-parse-diagnosis.sh +++ b/t/t1506-rev-parse-diagnosis.sh @@ -106,7 +106,7 @@ test_expect_success 'incorrect revision id' ' test_must_fail git rev-parse foobar:file.txt 2>error && grep "Invalid object name '"'"'foobar'"'"'." error && test_must_fail git rev-parse foobar 2> error && - grep "unknown revision or path not in the working tree." error + test_i18ngrep "unknown revision or path not in the working tree." error ' test_expect_success 'incorrect file in sha1:path' ' diff --git a/t/t2010-checkout-ambiguous.sh b/t/t2010-checkout-ambiguous.sh index 87bdf9c96b..e76e84afbb 100755 --- a/t/t2010-checkout-ambiguous.sh +++ b/t/t2010-checkout-ambiguous.sh @@ -49,7 +49,7 @@ test_expect_success 'disambiguate checking out from a tree-ish' ' test_expect_success 'accurate error message with more than one ref' ' test_must_fail git checkout HEAD master -- 2>actual && - grep 2 actual && + test_i18ngrep 2 actual && test_i18ngrep "one reference expected, 2 given" actual ' diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index 2741262369..2131fb2a56 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -124,7 +124,7 @@ test_expect_success 'checkout -b to @{-1} fails with the right branch name' ' git checkout branch2 && echo >expect "fatal: A branch named '\''branch1'\'' already exists." && test_must_fail git checkout -b @{-1} 2>actual && - test_cmp expect actual + test_i18ncmp expect actual ' test_expect_success 'checkout -B to an existing branch resets branch to HEAD' ' diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index f3e3b6cf2e..ac9c764799 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -550,7 +550,7 @@ If you wanted to make '"'master'"' track '"'origin/master'"', do this: git branch -d origin/master git branch --set-upstream-to origin/master EOF - test_cmp expected actual + test_i18ncmp expected actual ' test_expect_success '--set-upstream with two args only shows the deprecation message' ' @@ -559,7 +559,7 @@ test_expect_success '--set-upstream with two args only shows the deprecation mes cat >expected <<EOF && The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to EOF - test_cmp expected actual + test_i18ncmp expected actual ' test_expect_success '--set-upstream with one arg only shows the deprecation message if the branch existed' ' @@ -568,7 +568,7 @@ test_expect_success '--set-upstream with one arg only shows the deprecation mess cat >expected <<EOF && The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to EOF - test_cmp expected actual + test_i18ncmp expected actual ' test_expect_success '--set-upstream-to notices an error to set branch as own upstream' ' diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh index 912a6635a8..7f3ec47241 100755 --- a/t/t3201-branch-contains.sh +++ b/t/t3201-branch-contains.sh @@ -156,7 +156,7 @@ test_expect_success 'branch --merged with --verbose' ' * topic 2c939f4 [ahead 1] foo zzz c77a0a9 second on master EOF - test_cmp expect actual + test_i18ncmp expect actual ' test_done diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh index d5572121da..6967436327 100755 --- a/t/t3310-notes-merge-manual-resolve.sh +++ b/t/t3310-notes-merge-manual-resolve.sh @@ -178,7 +178,7 @@ test_expect_success 'merge z into m (== y) with default ("manual") resolver => C git config core.notesRef refs/notes/m && test_must_fail git notes merge z >output && # Output should point to where to resolve conflicts - grep -q "\\.git/NOTES_MERGE_WORKTREE" output && + test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && @@ -381,7 +381,7 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol git config core.notesRef refs/notes/m && test_must_fail git notes merge z >output && # Output should point to where to resolve conflicts - grep -q "\\.git/NOTES_MERGE_WORKTREE" output && + test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && @@ -415,7 +415,7 @@ git rev-parse refs/notes/z > pre_merge_z test_expect_success 'redo merge of z into m (== y) with default ("manual") resolver => Conflicting 3-way merge' ' test_must_fail git notes merge z >output && # Output should point to where to resolve conflicts - grep -q "\\.git/NOTES_MERGE_WORKTREE" output && + test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && @@ -496,7 +496,7 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol git update-ref refs/notes/m refs/notes/y && test_must_fail git notes merge z >output && # Output should point to where to resolve conflicts - grep -q "\\.git/NOTES_MERGE_WORKTREE" output && + test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && diff --git a/t/t3320-notes-merge-worktrees.sh b/t/t3320-notes-merge-worktrees.sh index 1f71d589f5..6e0511596b 100755 --- a/t/t3320-notes-merge-worktrees.sh +++ b/t/t3320-notes-merge-worktrees.sh @@ -52,7 +52,7 @@ test_expect_success 'merge z into y while mid-merge in another workdir fails' ' cd worktree && git config core.notesRef refs/notes/y && test_must_fail git notes merge z 2>err && - grep "A notes merge into refs/notes/y is already in-progress at" err + test_i18ngrep "A notes merge into refs/notes/y is already in-progress at" err ) && test_path_is_missing .git/worktrees/worktree/NOTES_MERGE_REF ' @@ -62,7 +62,7 @@ test_expect_success 'merge z into x while mid-merge on y succeeds' ' cd worktree2 && git config core.notesRef refs/notes/x && test_must_fail git notes merge z 2>&1 >out && - grep "Automatic notes merge failed" out && + test_i18ngrep "Automatic notes merge failed" out && grep -v "A notes merge into refs/notes/x is already in-progress in" out ) && echo "ref: refs/notes/x" >expect && diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 47b5682662..f5fd15e559 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -136,8 +136,8 @@ test_expect_success 'setup: recover' ' test_expect_success 'Show verbose error when HEAD could not be detached' ' >B && test_must_fail git rebase topic 2>output.err >output.out && - grep "The following untracked working tree files would be overwritten by checkout:" output.err && - grep B output.err + test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" output.err && + test_i18ngrep B output.err ' rm -f B diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 66348f11d1..3532c482fc 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -60,7 +60,7 @@ test_expect_success 'setup' ' test_commit P fileP ' -# "exec" commands are ran with the user shell by default, but this may +# "exec" commands are run with the user shell by default, but this may # be non-POSIX. For example, if SHELL=zsh then ">file" doesn't work # to create a file. Unsetting SHELL avoids such non-portable behavior # in tests. It must be exported for it to take effect where needed. @@ -219,9 +219,9 @@ test_expect_success 'abort with error when new base cannot be checked out' ' git commit -m "remove file in base" && set_fake_editor && test_must_fail git rebase -i master > output 2>&1 && - grep "The following untracked working tree files would be overwritten by checkout:" \ + test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" \ output && - grep "file1" output && + test_i18ngrep "file1" output && test_path_is_missing .git/rebase-merge && git reset --hard HEAD^ ' @@ -540,7 +540,7 @@ test_expect_success 'clean error after failed "exec"' ' echo "edited again" > file7 && git add file7 && test_must_fail git rebase --continue 2>error && - grep "You have staged changes in your working tree." error + test_i18ngrep "You have staged changes in your working tree." error ' test_expect_success 'rebase a detached HEAD' ' @@ -1060,7 +1060,7 @@ test_expect_success 'todo count' ' EOF test_set_editor "$(pwd)/dump-raw.sh" && git rebase -i HEAD~4 >actual && - grep "^# Rebase ..* onto ..* ([0-9]" actual + test_i18ngrep "^# Rebase ..* onto ..* ([0-9]" actual ' test_expect_success 'rebase -i commits that overwrite untracked files (pick)' ' @@ -1160,7 +1160,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = ignore' ' FAKE_LINES="1 2 3 4" \ git rebase -i --root 2>actual && test D = $(git cat-file commit HEAD | sed -ne \$p) && - test_cmp expect actual + test_i18ncmp expect actual ' cat >expect <<EOF @@ -1181,7 +1181,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = warn' ' set_fake_editor && FAKE_LINES="1 2 3 4" \ git rebase -i --root 2>actual && - test_cmp expect actual && + test_i18ncmp expect actual && test D = $(git cat-file commit HEAD | sed -ne \$p) ' @@ -1205,7 +1205,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' ' set_fake_editor && test_must_fail env FAKE_LINES="1 2 4" \ git rebase -i --root 2>actual && - test_cmp expect actual && + test_i18ncmp expect actual && cp .git/rebase-merge/git-rebase-todo.backup \ .git/rebase-merge/git-rebase-todo && FAKE_LINES="1 2 drop 3 4 drop 5" \ @@ -1228,7 +1228,7 @@ test_expect_success 'static check of bad command' ' set_fake_editor && test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \ git rebase -i --root 2>actual && - test_cmp expect actual && + test_i18ncmp expect actual && FAKE_LINES="1 2 3 drop 4 5" git rebase --edit-todo && git rebase --continue && test E = $(git cat-file commit HEAD | sed -ne \$p) && @@ -1263,7 +1263,7 @@ test_expect_success 'static check of bad SHA-1' ' set_fake_editor && test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \ git rebase -i --root 2>actual && - test_cmp expect actual && + test_i18ncmp expect actual && FAKE_LINES="1 2 4 5 6" git rebase --edit-todo && git rebase --continue && test E = $(git cat-file commit HEAD | sed -ne \$p) diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh index 944154b2e0..532ff5cbd1 100755 --- a/t/t3420-rebase-autostash.sh +++ b/t/t3420-rebase-autostash.sh @@ -192,4 +192,35 @@ test_expect_success 'abort rebase -i with --autostash' ' test_cmp expected file0 ' +test_expect_success 'restore autostash on editor failure' ' + test_when_finished "git reset --hard" && + echo uncommitted-content >file0 && + ( + test_set_editor "false" && + test_must_fail git rebase -i --autostash HEAD^ + ) && + echo uncommitted-content >expected && + test_cmp expected file0 +' + +test_expect_success 'autostash is saved on editor failure with conflict' ' + test_when_finished "git reset --hard" && + echo uncommitted-content >file0 && + ( + write_script abort-editor.sh <<-\EOF && + echo conflicting-content >file0 + exit 1 + EOF + test_set_editor "$(pwd)/abort-editor.sh" && + test_must_fail git rebase -i --autostash HEAD^ && + rm -f abort-editor.sh + ) && + echo conflicting-content >expected && + test_cmp expected file0 && + git checkout file0 && + git stash pop && + echo uncommitted-content >expected && + test_cmp expected file0 +' + test_done diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh new file mode 100755 index 0000000000..3780877e4e --- /dev/null +++ b/t/t3427-rebase-subtree.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +test_description='git rebase tests for -Xsubtree + +This test runs git rebase and tests the subtree strategy. +' +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-rebase.sh + +commit_message() { + git log --pretty=format:%s -1 "$1" +} + +test_expect_success 'setup' ' + test_commit README && + mkdir files && + ( + cd files && + git init && + test_commit master1 && + test_commit master2 && + test_commit master3 + ) && + git fetch files master && + git branch files-master FETCH_HEAD && + git read-tree --prefix=files_subtree files-master && + git checkout -- files_subtree && + tree=$(git write-tree) && + head=$(git rev-parse HEAD) && + rev=$(git rev-parse --verify files-master^0) && + commit=$(git commit-tree -p $head -p $rev -m "Add subproject master" $tree) && + git update-ref HEAD $commit && + ( + cd files_subtree && + test_commit master4 + ) && + test_commit files_subtree/master5 +' + +# FAILURE: Does not preserve master4. +test_expect_failure 'Rebase -Xsubtree --preserve-merges --onto commit 4' ' + reset_rebase && + git checkout -b rebase-preserve-merges-4 master && + git filter-branch --prune-empty -f --subdirectory-filter files_subtree && + git commit -m "Empty commit" --allow-empty && + git rebase -Xsubtree=files_subtree --preserve-merges --onto files-master master && + verbose test "$(commit_message HEAD~)" = "files_subtree/master4" +' + +# FAILURE: Does not preserve master5. +test_expect_failure 'Rebase -Xsubtree --preserve-merges --onto commit 5' ' + reset_rebase && + git checkout -b rebase-preserve-merges-5 master && + git filter-branch --prune-empty -f --subdirectory-filter files_subtree && + git commit -m "Empty commit" --allow-empty && + git rebase -Xsubtree=files_subtree --preserve-merges --onto files-master master && + verbose test "$(commit_message HEAD)" = "files_subtree/master5" +' + +# FAILURE: Does not preserve master4. +test_expect_failure 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 4' ' + reset_rebase && + git checkout -b rebase-keep-empty-4 master && + git filter-branch --prune-empty -f --subdirectory-filter files_subtree && + git commit -m "Empty commit" --allow-empty && + git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master && + verbose test "$(commit_message HEAD~2)" = "files_subtree/master4" +' + +# FAILURE: Does not preserve master5. +test_expect_failure 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 5' ' + reset_rebase && + git checkout -b rebase-keep-empty-5 master && + git filter-branch --prune-empty -f --subdirectory-filter files_subtree && + git commit -m "Empty commit" --allow-empty && + git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master && + verbose test "$(commit_message HEAD~)" = "files_subtree/master5" +' + +# FAILURE: Does not preserve Empty. +test_expect_failure 'Rebase -Xsubtree --keep-empty --preserve-merges --onto empty commit' ' + reset_rebase && + git checkout -b rebase-keep-empty-empty master && + git filter-branch --prune-empty -f --subdirectory-filter files_subtree && + git commit -m "Empty commit" --allow-empty && + git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master && + verbose test "$(commit_message HEAD)" = "Empty commit" +' + +# FAILURE: fatal: Could not parse object +test_expect_failure 'Rebase -Xsubtree --onto commit 4' ' + reset_rebase && + git checkout -b rebase-onto-4 master && + git filter-branch --prune-empty -f --subdirectory-filter files_subtree && + git commit -m "Empty commit" --allow-empty && + git rebase -Xsubtree=files_subtree --onto files-master master && + verbose test "$(commit_message HEAD~2)" = "files_subtree/master4" +' + +# FAILURE: fatal: Could not parse object +test_expect_failure 'Rebase -Xsubtree --onto commit 5' ' + reset_rebase && + git checkout -b rebase-onto-5 master && + git filter-branch --prune-empty -f --subdirectory-filter files_subtree && + git commit -m "Empty commit" --allow-empty && + git rebase -Xsubtree=files_subtree --onto files-master master && + verbose test "$(commit_message HEAD~)" = "files_subtree/master5" +' +# FAILURE: fatal: Could not parse object +test_expect_failure 'Rebase -Xsubtree --onto empty commit' ' + reset_rebase && + git checkout -b rebase-onto-empty master && + git filter-branch --prune-empty -f --subdirectory-filter files_subtree && + git commit -m "Empty commit" --allow-empty && + git rebase -Xsubtree=files_subtree --onto files-master master && + verbose test "$(commit_message HEAD)" = "Empty commit" +' + +test_done diff --git a/t/t4026-color.sh b/t/t4026-color.sh index 2b32c4fbe6..ec78c5e3ac 100755 --- a/t/t4026-color.sh +++ b/t/t4026-color.sh @@ -50,14 +50,19 @@ test_expect_success 'attr negation' ' color "nobold nodim noul noblink noreverse" "[22;24;25;27m" ' +test_expect_success '"no-" variant of negation' ' + color "no-bold no-blink" "[22;25m" +' + test_expect_success 'long color specification' ' color "254 255 bold dim ul blink reverse" "[1;2;4;5;7;38;5;254;48;5;255m" ' test_expect_success 'absurdly long color specification' ' color \ - "#ffffff #ffffff bold nobold dim nodim ul noul blink noblink reverse noreverse" \ - "[1;2;4;5;7;22;24;25;27;38;2;255;255;255;48;2;255;255;255m" + "#ffffff #ffffff bold nobold dim nodim italic noitalic + ul noul blink noblink reverse noreverse strike nostrike" \ + "[1;2;3;4;5;7;9;22;23;24;25;27;29;38;2;255;255;255;48;2;255;255;255m" ' test_expect_success '0-7 are aliases for basic ANSI color names' ' diff --git a/t/t4153-am-resume-override-opts.sh b/t/t4153-am-resume-override-opts.sh index 7c013d84d5..8ea22d1bcb 100755 --- a/t/t4153-am-resume-override-opts.sh +++ b/t/t4153-am-resume-override-opts.sh @@ -53,7 +53,7 @@ test_expect_success '--no-quiet overrides --quiet' ' # Applying side1 will be quiet. test_must_fail git am --quiet side[123].eml >out && test_path_is_dir .git/rebase-apply && - ! test_i18ngrep "^Applying: " out && + test_i18ngrep ! "^Applying: " out && echo side1 >file && git add file && diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh index a9773658f0..ae08b57712 100755 --- a/t/t4201-shortlog.sh +++ b/t/t4201-shortlog.sh @@ -184,4 +184,10 @@ test_expect_success 'shortlog with revision pseudo options' ' git shortlog --exclude=refs/heads/m* --all ' +test_expect_success 'shortlog with --output=<file>' ' + git shortlog --output=shortlog -1 master >output && + test ! -s output && + test_line_count = 3 shortlog +' + test_done diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 128ba93537..803e1e6b8f 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -860,12 +860,15 @@ test_expect_success 'dotdot is a parent directory' ' test_cmp expect actual ' -test_expect_success GPG 'log --graph --show-signature' ' +test_expect_success GPG 'setup signed branch' ' test_when_finished "git reset --hard && git checkout master" && git checkout -b signed master && echo foo >foo && git add foo && - git commit -S -m signed_commit && + git commit -S -m signed_commit +' + +test_expect_success GPG 'log --graph --show-signature' ' git log --graph --show-signature -n1 signed >actual && grep "^| gpg: Signature made" actual && grep "^| gpg: Good signature" actual @@ -890,6 +893,31 @@ test_expect_success GPG 'log --graph --show-signature for merged tag' ' grep "^| | gpg: Good signature" actual ' +test_expect_success GPG '--no-show-signature overrides --show-signature' ' + git log -1 --show-signature --no-show-signature signed >actual && + ! grep "^gpg:" actual +' + +test_expect_success GPG 'log.showsignature=true behaves like --show-signature' ' + test_config log.showsignature true && + git log -1 signed >actual && + grep "gpg: Signature made" actual && + grep "gpg: Good signature" actual +' + +test_expect_success GPG '--no-show-signature overrides log.showsignature=true' ' + test_config log.showsignature true && + git log -1 --no-show-signature signed >actual && + ! grep "^gpg:" actual +' + +test_expect_success GPG '--show-signature overrides log.showsignature=false' ' + test_config log.showsignature false && + git log -1 --show-signature signed >actual && + grep "gpg: Signature made" actual && + grep "gpg: Good signature" actual +' + test_expect_success 'log --graph --no-walk is forbidden' ' test_must_fail git log --graph --no-walk ' diff --git a/t/t4208-log-magic-pathspec.sh b/t/t4208-log-magic-pathspec.sh index d8f23f488e..001343e2fc 100755 --- a/t/t4208-log-magic-pathspec.sh +++ b/t/t4208-log-magic-pathspec.sh @@ -18,7 +18,7 @@ test_expect_success '"git log :/" should not be ambiguous' ' test_expect_success '"git log :/a" should be ambiguous (applied both rev and worktree)' ' : >a && test_must_fail git log :/a 2>error && - grep ambiguous error + test_i18ngrep ambiguous error ' test_expect_success '"git log :/a -- " should not be ambiguous' ' @@ -31,7 +31,7 @@ test_expect_success '"git log -- :/a" should not be ambiguous' ' test_expect_success '"git log :" should be ambiguous' ' test_must_fail git log : 2>error && - grep ambiguous error + test_i18ngrep ambiguous error ' test_expect_success 'git log -- :' ' diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh index 4451127eb2..9d87777b59 100755 --- a/t/t4211-line-log.sh +++ b/t/t4211-line-log.sh @@ -99,4 +99,11 @@ test_expect_success '-L with --first-parent and a merge' ' git log --first-parent -L 1,1:b.c ' +test_expect_success '-L with --output' ' + git checkout parallel-change && + git log --output=log -L :main:b.c >output && + test ! -s output && + test_line_count = 70 log +' + test_done diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 4b68bbafbe..80b2387341 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -319,4 +319,78 @@ test_expect_success 'catch non-matching pathspec' ' test_must_fail git archive -v HEAD -- "*.abc" >/dev/null ' +# Pull the size and date of each entry in a tarfile using the system tar. +# +# We'll pull out only the year from the date; that avoids any question of +# timezones impacting the result (as long as we keep our test times away from a +# year boundary; our reference times are all in August). +# +# The output of tar_info is expected to be "<size> <year>", both in decimal. It +# ignores the return value of tar. We have to do this, because some of our test +# input is only partial (the real data is 64GB in some cases). +tar_info () { + "$TAR" tvf "$1" | + awk '{ + split($4, date, "-") + print $3 " " date[1] + }' +} + +# See if our system tar can handle a tar file with huge sizes and dates far in +# the future, and that we can actually parse its output. +# +# The reference file was generated by GNU tar, and the magic time and size are +# both octal 01000000000001, which overflows normal ustar fields. +test_lazy_prereq TAR_HUGE ' + echo "68719476737 4147" >expect && + tar_info "$TEST_DIRECTORY"/t5000/huge-and-future.tar >actual && + test_cmp expect actual +' + +test_expect_success LONG_IS_64BIT 'set up repository with huge blob' ' + obj_d=19 && + obj_f=f9c8273ec45a8938e6999cb59b3ff66739902a && + obj=${obj_d}${obj_f} && + mkdir -p .git/objects/$obj_d && + cp "$TEST_DIRECTORY"/t5000/$obj .git/objects/$obj_d/$obj_f && + rm -f .git/index && + git update-index --add --cacheinfo 100644,$obj,huge && + git commit -m huge +' + +# We expect git to die with SIGPIPE here (otherwise we +# would generate the whole 64GB). +test_expect_success LONG_IS_64BIT 'generate tar with huge size' ' + { + git archive HEAD + echo $? >exit-code + } | test_copy_bytes 4096 >huge.tar && + echo 141 >expect && + test_cmp expect exit-code +' + +test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' ' + echo 68719476737 >expect && + tar_info huge.tar | cut -d" " -f1 >actual && + test_cmp expect actual +' + +test_expect_success LONG_IS_64BIT 'set up repository with far-future commit' ' + rm -f .git/index && + echo content >file && + git add file && + GIT_COMMITTER_DATE="@68719476737 +0000" \ + git commit -m "tempori parendum" +' + +test_expect_success LONG_IS_64BIT 'generate tar with future mtime' ' + git archive HEAD >future.tar +' + +test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our future mtime' ' + echo 4147 >expect && + tar_info future.tar | cut -d" " -f2 >actual && + test_cmp expect actual +' + test_done diff --git a/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a b/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a Binary files differnew file mode 100644 index 0000000000..5cbe9ec312 --- /dev/null +++ b/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a diff --git a/t/t5000/huge-and-future.tar b/t/t5000/huge-and-future.tar Binary files differnew file mode 100644 index 0000000000..63155e1855 --- /dev/null +++ b/t/t5000/huge-and-future.tar diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index dd2e6ce34e..8198d8eb05 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -1182,7 +1182,7 @@ test_expect_success 'extra args: setup' ' test_extra_arg () { test_expect_success "extra args: $*" " test_must_fail git remote $* bogus_extra_arg 2>actual && - grep '^usage:' actual + test_i18ngrep '^usage:' actual " } diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 454d896390..6bd4853079 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -644,7 +644,7 @@ test_expect_success 'fetch --prune prints the remotes url' ' git fetch --prune origin 2>&1 | head -n1 >../actual ) && echo "From ${D}/." >expect && - test_cmp expect actual + test_i18ncmp expect actual ' test_expect_success 'branchname D/F conflict resolved by --prune' ' @@ -688,4 +688,34 @@ test_expect_success 'fetching with auto-gc does not lock up' ' ) ' +test_expect_success 'fetch aligned output' ' + git clone . full-output && + test_commit looooooooooooong-tag && + ( + cd full-output && + git -c fetch.output=full fetch origin 2>&1 | \ + grep -e "->" | cut -c 22- >../actual + ) && + cat >expect <<-\EOF && + master -> origin/master + looooooooooooong-tag -> looooooooooooong-tag + EOF + test_cmp expect actual +' + +test_expect_success 'fetch compact output' ' + git clone . compact && + test_commit extraaa && + ( + cd compact && + git -c fetch.output=compact fetch origin 2>&1 | \ + grep -e "->" | cut -c 22- >../actual + ) && + cat >expect <<-\EOF && + master -> origin/* + extraaa -> * + EOF + test_cmp expect actual +' + test_done diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 3159956fde..37ebbcfbbf 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -211,7 +211,7 @@ test_expect_success 'fail if the index has unresolved entries' ' test -n "$(git ls-files -u)" && cp file expected && test_must_fail git pull . second 2>err && - test_i18ngrep "Pull is not possible because you have unmerged files" err && + test_i18ngrep "Pulling is not possible because you have unmerged files." err && test_cmp expected file && git add file && test -z "$(git ls-files -u)" && diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh index 3683df13a6..d6981ba304 100755 --- a/t/t5523-push-upstream.sh +++ b/t/t5523-push-upstream.sh @@ -75,7 +75,7 @@ test_expect_success TTY 'progress messages go to tty' ' ensure_fresh_upstream && test_terminal git push -u upstream master >out 2>err && - grep "Writing objects" err + test_i18ngrep "Writing objects" err ' test_expect_success 'progress messages do not go to non-tty' ' @@ -83,7 +83,7 @@ test_expect_success 'progress messages do not go to non-tty' ' # skip progress messages, since stderr is non-tty git push -u upstream master >out 2>err && - ! grep "Writing objects" err + test_i18ngrep ! "Writing objects" err ' test_expect_success 'progress messages go to non-tty (forced)' ' @@ -91,22 +91,22 @@ test_expect_success 'progress messages go to non-tty (forced)' ' # force progress messages to stderr, even though it is non-tty git push -u --progress upstream master >out 2>err && - grep "Writing objects" err + test_i18ngrep "Writing objects" err ' test_expect_success TTY 'push -q suppresses progress' ' ensure_fresh_upstream && test_terminal git push -u -q upstream master >out 2>err && - ! grep "Writing objects" err + test_i18ngrep ! "Writing objects" err ' test_expect_success TTY 'push --no-progress suppresses progress' ' ensure_fresh_upstream && test_terminal git push -u --no-progress upstream master >out 2>err && - ! grep "Unpacking objects" err && - ! grep "Writing objects" err + test_i18ngrep ! "Unpacking objects" err && + test_i18ngrep ! "Writing objects" err ' test_expect_success TTY 'quiet push' ' diff --git a/t/t5536-fetch-conflicts.sh b/t/t5536-fetch-conflicts.sh index 6c5d3a4ce0..2e42cf3316 100755 --- a/t/t5536-fetch-conflicts.sh +++ b/t/t5536-fetch-conflicts.sh @@ -22,8 +22,8 @@ verify_stderr () { cat >expected && # We're not interested in the error # "fatal: The remote end hung up unexpectedly": - grep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort && - test_cmp expected actual + test_i18ngrep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort && + test_i18ncmp expected actual } test_expect_success 'setup' ' diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh index fd7d06b9a2..ca6becfe37 100755 --- a/t/t5541-http-push-smart.sh +++ b/t/t5541-http-push-smart.sh @@ -119,7 +119,7 @@ test_expect_success 'rejected update prints status' ' git commit -m dev2 && test_must_fail git push origin dev2 2>act && sed -e "/^remote: /s/ *$//" <act >cmp && - test_cmp exp cmp + test_i18ncmp exp cmp ' rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" @@ -219,7 +219,7 @@ test_expect_success TTY 'push shows progress when stderr is a tty' ' cd "$ROOT_PATH"/test_repo_clone && test_commit noisy && test_terminal git push >output 2>&1 && - grep "^Writing objects" output + test_i18ngrep "^Writing objects" output ' test_expect_success TTY 'push --quiet silences status and progress' ' @@ -233,16 +233,16 @@ test_expect_success TTY 'push --no-progress silences progress but not status' ' cd "$ROOT_PATH"/test_repo_clone && test_commit no-progress && test_terminal git push --no-progress >output 2>&1 && - grep "^To http" output && - ! grep "^Writing objects" + test_i18ngrep "^To http" output && + test_i18ngrep ! "^Writing objects" ' test_expect_success 'push --progress shows progress to non-tty' ' cd "$ROOT_PATH"/test_repo_clone && test_commit progress && git push --progress >output 2>&1 && - grep "^To http" output && - grep "^Writing objects" output + test_i18ngrep "^To http" output && + test_i18ngrep "^Writing objects" output ' test_expect_success 'http push gives sane defaults to reflog' ' diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index e74662ba5c..86d1380b9c 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -362,7 +362,7 @@ test_expect_success 'bisect starting with a detached HEAD' ' test_expect_success 'bisect errors out if bad and good are mistaken' ' git bisect reset && test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error && - grep "mistook good and bad" rev_list_error && + test_i18ngrep "mistook good and bad" rev_list_error && git bisect reset ' @@ -404,7 +404,7 @@ test_expect_success 'side branch creation' ' test_expect_success 'good merge base when good and bad are siblings' ' git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt && - grep "merge base must be tested" my_bisect_log.txt && + test_i18ngrep "merge base must be tested" my_bisect_log.txt && grep $HASH4 my_bisect_log.txt && git bisect good > my_bisect_log.txt && test_must_fail grep "merge base must be tested" my_bisect_log.txt && @@ -413,7 +413,7 @@ test_expect_success 'good merge base when good and bad are siblings' ' ' test_expect_success 'skipped merge base when good and bad are siblings' ' git bisect start "$SIDE_HASH7" "$HASH7" > my_bisect_log.txt && - grep "merge base must be tested" my_bisect_log.txt && + test_i18ngrep "merge base must be tested" my_bisect_log.txt && grep $HASH4 my_bisect_log.txt && git bisect skip > my_bisect_log.txt 2>&1 && grep "warning" my_bisect_log.txt && @@ -423,11 +423,11 @@ test_expect_success 'skipped merge base when good and bad are siblings' ' test_expect_success 'bad merge base when good and bad are siblings' ' git bisect start "$HASH7" HEAD > my_bisect_log.txt && - grep "merge base must be tested" my_bisect_log.txt && + test_i18ngrep "merge base must be tested" my_bisect_log.txt && grep $HASH4 my_bisect_log.txt && test_must_fail git bisect bad > my_bisect_log.txt 2>&1 && - grep "merge base $HASH4 is bad" my_bisect_log.txt && - grep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt && + test_i18ngrep "merge base $HASH4 is bad" my_bisect_log.txt && + test_i18ngrep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt && git bisect reset ' @@ -460,9 +460,9 @@ test_expect_success 'many merge bases creation' ' test_expect_success 'good merge bases when good and bad are siblings' ' git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt && - grep "merge base must be tested" my_bisect_log.txt && + test_i18ngrep "merge base must be tested" my_bisect_log.txt && git bisect good > my_bisect_log2.txt && - grep "merge base must be tested" my_bisect_log2.txt && + test_i18ngrep "merge base must be tested" my_bisect_log2.txt && { { grep "$SIDE_HASH5" my_bisect_log.txt && @@ -477,14 +477,14 @@ test_expect_success 'good merge bases when good and bad are siblings' ' test_expect_success 'optimized merge base checks' ' git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt && - grep "merge base must be tested" my_bisect_log.txt && + test_i18ngrep "merge base must be tested" my_bisect_log.txt && grep "$HASH4" my_bisect_log.txt && git bisect good > my_bisect_log2.txt && test -f ".git/BISECT_ANCESTORS_OK" && test "$HASH6" = $(git rev-parse --verify HEAD) && git bisect bad > my_bisect_log3.txt && git bisect good "$A_HASH" > my_bisect_log4.txt && - grep "merge base must be tested" my_bisect_log4.txt && + test_i18ngrep "merge base must be tested" my_bisect_log4.txt && test_must_fail test -f ".git/BISECT_ANCESTORS_OK" ' @@ -562,7 +562,7 @@ test_expect_success 'skipping away from skipped commit' ' test_expect_success 'erroring out when using bad path parameters' ' test_must_fail git bisect start $PARA_HASH7 $HASH1 -- foobar 2> error.txt && - grep "bad path parameters" error.txt + test_i18ngrep "bad path parameters" error.txt ' test_expect_success 'test bisection on bare repo - --no-checkout specified' ' @@ -803,7 +803,7 @@ test_expect_success 'bisect terms needs 0 or 1 argument' ' test_must_fail git bisect terms 1 2 && test_must_fail git bisect terms 2>actual && echo "no terms defined" >expected && - test_cmp expected actual + test_i18ncmp expected actual ' test_expect_success 'bisect terms shows good/bad after start' ' @@ -875,7 +875,7 @@ test_expect_success 'bisect start --term-* does store terms' ' Your current terms are two for the old state and one for the new state. EOF - test_cmp expected actual && + test_i18ncmp expected actual && git bisect terms --term-bad >actual && echo one >expected && test_cmp expected actual && diff --git a/t/t6301-for-each-ref-errors.sh b/t/t6301-for-each-ref-errors.sh index cdb67a03b7..c734ce2388 100755 --- a/t/t6301-for-each-ref-errors.sh +++ b/t/t6301-for-each-ref-errors.sh @@ -20,8 +20,8 @@ test_expect_success 'Broken refs are reported correctly' ' test_when_finished "rm -f .git/$r" && echo "warning: ignoring broken ref $r" >broken-err && git for-each-ref >out 2>err && - test_cmp full-list out && - test_cmp broken-err err + test_i18ncmp full-list out && + test_i18ncmp broken-err err ' test_expect_success 'NULL_SHA1 refs are reported correctly' ' @@ -31,10 +31,10 @@ test_expect_success 'NULL_SHA1 refs are reported correctly' ' echo "warning: ignoring broken ref $r" >zeros-err && git for-each-ref >out 2>err && test_cmp full-list out && - test_cmp zeros-err err && + test_i18ncmp zeros-err err && git for-each-ref --format="%(objectname) %(refname)" >brief-out 2>brief-err && test_cmp brief-list brief-out && - test_cmp zeros-err brief-err + test_i18ncmp zeros-err brief-err ' test_expect_success 'Missing objects are reported correctly' ' @@ -43,7 +43,7 @@ test_expect_success 'Missing objects are reported correctly' ' test_when_finished "rm -f .git/$r" && echo "fatal: missing object $MISSING for $r" >missing-err && test_must_fail git for-each-ref 2>err && - test_cmp missing-err err && + test_i18ncmp missing-err err && ( cat brief-list && echo "$MISSING $r" diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index a971884cfd..38b3890532 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -643,7 +643,7 @@ test_expect_success 'test ident field is working' ' cp -R done dthree dtwo four three ../other_worktree && GIT_WORK_TREE=../other_worktree git status 2>../err && echo "warning: Untracked cache is disabled on this system or location." >../expect && - test_cmp ../expect ../err + test_i18ncmp ../expect ../err ' test_done diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index 98bcfe21aa..86f23be34a 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -66,14 +66,14 @@ test_expect_success 'reset --hard message' ' hex=$(git log -1 --format="%h") && git reset --hard > .actual && echo HEAD is now at $hex $(commit_msg) > .expected && - test_cmp .expected .actual + test_i18ncmp .expected .actual ' test_expect_success 'reset --hard message (ISO8859-1 logoutputencoding)' ' hex=$(git log -1 --format="%h") && git -c "i18n.logOutputEncoding=$test_encoding" reset --hard > .actual && echo HEAD is now at $hex $(commit_msg $test_encoding) > .expected && - test_cmp .expected .actual + test_i18ncmp .expected .actual ' >.diff_expect diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 885923610a..d4b217b0ee 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -257,7 +257,7 @@ test_expect_success 'checkout to detach HEAD' ' git checkout -f renamer && git clean -f && git checkout renamer^ 2>messages && test_i18ngrep "HEAD is now at 7329388" messages && - test_line_count -gt 1 messages && + (test_line_count -gt 1 messages || test -n "$GETTEXT_POISON") && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/master) && test "z$H" = "z$M" && diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 3570f7bb8c..b77cce8e40 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -942,7 +942,7 @@ test_expect_success 'submodule deinit from subdirectory' ' cd sub && git submodule deinit ../init >../output ) && - grep "\\.\\./init" output && + test_i18ngrep "\\.\\./init" output && test -z "$(git config --get-regexp "submodule\.example\.")" && test -n "$(git config --get-regexp "submodule\.example2\.")" && test -f example2/.git && diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index 5503ec067f..0726799e74 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -157,7 +157,7 @@ test_expect_success '"git submodule sync" should update submodule URLs - subdire cd sub && git submodule sync >../../output ) && - grep "\\.\\./submodule" output && + test_i18ngrep "\\.\\./submodule" output && test -d "$( cd super-clone/submodule && git config remote.origin.url @@ -188,7 +188,7 @@ test_expect_success '"git submodule sync --recursive" should update all submodul cd sub && git submodule sync --recursive >../../output ) && - grep "\\.\\./submodule/sub-submodule" output && + test_i18ngrep "\\.\\./submodule/sub-submodule" output && test -d "$( cd super-clone/submodule && git config remote.origin.url diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 5f278799d5..88e9750abb 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -136,8 +136,8 @@ test_expect_success 'submodule update --init --recursive from subdirectory' ' cd tmp && git submodule update --init --recursive ../super >../../actual 2>../../actual2 ) && - test_cmp expect actual && - test_cmp expect2 actual2 + test_i18ncmp expect actual && + test_i18ncmp expect2 actual2 ' apos="'"; @@ -370,7 +370,7 @@ test_expect_success 'submodule update - command in .git/config catches failure' (cd super && test_must_fail git submodule update submodule 2>../actual ) && - test_cmp actual expect + test_i18ncmp actual expect ' cat << EOF >expect @@ -388,7 +388,7 @@ test_expect_success 'submodule update - command in .git/config catches failure - mkdir tmp && cd tmp && test_must_fail git submodule update ../submodule 2>../../actual ) && - test_cmp actual expect + test_i18ncmp actual expect ' cat << EOF >expect @@ -408,7 +408,7 @@ test_expect_success 'recursive submodule update - command in .git/config catches mkdir -p tmp && cd tmp && test_must_fail git submodule update --recursive ../super 2>../../actual ) && - test_cmp actual expect + test_i18ncmp actual expect ' test_expect_success 'submodule init does not copy command into .git/config' ' diff --git a/t/t7508-status.sh b/t/t7508-status.sh index c3ed7cb51c..b3bdd162aa 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -1377,7 +1377,7 @@ EOF git config --add -f .gitmodules submodule.subname.ignore all && git config --add -f .gitmodules submodule.subname.path sm && git status > output && - test_cmp expect output && + test_i18ncmp expect output && git config -f .gitmodules --remove-section submodule.subname ' @@ -1387,7 +1387,7 @@ test_expect_success '.git/config ignore=all suppresses unstaged submodule summar git config --add submodule.subname.ignore all && git config --add submodule.subname.path sm && git status > output && - test_cmp expect output && + test_i18ncmp expect output && git config --remove-section submodule.subname && git config -f .gitmodules --remove-section submodule.subname ' diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh index 4177a8609a..6e839f5489 100755 --- a/t/t7510-signed-commit.sh +++ b/t/t7510-signed-commit.sh @@ -210,4 +210,11 @@ test_expect_success GPG 'show lack of signature with custom format' ' test_cmp expect actual ' +test_expect_success GPG 'log.showsignature behaves like --show-signature' ' + test_config log.showsignature true && + git show initial >actual && + grep "gpg: Signature made" actual && + grep "gpg: Good signature" actual +' + test_done diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh index 758a623cdb..9444d6a9b9 100755 --- a/t/t7607-merge-overwrite.sh +++ b/t/t7607-merge-overwrite.sh @@ -115,7 +115,7 @@ cat >expect <<\EOF error: The following untracked working tree files would be overwritten by merge: sub sub2 -Please move or remove them before you can merge. +Please move or remove them before you merge. Aborting EOF @@ -125,7 +125,7 @@ test_expect_success 'will not overwrite untracked file in leading path' ' cp important sub && cp important sub2 && test_must_fail git merge sub 2>out && - test_cmp out expect && + test_i18ncmp out expect && test_path_is_missing .git/MERGE_HEAD && test_cmp important sub && test_cmp important sub2 && diff --git a/t/t7609-merge-co-error-msgs.sh b/t/t7609-merge-co-error-msgs.sh index 6729cb379f..f80bdb81e1 100755 --- a/t/t7609-merge-co-error-msgs.sh +++ b/t/t7609-merge-co-error-msgs.sh @@ -31,7 +31,7 @@ error: The following untracked working tree files would be overwritten by merge: four three two -Please move or remove them before you can merge. +Please move or remove them before you merge. Aborting EOF @@ -53,10 +53,10 @@ error: Your local changes to the following files would be overwritten by merge: four three two -Please commit your changes or stash them before you can merge. +Please commit your changes or stash them before you merge. error: The following untracked working tree files would be overwritten by merge: five -Please move or remove them before you can merge. +Please move or remove them before you merge. Aborting EOF @@ -72,7 +72,7 @@ cat >expect <<\EOF error: Your local changes to the following files would be overwritten by checkout: rep/one rep/two -Please commit your changes or stash them before you can switch branches. +Please commit your changes or stash them before you switch branches. Aborting EOF @@ -94,7 +94,7 @@ cat >expect <<\EOF error: Your local changes to the following files would be overwritten by checkout: rep/one rep/two -Please commit your changes or stash them before you can switch branches. +Please commit your changes or stash them before you switch branches. Aborting EOF diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index 76306cf268..7217f3968d 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -589,7 +589,12 @@ test_expect_success 'filenames seen by tools start with ./' ' git reset --hard master >/dev/null 2>&1 ' -test_expect_success 'temporary filenames are used with mergetool.writeToTemp' ' +test_lazy_prereq MKTEMP ' + tempdir=$(mktemp -d -t foo.XXXXXX) && + test -d "$tempdir" +' + +test_expect_success MKTEMP 'temporary filenames are used with mergetool.writeToTemp' ' git checkout -b test16 branch1 && test_config mergetool.writeToTemp true && test_config mergetool.myecho.cmd "echo \"\$LOCAL\"" && diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index bd8ea1191f..cf3f9ec631 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -177,7 +177,7 @@ do test_expect_success "grep -c $L (no /dev/null)" ' ! git grep -c test $H | grep /dev/null - ' + ' test_expect_success "grep --max-depth -1 $L" ' { @@ -1377,4 +1377,62 @@ test_expect_success 'grep --color -e A --and -e B -p with context' ' test_cmp expected actual ' +test_expect_success 'grep can find things only in the work tree' ' + : >work-tree-only && + git add work-tree-only && + test_when_finished "git rm -f work-tree-only" && + echo "find in work tree" >work-tree-only && + git grep --quiet "find in work tree" && + test_must_fail git grep --quiet --cached "find in work tree" && + test_must_fail git grep --quiet "find in work tree" HEAD +' + +test_expect_success 'grep can find things only in the work tree (i-t-a)' ' + echo "intend to add this" >intend-to-add && + git add -N intend-to-add && + test_when_finished "git rm -f intend-to-add" && + git grep --quiet "intend to add this" && + test_must_fail git grep --quiet --cached "intend to add this" && + test_must_fail git grep --quiet "intend to add this" HEAD +' + +test_expect_success 'grep does not search work tree with assume unchanged' ' + echo "intend to add this" >intend-to-add && + git add -N intend-to-add && + git update-index --assume-unchanged intend-to-add && + test_when_finished "git rm -f intend-to-add" && + test_must_fail git grep --quiet "intend to add this" && + test_must_fail git grep --quiet --cached "intend to add this" && + test_must_fail git grep --quiet "intend to add this" HEAD +' + +test_expect_success 'grep can find things only in the index' ' + echo "only in the index" >cache-this && + git add cache-this && + rm cache-this && + test_when_finished "git rm --cached cache-this" && + test_must_fail git grep --quiet "only in the index" && + git grep --quiet --cached "only in the index" && + test_must_fail git grep --quiet "only in the index" HEAD +' + +test_expect_success 'grep does not report i-t-a with -L --cached' ' + echo "intend to add this" >intend-to-add && + git add -N intend-to-add && + test_when_finished "git rm -f intend-to-add" && + git ls-files | grep -v "^intend-to-add\$" >expected && + git grep -L --cached "nonexistent_string" >actual && + test_cmp expected actual +' + +test_expect_success 'grep does not report i-t-a and assume unchanged with -L' ' + echo "intend to add this" >intend-to-add-assume-unchanged && + git add -N intend-to-add-assume-unchanged && + test_when_finished "git rm -f intend-to-add-assume-unchanged" && + git update-index --assume-unchanged intend-to-add-assume-unchanged && + git ls-files | grep -v "^intend-to-add-assume-unchanged\$" >expected && + git grep -L "nonexistent_string" >actual && + test_cmp expected actual +' + test_done diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh new file mode 100755 index 0000000000..169fd8d706 --- /dev/null +++ b/t/t7812-grep-icase-non-ascii.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +test_description='grep icase on non-English locales' + +. ./lib-gettext.sh + +test_expect_success GETTEXT_LOCALE 'setup' ' + test_write_lines "TILRAUN: Halló Heimur!" >file && + git add file && + LC_ALL="$is_IS_locale" && + export LC_ALL +' + +test_have_prereq GETTEXT_LOCALE && +test-regex "HALLÓ" "Halló" ICASE && +test_set_prereq REGEX_LOCALE + +test_expect_success REGEX_LOCALE 'grep literal string, no -F' ' + git grep -i "TILRAUN: Halló Heimur!" && + git grep -i "TILRAUN: HALLÓ HEIMUR!" +' + +test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 icase' ' + git grep --perl-regexp "TILRAUN: H.lló Heimur!" && + git grep --perl-regexp -i "TILRAUN: H.lló Heimur!" && + git grep --perl-regexp -i "TILRAUN: H.LLÓ HEIMUR!" +' + +test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 string with "+"' ' + test_write_lines "TILRAUN: Hallóó Heimur!" >file2 && + git add file2 && + git grep -l --perl-regexp "TILRAUN: H.lló+ Heimur!" >actual && + echo file >expected && + echo file2 >>expected && + test_cmp expected actual +' + +test_expect_success REGEX_LOCALE 'grep literal string, with -F' ' + git grep --debug -i -F "TILRAUN: Halló Heimur!" 2>&1 >/dev/null | + grep fixed >debug1 && + test_write_lines "fixed TILRAUN: Halló Heimur!" >expect1 && + test_cmp expect1 debug1 && + + git grep --debug -i -F "TILRAUN: HALLÓ HEIMUR!" 2>&1 >/dev/null | + grep fixed >debug2 && + test_write_lines "fixed TILRAUN: HALLÓ HEIMUR!" >expect2 && + test_cmp expect2 debug2 +' + +test_expect_success REGEX_LOCALE 'grep string with regex, with -F' ' + test_write_lines "^*TILR^AUN:.* \\Halló \$He[]imur!\$" >file && + + git grep --debug -i -F "^*TILR^AUN:.* \\Halló \$He[]imur!\$" 2>&1 >/dev/null | + grep fixed >debug1 && + test_write_lines "fixed \\^*TILR^AUN:\\.\\* \\\\Halló \$He\\[]imur!\\\$" >expect1 && + test_cmp expect1 debug1 && + + git grep --debug -i -F "^*TILR^AUN:.* \\HALLÓ \$HE[]IMUR!\$" 2>&1 >/dev/null | + grep fixed >debug2 && + test_write_lines "fixed \\^*TILR^AUN:\\.\\* \\\\HALLÓ \$HE\\[]IMUR!\\\$" >expect2 && + test_cmp expect2 debug2 +' + +test_expect_success REGEX_LOCALE 'pickaxe -i on non-ascii' ' + git commit -m first && + git log --format=%f -i -S"TILRAUN: HALLÓ HEIMUR!" >actual && + echo first >expected && + test_cmp expected actual +' + +test_done diff --git a/t/t7813-grep-icase-iso.sh b/t/t7813-grep-icase-iso.sh new file mode 100755 index 0000000000..efef7fb81f --- /dev/null +++ b/t/t7813-grep-icase-iso.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +test_description='grep icase on non-English locales' + +. ./lib-gettext.sh + +test_expect_success GETTEXT_ISO_LOCALE 'setup' ' + printf "TILRAUN: Halló Heimur!" >file && + git add file && + LC_ALL="$is_IS_iso_locale" && + export LC_ALL +' + +test_expect_success GETTEXT_ISO_LOCALE,LIBPCRE 'grep pcre string' ' + git grep --perl-regexp -i "TILRAUN: H.lló Heimur!" && + git grep --perl-regexp -i "TILRAUN: H.LLÓ HEIMUR!" +' + +test_done diff --git a/t/t8008-blame-formats.sh b/t/t8008-blame-formats.sh index 29f84a6dd1..92c8e792d1 100755 --- a/t/t8008-blame-formats.sh +++ b/t/t8008-blame-formats.sh @@ -87,4 +87,21 @@ test_expect_success 'blame --line-porcelain output' ' test_cmp expect actual ' +test_expect_success '--porcelain detects first non-blank line as subject' ' + ( + GIT_INDEX_FILE=.git/tmp-index && + export GIT_INDEX_FILE && + echo "This is it" >single-file && + git add single-file && + tree=$(git write-tree) && + commit=$(printf "%s\n%s\n%s\n\n\n \noneline\n\nbody\n" \ + "tree $tree" \ + "author A <a@b.c> 123456789 +0000" \ + "committer C <c@d.e> 123456789 +0000" | + git hash-object -w -t commit --stdin) && + git blame --porcelain $commit -- single-file >output && + grep "^summary oneline$" output + ) +' + test_done diff --git a/t/t9003-help-autocorrect.sh b/t/t9003-help-autocorrect.sh index dfe95c923b..b1c7919c4a 100755 --- a/t/t9003-help-autocorrect.sh +++ b/t/t9003-help-autocorrect.sh @@ -31,10 +31,10 @@ test_expect_success 'autocorrect showing candidates' ' git config help.autocorrect 0 && test_must_fail git lfg 2>actual && - sed -e "1,/^Did you mean this/d" actual | grep lgf && + grep "^ lgf" actual && test_must_fail git distimdist 2>actual && - sed -e "1,/^Did you mean this/d" actual | grep distimdistim + grep "^ distimdistim" actual ' test_expect_success 'autocorrect running commands' ' diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 74d740de41..2e0ba3ebd8 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -7,23 +7,6 @@ test_description='test git fast-import utility' . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash -# Print $1 bytes from stdin to stdout. -# -# This could be written as "head -c $1", but IRIX "head" does not -# support the -c option. -head_c () { - perl -e ' - my $len = $ARGV[1]; - while ($len > 0) { - my $s; - my $nread = sysread(STDIN, $s, $len); - die "cannot read: $!" unless defined($nread); - print $s; - $len -= $nread; - } - ' - "$1" -} - verify_packs () { for p in .git/objects/pack/*.pack do @@ -2481,7 +2464,7 @@ test_expect_success PIPE 'R: copy using cat-file' ' read blob_id type size <&3 && echo "$blob_id $type $size" >response && - head_c $size >blob <&3 && + test_copy_bytes $size >blob <&3 && read newline <&3 && cat <<-EOF && @@ -2524,7 +2507,7 @@ test_expect_success PIPE 'R: print blob mid-commit' ' EOF read blob_id type size <&3 && - head_c $size >actual <&3 && + test_copy_bytes $size >actual <&3 && read newline <&3 && echo @@ -2559,7 +2542,7 @@ test_expect_success PIPE 'R: print staged blob within commit' ' echo "cat-blob $to_get" && read blob_id type size <&3 && - head_c $size >actual <&3 && + test_copy_bytes $size >actual <&3 && read newline <&3 && echo deleteall diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 48884d5208..4f7eadb596 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -612,7 +612,7 @@ test_must_fail () { then echo >&2 "test_must_fail: command succeeded: $*" return 1 - elif test $exit_code -eq 141 && list_contains "$_test_ok" sigpipe + elif test_match_signal 13 $exit_code && list_contains "$_test_ok" sigpipe then return 0 elif test $exit_code -gt 129 && test $exit_code -le 192 @@ -961,3 +961,32 @@ test_env () { done ) } + +# Returns true if the numeric exit code in "$2" represents the expected signal +# in "$1". Signals should be given numerically. +test_match_signal () { + if test "$2" = "$((128 + $1))" + then + # POSIX + return 0 + elif test "$2" = "$((256 + $1))" + then + # ksh + return 0 + fi + return 1 +} + +# Read up to "$1" bytes (or to EOF) from stdin and write them to stdout. +test_copy_bytes () { + perl -e ' + my $len = $ARGV[1]; + while ($len > 0) { + my $s; + my $nread = sysread(STDIN, $s, $len); + die "cannot read: $!" unless defined($nread); + print $s; + $len -= $nread; + } + ' - "$1" +} diff --git a/t/test-lib.sh b/t/test-lib.sh index 0055ebba46..11201e9cf8 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1111,3 +1111,12 @@ run_with_limited_cmdline () { } test_lazy_prereq CMDLINE_LIMIT 'run_with_limited_cmdline true' + +build_option () { + git version --build-options | + sed -ne "s/^$1: //p" +} + +test_lazy_prereq LONG_IS_64BIT ' + test 8 -le "$(build_option sizeof-long)" +' diff --git a/transport-helper.c b/transport-helper.c index bd666b29ec..4208743605 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -1038,7 +1038,7 @@ static struct ref *get_refs_list(struct transport *transport, int for_push) (*tail)->status |= REF_STATUS_UPTODATE; if (read_ref((*tail)->name, (*tail)->old_oid.hash) < 0) - die(N_("Could not read ref %s"), + die(_("Could not read ref %s"), (*tail)->name); } } diff --git a/transport.c b/transport.c index 095e61f0ad..59b911e5ff 100644 --- a/transport.c +++ b/transport.c @@ -59,7 +59,7 @@ static void set_upstreams(struct transport *transport, struct ref *refs, localname + 11, transport->remote->name, remotename); else - printf("Would set upstream of '%s' to '%s' of '%s'\n", + printf(_("Would set upstream of '%s' to '%s' of '%s'\n"), localname + 11, remotename + 11, transport->remote->name); } @@ -148,7 +148,7 @@ static int set_git_option(struct git_transport_options *opts, char *end; opts->depth = strtol(value, &end, 0); if (*end) - die("transport: invalid depth option '%s'", value); + die(_("transport: invalid depth option '%s'"), value); } return 0; } @@ -767,19 +767,19 @@ static void die_with_unpushed_submodules(struct string_list *needs_pushing) { int i; - fprintf(stderr, "The following submodule paths contain changes that can\n" - "not be found on any remote:\n"); + fprintf(stderr, _("The following submodule paths contain changes that can\n" + "not be found on any remote:\n")); for (i = 0; i < needs_pushing->nr; i++) printf(" %s\n", needs_pushing->items[i].string); - fprintf(stderr, "\nPlease try\n\n" - " git push --recurse-submodules=on-demand\n\n" - "or cd to the path and use\n\n" - " git push\n\n" - "to push them to a remote.\n\n"); + fprintf(stderr, _("\nPlease try\n\n" + " git push --recurse-submodules=on-demand\n\n" + "or cd to the path and use\n\n" + " git push\n\n" + "to push them to a remote.\n\n")); string_list_clear(needs_pushing, 0); - die("Aborting."); + die(_("Aborting.")); } static int run_pre_push_hook(struct transport *transport, diff --git a/unpack-trees.c b/unpack-trees.c index 6bc9512a45..11c37fbc58 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -62,17 +62,17 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts, if (!strcmp(cmd, "checkout")) msg = advice_commit_before_merge ? _("Your local changes to the following files would be overwritten by checkout:\n%%s" - "Please commit your changes or stash them before you can switch branches.") + "Please commit your changes or stash them before you switch branches.") : _("Your local changes to the following files would be overwritten by checkout:\n%%s"); else if (!strcmp(cmd, "merge")) msg = advice_commit_before_merge ? _("Your local changes to the following files would be overwritten by merge:\n%%s" - "Please commit your changes or stash them before you can merge.") + "Please commit your changes or stash them before you merge.") : _("Your local changes to the following files would be overwritten by merge:\n%%s"); else msg = advice_commit_before_merge ? _("Your local changes to the following files would be overwritten by %s:\n%%s" - "Please commit your changes or stash them before you can %s.") + "Please commit your changes or stash them before you %s.") : _("Your local changes to the following files would be overwritten by %s:\n%%s"); msgs[ERROR_WOULD_OVERWRITE] = msgs[ERROR_NOT_UPTODATE_FILE] = xstrfmt(msg, cmd, cmd); @@ -83,34 +83,34 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts, if (!strcmp(cmd, "checkout")) msg = advice_commit_before_merge ? _("The following untracked working tree files would be removed by checkout:\n%%s" - "Please move or remove them before you can switch branches.") + "Please move or remove them before you switch branches.") : _("The following untracked working tree files would be removed by checkout:\n%%s"); else if (!strcmp(cmd, "merge")) msg = advice_commit_before_merge ? _("The following untracked working tree files would be removed by merge:\n%%s" - "Please move or remove them before you can merge.") + "Please move or remove them before you merge.") : _("The following untracked working tree files would be removed by merge:\n%%s"); else msg = advice_commit_before_merge ? _("The following untracked working tree files would be removed by %s:\n%%s" - "Please move or remove them before you can %s.") + "Please move or remove them before you %s.") : _("The following untracked working tree files would be removed by %s:\n%%s"); msgs[ERROR_WOULD_LOSE_UNTRACKED_REMOVED] = xstrfmt(msg, cmd, cmd); if (!strcmp(cmd, "checkout")) msg = advice_commit_before_merge ? _("The following untracked working tree files would be overwritten by checkout:\n%%s" - "Please move or remove them before you can switch branches.") + "Please move or remove them before you switch branches.") : _("The following untracked working tree files would be overwritten by checkout:\n%%s"); else if (!strcmp(cmd, "merge")) msg = advice_commit_before_merge ? _("The following untracked working tree files would be overwritten by merge:\n%%s" - "Please move or remove them before you can merge.") + "Please move or remove them before you merge.") : _("The following untracked working tree files would be overwritten by merge:\n%%s"); else msg = advice_commit_before_merge ? _("The following untracked working tree files would be overwritten by %s:\n%%s" - "Please move or remove them before you can %s.") + "Please move or remove them before you %s.") : _("The following untracked working tree files would be overwritten by %s:\n%%s"); msgs[ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN] = xstrfmt(msg, cmd, cmd); diff --git a/upload-pack.c b/upload-pack.c index f93787003a..d4cc414bc2 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -828,7 +828,7 @@ static int upload_pack_config(const char *var, const char *value, void *unused) return parse_hide_refs_config(var, value, "uploadpack"); } -int main(int argc, const char **argv) +int cmd_main(int argc, const char **argv) { const char *dir; int strict = 0; @@ -844,10 +844,7 @@ int main(int argc, const char **argv) OPT_END() }; - git_setup_gettext(); - packet_trace_identity("upload-pack"); - git_extract_argv0_path(argv[0]); check_replace_refs = 0; argc = parse_options(argc, argv, NULL, options, upload_pack_usage, 0); @@ -227,6 +227,24 @@ int xopen(const char *path, int oflag, ...) } } +static int handle_nonblock(int fd, short poll_events, int err) +{ + struct pollfd pfd; + + if (err != EAGAIN && err != EWOULDBLOCK) + return 0; + + pfd.fd = fd; + pfd.events = poll_events; + + /* + * no need to check for errors, here; + * a subsequent read/write will detect unrecoverable errors + */ + poll(&pfd, 1, -1); + return 1; +} + /* * xread() is the same a read(), but it automatically restarts read() * operations with a recoverable error (EAGAIN and EINTR). xread() @@ -242,20 +260,8 @@ ssize_t xread(int fd, void *buf, size_t len) if (nr < 0) { if (errno == EINTR) continue; - if (errno == EAGAIN || errno == EWOULDBLOCK) { - struct pollfd pfd; - pfd.events = POLLIN; - pfd.fd = fd; - /* - * it is OK if this poll() failed; we - * want to leave this infinite loop - * only when read() returns with - * success, or an expected failure, - * which would be checked by the next - * call to read(2). - */ - poll(&pfd, 1, -1); - } + if (handle_nonblock(fd, POLLIN, errno)) + continue; } return nr; } @@ -273,8 +279,13 @@ ssize_t xwrite(int fd, const void *buf, size_t len) len = MAX_IO_SIZE; while (1) { nr = write(fd, buf, len); - if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) - continue; + if (nr < 0) { + if (errno == EINTR) + continue; + if (handle_nonblock(fd, POLLOUT, errno)) + continue; + } + return nr; } } diff --git a/wt-status.c b/wt-status.c index 4ce4e35ac3..de62ab2149 100644 --- a/wt-status.c +++ b/wt-status.c @@ -263,7 +263,7 @@ static const char *wt_status_unmerged_status_string(int stagemask) case 7: return _("both modified:"); default: - die(_("bug: unhandled unmerged status %x"), stagemask); + die("bug: unhandled unmerged status %x", stagemask); } } @@ -388,7 +388,7 @@ static void wt_status_print_change_data(struct wt_status *s, status_printf(s, color(WT_STATUS_HEADER, s), "\t"); what = wt_status_diff_status_string(status); if (!what) - die(_("bug: unhandled diff status %c"), status); + die("bug: unhandled diff status %c", status); len = label_width - utf8_strwidth(what); assert(len >= 0); if (status == DIFF_STATUS_COPIED || status == DIFF_STATUS_RENAMED) @@ -432,7 +432,8 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q, d->worktree_status = p->status; d->dirty_submodule = p->two->dirty_submodule; if (S_ISGITLINK(p->two->mode)) - d->new_submodule_commits = !!hashcmp(p->one->sha1, p->two->sha1); + d->new_submodule_commits = !!oidcmp(&p->one->oid, + &p->two->oid); } } |