Merge v1.7.10-rc0 for git l10n update
This commit is contained in:
commit
13ef396635
@ -1,27 +1,54 @@
|
||||
Git v1.7.10 Release Notes
|
||||
=========================
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
|
||||
* From this release on, the "git merge" command in an interactive
|
||||
session will start an editor when it automatically resolves the
|
||||
merge for the user to explain the resulting commit, just like the
|
||||
"git commit" command does when it wasn't given a commit message.
|
||||
|
||||
If you have a script that runs "git merge" and keeps its standard
|
||||
input and output attached to the user's terminal, and if you do not
|
||||
want the user to explain the resulting merge commits, you can
|
||||
export GIT_MERGE_AUTOEDIT environment variable set to "no", like
|
||||
this:
|
||||
|
||||
#!/bin/sh
|
||||
GIT_MERGE_AUTOEDIT=no
|
||||
export GIT_MERGE_AUTOEDIT
|
||||
|
||||
to disable this behaviour (if you want your users to explain their
|
||||
merge commits, you do not have to do anything). Alternatively, you
|
||||
can give the "--no-edit" option to individual invocations of the
|
||||
"git merge" command if you know everybody who uses your script has
|
||||
Git v1.7.8 or newer.
|
||||
|
||||
|
||||
Updates since v1.7.9
|
||||
--------------------
|
||||
|
||||
UI, Workflows & Features
|
||||
|
||||
* Improved handling of views, labels and branches in git-p4 (in contrib).
|
||||
|
||||
* "git-p4" (in contrib) suffered from unnecessary merge conflicts when
|
||||
p4 expanded the embedded $RCS$-like keywords; it can be now told to
|
||||
unexpand them.
|
||||
|
||||
* Some "git-svn" updates.
|
||||
|
||||
* "vcs-svn"/"svn-fe" learned to read dumps with svn-deltas and
|
||||
support incremental imports.
|
||||
* Teams for localizing the messages from the Porcelain layer of
|
||||
commands are starting to form, thanks to Jiang Xin who volunteered
|
||||
to be the localization coordinator. An initial set of translated
|
||||
messages for simplified chinese is available.
|
||||
|
||||
* The configuration mechanism learned an "include" facility; an
|
||||
assignment to the include.path pseudo-variable causes the named
|
||||
file to be included in-place when Git looks up configuration
|
||||
variables.
|
||||
|
||||
* A content filter (clean/smudge) used to be just a way to make the
|
||||
recorded contents "more useful", and allowed to fail; a filter can
|
||||
new optionally be marked as "required".
|
||||
|
||||
* Options whose names begin with "--no-" (e.g. the "--no-verify"
|
||||
option of the "git commit" command) can be negated by omitting
|
||||
"no-" from its name, e.g. "git commit --verify".
|
||||
|
||||
* "git am" learned to pass "-b" option to underlying "git mailinfo", so
|
||||
that bracketed string other than "PATCH" at the beginning can be kept.
|
||||
|
||||
@ -35,9 +62,19 @@ UI, Workflows & Features
|
||||
lines are taken from the postimage, in order to make it easier to
|
||||
view the output.
|
||||
|
||||
* "git diff --stat" learned to adjust the width of the output on
|
||||
wider terminals, and give more columns to pathnames as needed.
|
||||
|
||||
* "diff-highlight" filter (in contrib/) was updated to produce more
|
||||
aesthetically pleasing output.
|
||||
|
||||
* "fsck" learned "--no-dangling" option to omit dangling object
|
||||
information.
|
||||
|
||||
* "git log -G" learned to pay attention to the "-i" option and can
|
||||
find patch hunks that introduce or remove a string that matches the
|
||||
given pattern ignoring the case.
|
||||
|
||||
* "git merge" in an interactive session learned to spawn the editor
|
||||
by default to let the user edit the auto-generated merge message,
|
||||
to encourage people to explain their merges better. Legacy scripts
|
||||
@ -45,8 +82,15 @@ UI, Workflows & Features
|
||||
Both "git merge" and "git pull" can be given --no-edit from the
|
||||
command line to accept the auto-generated merge message.
|
||||
|
||||
* The advise message given when the user didn't give enough clue on
|
||||
what to merge to "git pull" and "git merge" has been updated to
|
||||
be more concise and easier to understand.
|
||||
|
||||
* "git push" learned the "--prune" option, similar to "git fetch".
|
||||
|
||||
* "git symbolic-ref" learned the "--short" option to abbreviate the
|
||||
refname it shows unambiguously.
|
||||
|
||||
* "git tag --list" can be given "--points-at <object>" to limit its
|
||||
output to those that point at the given object.
|
||||
|
||||
@ -59,11 +103,29 @@ UI, Workflows & Features
|
||||
needed (including the ones that are not necessary for a specific
|
||||
task).
|
||||
|
||||
* Project search in "gitweb" shows the substring that matched in the
|
||||
project name and description highlighted.
|
||||
|
||||
Foreign Interface
|
||||
|
||||
* Improved handling of views, labels and branches in "git-p4" (in contrib).
|
||||
|
||||
* "git-p4" (in contrib) suffered from unnecessary merge conflicts when
|
||||
p4 expanded the embedded $RCS$-like keywords; it can be now told to
|
||||
unexpand them.
|
||||
|
||||
* Some "git-svn" updates.
|
||||
|
||||
* "vcs-svn"/"svn-fe" learned to read dumps with svn-deltas and
|
||||
support incremental imports.
|
||||
|
||||
* "git difftool/mergetool" learned to drive DeltaWalker.
|
||||
|
||||
Performance
|
||||
|
||||
* During "git upload-pack" in response to "git fetch", unnecessary calls
|
||||
to parse_object() have been eliminated, to help performance in
|
||||
repositories with excessive number of refs.
|
||||
* Unnecessary calls to parse_object() "git upload-pack" makes in
|
||||
response to "git fetch", have been eliminated, to help performance
|
||||
in repositories with excessive number of refs.
|
||||
|
||||
Internal Implementation (please report possible regressions)
|
||||
|
||||
@ -84,6 +146,9 @@ Internal Implementation (please report possible regressions)
|
||||
* t/Makefile is adjusted to prevent newer versions of GNU make from
|
||||
running tests in seemingly random order.
|
||||
|
||||
* The code to check if a path points at a file beyond a symbolic link
|
||||
has been restructured to be thread-safe.
|
||||
|
||||
Also contains minor documentation updates and code clean-ups.
|
||||
|
||||
|
||||
@ -94,27 +159,21 @@ Unless otherwise noted, all the fixes since v1.7.9 in the maintenance
|
||||
releases are contained in this release (see release notes to them for
|
||||
details).
|
||||
|
||||
* The bulk check-in codepath streamed contents that needs
|
||||
smudge/clean filters without running them, instead of punting and
|
||||
delegating to the codepath to run filters after slurping everything
|
||||
to core.
|
||||
(merge 4f22b10 jk/maint-avoid-streaming-filtered-contents later to maint).
|
||||
* "git bundle" did not record boundary commits correctly when there
|
||||
are many of them.
|
||||
(merge efe4be1 tr/maint-bundle-boundary later to maint).
|
||||
|
||||
* When the filter driver exits before reading the content before the
|
||||
main git process writes the contents to be filtered to the pipe to
|
||||
it, the latter could be killed with SIGPIPE instead of ignoring
|
||||
such an event as an error.
|
||||
(merge 6424c2a jb/filter-ignore-sigpipe later to maint).
|
||||
* "git diff-index" and its friends at the plumbing level showed the
|
||||
"diff --git" header and nothing else for a path whose cached stat
|
||||
info is dirty without actual difference when asked to produce a
|
||||
patch. This was a longstanding bug that we could have fixed long
|
||||
time ago.
|
||||
(merge b3f01ff jc/maint-diff-patch-header later to maint).
|
||||
|
||||
* When a remote helper exits before reading the blank line from the
|
||||
main git process to signal the end of commands, the latter could be
|
||||
killed with SIGPIPE. Instead we should ignore such event as a
|
||||
non-error.
|
||||
(merge c34fe63 sp/smart-http-failure-to-push later to maint).
|
||||
|
||||
* "git bundle create" produced a corrupt bundle file upon seeing
|
||||
commits with excessively long subject line.
|
||||
(merge 8a557bb tr/maint-bundle-long-subject later to maint).
|
||||
* The code to synthesize the fake ancestor tree used by 3-way merge
|
||||
fallback in "git am" was not prepared to read a patch created with
|
||||
a non-standard -p<num> value.
|
||||
(merge a61ba26 jc/am-3-nonstandard-popt later to maint).
|
||||
|
||||
* "gitweb" used to drop warnings in the log file when "heads" view is
|
||||
accessed in a repository whose HEAD does not point at a valid
|
||||
@ -122,7 +181,7 @@ details).
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
O=v1.7.9.2-301-g507fba2
|
||||
O=v1.7.9.3-366-g1e4d087
|
||||
echo O=$(git describe)
|
||||
git log --first-parent --oneline ^maint $O..
|
||||
echo
|
||||
|
@ -11,14 +11,41 @@ Fixes since v1.7.9.2
|
||||
to link the binary with -lintl even when libintl.h is missing from
|
||||
the system.
|
||||
|
||||
* When the filter driver exits before reading the content before the
|
||||
main git process writes the contents to be filtered to the pipe to
|
||||
it, the latter could be killed with SIGPIPE instead of ignoring
|
||||
such an event as an error.
|
||||
|
||||
* "git add --refresh <pathspec>" used to warn about unmerged paths
|
||||
outside the given pathspec.
|
||||
|
||||
* The bulk check-in codepath in "git add" streamed contents that
|
||||
needs smudge/clean filters without running them, instead of punting
|
||||
and delegating to the codepath to run filters after slurping
|
||||
everything to core.
|
||||
|
||||
* "git branch --with $that" assumed incorrectly that the user will never
|
||||
ask the question with nonsense value in $that.
|
||||
|
||||
* "git bundle create" produced a corrupt bundle file upon seeing
|
||||
commits with excessively long subject line.
|
||||
|
||||
* When a remote helper exits before reading the blank line from the
|
||||
main git process to signal the end of commands, the latter could be
|
||||
killed with SIGPIPE. Instead we should ignore such event as a
|
||||
non-error.
|
||||
|
||||
* The commit log template given with "git merge --edit" did not have
|
||||
a short instructive text like what "git commit" gives.
|
||||
|
||||
* "git rev-list --verify-objects -q" omitted the extra verification
|
||||
it needs to do over "git rev-list --objects -q" by mistake.
|
||||
|
||||
* "gitweb" used to drop warnings in the log file when "heads" view is
|
||||
accessed in a repository whose HEAD does not point at a valid
|
||||
branch.
|
||||
|
||||
* An invalid regular expression pattern given by an end user made
|
||||
"gitweb" to return garbled response.
|
||||
|
||||
Also contains minor fixes and documentation updates.
|
||||
|
@ -12,8 +12,9 @@ The configuration variables are used by both the git plumbing
|
||||
and the porcelains. The variables are divided into sections, wherein
|
||||
the fully qualified variable name of the variable itself is the last
|
||||
dot-separated segment and the section name is everything before the last
|
||||
dot. The variable names are case-insensitive and only alphanumeric
|
||||
characters are allowed. Some variables may appear multiple times.
|
||||
dot. The variable names are case-insensitive, allow only alphanumeric
|
||||
characters and `-`, and must start with an alphabetic character. Some
|
||||
variables may appear multiple times.
|
||||
|
||||
Syntax
|
||||
~~~~~~
|
||||
@ -54,9 +55,10 @@ All the other lines (and the remainder of the line after the section
|
||||
header) are recognized as setting variables, in the form
|
||||
'name = value'. If there is no equal sign on the line, the entire line
|
||||
is taken as 'name' and the variable is recognized as boolean "true".
|
||||
The variable names are case-insensitive and only alphanumeric
|
||||
characters and `-` are allowed. There can be more than one value
|
||||
for a given variable; we say then that variable is multivalued.
|
||||
The variable names are case-insensitive, allow only alphanumeric characters
|
||||
and `-`, and must start with an alphabetic character. There can be more
|
||||
than one value for a given variable; we say then that the variable is
|
||||
multivalued.
|
||||
|
||||
Leading and trailing whitespace in a variable value is discarded.
|
||||
Internal whitespace within a variable value is retained verbatim.
|
||||
@ -1273,9 +1275,10 @@ help.autocorrect::
|
||||
This is the default.
|
||||
|
||||
http.proxy::
|
||||
Override the HTTP proxy, normally configured using the 'http_proxy'
|
||||
environment variable (see linkgit:curl[1]). This can be overridden
|
||||
on a per-remote basis; see remote.<name>.proxy
|
||||
Override the HTTP proxy, normally configured using the 'http_proxy',
|
||||
'https_proxy', and 'all_proxy' environment variables (see
|
||||
`curl(1)`). This can be overridden on a per-remote basis; see
|
||||
remote.<name>.proxy
|
||||
|
||||
http.cookiefile::
|
||||
File containing previously stored cookie lines which should be used
|
||||
|
@ -52,6 +52,10 @@ directories with less than 10% of the total amount of changed files,
|
||||
and accumulating child directory counts in the parent directories:
|
||||
`files,10,cumulative`.
|
||||
|
||||
diff.statGraphWidth::
|
||||
Limit the width of the graph part in --stat output. If set, applies
|
||||
to all commands generating --stat outuput except format-patch.
|
||||
|
||||
diff.external::
|
||||
If this config variable is set, diff generation is not
|
||||
performed using the internal diff machinery, but using the
|
||||
|
@ -52,14 +52,23 @@ endif::git-format-patch[]
|
||||
--patience::
|
||||
Generate a diff using the "patience diff" algorithm.
|
||||
|
||||
--histogram::
|
||||
Generate a diff using the "histogram diff" algorithm.
|
||||
|
||||
--stat[=<width>[,<name-width>[,<count>]]]::
|
||||
Generate a diffstat. You can override the default
|
||||
output width for 80-column terminal by `--stat=<width>`.
|
||||
The width of the filename part can be controlled by
|
||||
giving another width to it separated by a comma.
|
||||
Generate a diffstat. By default, as much space as necessary
|
||||
will be used for the filename part, and the rest for the graph
|
||||
part. Maximum width defaults to terminal width, or 80 columns
|
||||
if not connected to a terminal, and can be overriden by
|
||||
`<width>`. The width of the filename part can be limited by
|
||||
giving another width `<name-width>` after a comma. The width
|
||||
of the graph part can be limited by using
|
||||
`--stat-graph-width=<width>` (affects all commands generating
|
||||
a stat graph) or by setting `diff.statGraphWidth=<width>`
|
||||
(does not affect `git format-patch`).
|
||||
By giving a third parameter `<count>`, you can limit the
|
||||
output to the first `<count>` lines, followed by
|
||||
`...` if there are more.
|
||||
output to the first `<count>` lines, followed by `...` if
|
||||
there are more.
|
||||
+
|
||||
These parameters can also be set individually with `--stat-width=<width>`,
|
||||
`--stat-name-width=<name-width>` and `--stat-count=<count>`.
|
||||
|
@ -85,8 +85,11 @@ OPTIONS
|
||||
is not exactly one.
|
||||
|
||||
--get-regexp::
|
||||
Like --get-all, but interprets the name as a regular expression.
|
||||
Also outputs the key names.
|
||||
Like --get-all, but interprets the name as a regular expression and
|
||||
writes out the key names. Regular expression matching is currently
|
||||
case-sensitive and done against a canonicalized version of the key
|
||||
in which section and variable names are lowercased, but subsection
|
||||
names are not.
|
||||
|
||||
--global::
|
||||
For writing options: write to global ~/.gitconfig file rather than
|
||||
|
@ -11,7 +11,7 @@ SYNOPSIS
|
||||
[verse]
|
||||
'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
|
||||
[--[no-]full] [--strict] [--verbose] [--lost-found]
|
||||
[--[no-]progress] [<object>*]
|
||||
[--[no-]dangling] [--[no-]progress] [<object>*]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -30,6 +30,11 @@ index file, all SHA1 references in .git/refs/*, and all reflogs (unless
|
||||
Print out objects that exist but that aren't reachable from any
|
||||
of the reference nodes.
|
||||
|
||||
--dangling::
|
||||
--no-dangling::
|
||||
Print objects that exist but that are never 'directly' used (default).
|
||||
`--no-dangling` can be used to omit this information from the output.
|
||||
|
||||
--root::
|
||||
Report root nodes.
|
||||
|
||||
|
@ -34,7 +34,7 @@ OPTIONS
|
||||
Especially useful when packing a repository that is used
|
||||
for private development. Use
|
||||
with '-d'. This will clean up the objects that `git prune`
|
||||
leaves behind, but `git fsck --full` shows as
|
||||
leaves behind, but `git fsck --full --dangling` shows as
|
||||
dangling.
|
||||
+
|
||||
Note that users fetching over dumb protocols will have to fetch the
|
||||
|
@ -8,7 +8,8 @@ git-symbolic-ref - Read and modify symbolic refs
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git symbolic-ref' [-q] [-m <reason>] <name> [<ref>]
|
||||
'git symbolic-ref' [-m <reason>] <name> <ref>
|
||||
'git symbolic-ref' [-q] [--short] <name>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -33,6 +34,10 @@ OPTIONS
|
||||
symbolic ref but a detached HEAD; instead exit with
|
||||
non-zero status silently.
|
||||
|
||||
--short::
|
||||
When showing the value of <name> as a symbolic ref, try to shorten the
|
||||
value, e.g. from `refs/heads/master` to `master`.
|
||||
|
||||
-m::
|
||||
Update the reflog for <name> with <reason>. This is valid only
|
||||
when creating or updating a symbolic ref.
|
||||
|
@ -44,9 +44,10 @@ unreleased) version of git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v1.7.9.2/git.html[documentation for release 1.7.9.2]
|
||||
* link:v1.7.9.3/git.html[documentation for release 1.7.9.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.9.3.txt[1.7.9.3],
|
||||
link:RelNotes/1.7.9.2.txt[1.7.9.2],
|
||||
link:RelNotes/1.7.9.1.txt[1.7.9.1],
|
||||
link:RelNotes/1.7.9.txt[1.7.9].
|
||||
|
@ -294,16 +294,27 @@ output is used to update the worktree file. Similarly, the
|
||||
`clean` command is used to convert the contents of worktree file
|
||||
upon checkin.
|
||||
|
||||
A missing filter driver definition in the config is not an error
|
||||
but makes the filter a no-op passthru.
|
||||
One use of the content filtering is to massage the content into a shape
|
||||
that is more convenient for the platform, filesystem, and the user to use.
|
||||
For this mode of operation, the key phrase here is "more convenient" and
|
||||
not "turning something unusable into usable". In other words, the intent
|
||||
is that if someone unsets the filter driver definition, or does not have
|
||||
the appropriate filter program, the project should still be usable.
|
||||
|
||||
The content filtering is done to massage the content into a
|
||||
shape that is more convenient for the platform, filesystem, and
|
||||
the user to use. The key phrase here is "more convenient" and not
|
||||
"turning something unusable into usable". In other words, the
|
||||
intent is that if someone unsets the filter driver definition,
|
||||
or does not have the appropriate filter program, the project
|
||||
should still be usable.
|
||||
Another use of the content filtering is to store the content that cannot
|
||||
be directly used in the repository (e.g. a UUID that refers to the true
|
||||
content stored outside git, or an encrypted content) and turn it into a
|
||||
usable form upon checkout (e.g. download the external content, or decrypt
|
||||
the encrypted content).
|
||||
|
||||
These two filters behave differently, and by default, a filter is taken as
|
||||
the former, massaging the contents into more convenient shape. A missing
|
||||
filter driver definition in the config, or a filter driver that exits with
|
||||
a non-zero status, is not an error but makes the filter a no-op passthru.
|
||||
|
||||
You can declare that a filter turns a content that by itself is unusable
|
||||
into a usable content by setting the filter.<driver>.required configuration
|
||||
variable to `true`.
|
||||
|
||||
For example, in .gitattributes, you would assign the `filter`
|
||||
attribute for paths.
|
||||
@ -335,6 +346,16 @@ input that is already correctly indented. In this case, the lack of a
|
||||
smudge filter means that the clean filter _must_ accept its own output
|
||||
without modifying it.
|
||||
|
||||
If a filter _must_ succeed in order to make the stored contents usable,
|
||||
you can declare that the filter is `required`, in the configuration:
|
||||
|
||||
------------------------
|
||||
[filter "crypt"]
|
||||
clean = openssl enc ...
|
||||
smudge = openssl enc -d ...
|
||||
required
|
||||
------------------------
|
||||
|
||||
Sequence "%f" on the filter command line is replaced with the name of
|
||||
the file the filter is working on. A filter might use this in keyword
|
||||
substitution. For example:
|
||||
|
@ -117,27 +117,27 @@ parents) and `--max-parents=-1` (negative numbers denote no upper limit).
|
||||
Pretend as if all the refs in `refs/heads` are listed
|
||||
on the command line as '<commit>'. If '<pattern>' is given, limit
|
||||
branches to ones matching given shell glob. If pattern lacks '?',
|
||||
'*', or '[', '/*' at the end is implied.
|
||||
'{asterisk}', or '[', '/{asterisk}' at the end is implied.
|
||||
|
||||
--tags[=<pattern>]::
|
||||
|
||||
Pretend as if all the refs in `refs/tags` are listed
|
||||
on the command line as '<commit>'. If '<pattern>' is given, limit
|
||||
tags to ones matching given shell glob. If pattern lacks '?', '*',
|
||||
or '[', '/*' at the end is implied.
|
||||
tags to ones matching given shell glob. If pattern lacks '?', '{asterisk}',
|
||||
or '[', '/{asterisk}' at the end is implied.
|
||||
|
||||
--remotes[=<pattern>]::
|
||||
|
||||
Pretend as if all the refs in `refs/remotes` are listed
|
||||
on the command line as '<commit>'. If '<pattern>' is given, limit
|
||||
remote-tracking branches to ones matching given shell glob.
|
||||
If pattern lacks '?', '*', or '[', '/*' at the end is implied.
|
||||
If pattern lacks '?', '{asterisk}', or '[', '/{asterisk}' at the end is implied.
|
||||
|
||||
--glob=<glob-pattern>::
|
||||
Pretend as if all the refs matching shell glob '<glob-pattern>'
|
||||
are listed on the command line as '<commit>'. Leading 'refs/',
|
||||
is automatically prepended if missing. If pattern lacks '?', '*',
|
||||
or '[', '/*' at the end is implied.
|
||||
is automatically prepended if missing. If pattern lacks '?', '{asterisk}',
|
||||
or '[', '/{asterisk}' at the end is implied.
|
||||
|
||||
--ignore-missing::
|
||||
|
||||
|
@ -101,7 +101,7 @@ the '$GIT_DIR/refs' directory or from the '$GIT_DIR/packed-refs' file.
|
||||
|
||||
'<rev>{tilde}<n>', e.g. 'master{tilde}3'::
|
||||
A suffix '{tilde}<n>' to a revision parameter means the commit
|
||||
object that is the <n>th generation grand-parent of the named
|
||||
object that is the <n>th generation ancestor of the named
|
||||
commit object, following only the first parents. I.e. '<rev>{tilde}3' is
|
||||
equivalent to '<rev>{caret}{caret}{caret}' which is equivalent to
|
||||
'<rev>{caret}1{caret}1{caret}1'. See below for an illustration of
|
||||
|
@ -39,7 +39,8 @@ The parse-options API allows:
|
||||
* Short options may be bundled, e.g. `-a -b` can be specified as `-ab`.
|
||||
|
||||
* Boolean long options can be 'negated' (or 'unset') by prepending
|
||||
`no-`, e.g. `\--no-abbrev` instead of `\--abbrev`.
|
||||
`no-`, e.g. `\--no-abbrev` instead of `\--abbrev`. Conversely,
|
||||
options that begin with `no-` can be 'negated' by removing it.
|
||||
|
||||
* Options and non-option arguments can clearly be separated using the `\--`
|
||||
option, e.g. `-a -b \--option \-- \--this-is-a-file` indicates that
|
||||
|
@ -1582,7 +1582,7 @@ Checking the repository for corruption
|
||||
|
||||
The linkgit:git-fsck[1] command runs a number of self-consistency checks
|
||||
on the repository, and reports on any problems. This may take some
|
||||
time. The most common warning by far is about "dangling" objects:
|
||||
time.
|
||||
|
||||
-------------------------------------------------
|
||||
$ git fsck
|
||||
@ -1597,9 +1597,11 @@ dangling tree b24c2473f1fd3d91352a624795be026d64c8841f
|
||||
...
|
||||
-------------------------------------------------
|
||||
|
||||
Dangling objects are not a problem. At worst they may take up a little
|
||||
extra disk space. They can sometimes provide a last-resort method for
|
||||
recovering lost work--see <<dangling-objects>> for details.
|
||||
You will see informational messages on dangling objects. They are objects
|
||||
that still exist in the repository but are no longer referenced by any of
|
||||
your branches, and can (and will) be removed after a while with "gc".
|
||||
You can run `git fsck --no-dangling` to supress these messages, and still
|
||||
view real errors.
|
||||
|
||||
[[recovering-lost-changes]]
|
||||
Recovering lost changes
|
||||
@ -3295,15 +3297,12 @@ it is with linkgit:git-fsck[1]; this may be time-consuming.
|
||||
Assume the output looks like this:
|
||||
|
||||
------------------------------------------------
|
||||
$ git fsck --full
|
||||
$ git fsck --full --no-dangling
|
||||
broken link from tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
|
||||
to blob 4b9458b3786228369c63936db65827de3cc06200
|
||||
missing blob 4b9458b3786228369c63936db65827de3cc06200
|
||||
------------------------------------------------
|
||||
|
||||
(Typically there will be some "dangling object" messages too, but they
|
||||
aren't interesting.)
|
||||
|
||||
Now you know that blob 4b9458b3 is missing, and that the tree 2d9263c6
|
||||
points to it. If you could find just one copy of that missing blob
|
||||
object, possibly in some other repository, you could move it into
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v1.7.9.GIT
|
||||
DEF_VER=v1.7.10-rc0
|
||||
|
||||
LF='
|
||||
'
|
||||
|
5
bisect.h
5
bisect.h
@ -15,13 +15,12 @@ extern void print_commit_list(struct commit_list *list,
|
||||
const char *format_cur,
|
||||
const char *format_last);
|
||||
|
||||
/* bisect_show_flags flags in struct rev_list_info */
|
||||
#define BISECT_SHOW_ALL (1<<0)
|
||||
#define BISECT_SHOW_TRIED (1<<1)
|
||||
#define REV_LIST_QUIET (1<<1)
|
||||
|
||||
struct rev_list_info {
|
||||
struct rev_info *revs;
|
||||
int bisect_show_flags;
|
||||
int flags;
|
||||
int show_timestamp;
|
||||
int hdr_termination;
|
||||
const char *header_prefix;
|
||||
|
@ -530,6 +530,10 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru
|
||||
if (merge_filter != NO_FILTER) {
|
||||
struct commit *filter;
|
||||
filter = lookup_commit_reference_gently(merge_filter_ref, 0);
|
||||
if (!filter)
|
||||
die("object '%s' does not point to a commit",
|
||||
sha1_to_hex(merge_filter_ref));
|
||||
|
||||
filter->object.flags |= UNINTERESTING;
|
||||
add_pending_object(&ref_list.revs,
|
||||
(struct object *) filter, "");
|
||||
|
@ -285,6 +285,10 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
|
||||
/* Otherwise, we are doing the usual "git" diff */
|
||||
rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
|
||||
|
||||
/* Scale to real terminal size and respect statGraphWidth config */
|
||||
rev.diffopt.stat_width = -1;
|
||||
rev.diffopt.stat_graph_width = -1;
|
||||
|
||||
/* Default to let external and textconv be used */
|
||||
DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
|
||||
DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
|
||||
|
@ -647,9 +647,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
||||
"Output full tree for each commit"),
|
||||
OPT_BOOLEAN(0, "use-done-feature", &use_done_feature,
|
||||
"Use the done feature to terminate the stream"),
|
||||
{ OPTION_NEGBIT, 0, "data", &no_data, NULL,
|
||||
"Skip output of blob data",
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NEGHELP, NULL, 1 },
|
||||
OPT_BOOL(0, "no-data", &no_data, "Skip output of blob data"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
@ -29,6 +29,7 @@ static int errors_found;
|
||||
static int write_lost_and_found;
|
||||
static int verbose;
|
||||
static int show_progress = -1;
|
||||
static int show_dangling = 1;
|
||||
#define ERROR_OBJECT 01
|
||||
#define ERROR_REACHABLE 02
|
||||
#define ERROR_PACK 04
|
||||
@ -221,8 +222,9 @@ static void check_unreachable_object(struct object *obj)
|
||||
* start looking at, for example.
|
||||
*/
|
||||
if (!obj->used) {
|
||||
printf("dangling %s %s\n", typename(obj->type),
|
||||
sha1_to_hex(obj->sha1));
|
||||
if (show_dangling)
|
||||
printf("dangling %s %s\n", typename(obj->type),
|
||||
sha1_to_hex(obj->sha1));
|
||||
if (write_lost_and_found) {
|
||||
char *filename = git_path("lost-found/%s/%s",
|
||||
obj->type == OBJ_COMMIT ? "commit" : "other",
|
||||
@ -614,6 +616,7 @@ static char const * const fsck_usage[] = {
|
||||
static struct option fsck_opts[] = {
|
||||
OPT__VERBOSE(&verbose, "be verbose"),
|
||||
OPT_BOOLEAN(0, "unreachable", &show_unreachable, "show unreachable objects"),
|
||||
OPT_BOOL(0, "dangling", &show_dangling, "show dangling objects"),
|
||||
OPT_BOOLEAN(0, "tags", &show_tags, "report tags"),
|
||||
OPT_BOOLEAN(0, "root", &show_root, "report root nodes"),
|
||||
OPT_BOOLEAN(0, "cache", &keep_cache_objects, "make index objects head nodes"),
|
||||
|
@ -684,9 +684,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
struct option options[] = {
|
||||
OPT_BOOLEAN(0, "cached", &cached,
|
||||
"search in index instead of in the work tree"),
|
||||
{ OPTION_BOOLEAN, 0, "index", &use_index, NULL,
|
||||
"finds in contents not managed by git",
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NEGHELP },
|
||||
OPT_NEGBIT(0, "no-index", &use_index,
|
||||
"finds in contents not managed by git", 1),
|
||||
OPT_BOOLEAN(0, "untracked", &untracked,
|
||||
"search in both tracked and untracked files"),
|
||||
OPT_SET_INT(0, "exclude-standard", &opt_exclude,
|
||||
|
@ -77,6 +77,8 @@ static void cmd_log_init_defaults(struct rev_info *rev)
|
||||
get_commit_format(fmt_pretty, rev);
|
||||
rev->verbose_header = 1;
|
||||
DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
|
||||
rev->diffopt.stat_width = -1; /* use full terminal width */
|
||||
rev->diffopt.stat_graph_width = -1; /* respect statGraphWidth config */
|
||||
rev->abbrev_commit = default_abbrev_commit;
|
||||
rev->show_root_diff = default_show_root;
|
||||
rev->subject_prefix = fmt_patch_subject_prefix;
|
||||
@ -447,6 +449,8 @@ int cmd_show(int argc, const char **argv, const char *prefix)
|
||||
rev.diff = 1;
|
||||
rev.always_show_header = 1;
|
||||
rev.no_walk = 1;
|
||||
rev.diffopt.stat_width = -1; /* Scale to real terminal size */
|
||||
|
||||
memset(&opt, 0, sizeof(opt));
|
||||
opt.def = "HEAD";
|
||||
opt.tweak = show_rev_tweak_rev;
|
||||
|
@ -399,6 +399,8 @@ static void finish(struct commit *head_commit,
|
||||
if (new_head && show_diffstat) {
|
||||
struct diff_options opts;
|
||||
diff_setup(&opts);
|
||||
opts.stat_width = -1; /* use full terminal width */
|
||||
opts.stat_graph_width = -1; /* respect statGraphWidth config */
|
||||
opts.output_format |=
|
||||
DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
|
||||
opts.detect_rename = DIFF_DETECT_RENAME;
|
||||
|
@ -52,6 +52,11 @@ static void show_commit(struct commit *commit, void *data)
|
||||
struct rev_list_info *info = data;
|
||||
struct rev_info *revs = info->revs;
|
||||
|
||||
if (info->flags & REV_LIST_QUIET) {
|
||||
finish_commit(commit, data);
|
||||
return;
|
||||
}
|
||||
|
||||
graph_show_commit(revs->graph);
|
||||
|
||||
if (revs->count) {
|
||||
@ -172,8 +177,11 @@ static void finish_object(struct object *obj,
|
||||
const struct name_path *path, const char *name,
|
||||
void *cb_data)
|
||||
{
|
||||
struct rev_list_info *info = cb_data;
|
||||
if (obj->type == OBJ_BLOB && !has_sha1_file(obj->sha1))
|
||||
die("missing blob object '%s'", sha1_to_hex(obj->sha1));
|
||||
if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT)
|
||||
parse_object(obj->sha1);
|
||||
}
|
||||
|
||||
static void show_object(struct object *obj,
|
||||
@ -181,10 +189,9 @@ static void show_object(struct object *obj,
|
||||
void *cb_data)
|
||||
{
|
||||
struct rev_list_info *info = cb_data;
|
||||
|
||||
finish_object(obj, path, component, cb_data);
|
||||
if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT)
|
||||
parse_object(obj->sha1);
|
||||
if (info->flags & REV_LIST_QUIET)
|
||||
return;
|
||||
show_object_with_name(stdout, obj, path, component);
|
||||
}
|
||||
|
||||
@ -242,13 +249,6 @@ void print_commit_list(struct commit_list *list,
|
||||
}
|
||||
}
|
||||
|
||||
static void show_tried_revs(struct commit_list *tried)
|
||||
{
|
||||
printf("bisect_tried='");
|
||||
print_commit_list(tried, "%s|", "%s");
|
||||
printf("'\n");
|
||||
}
|
||||
|
||||
static void print_var_str(const char *var, const char *val)
|
||||
{
|
||||
printf("%s='%s'\n", var, val);
|
||||
@ -261,12 +261,12 @@ static void print_var_int(const char *var, int val)
|
||||
|
||||
static int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
|
||||
{
|
||||
int cnt, flags = info->bisect_show_flags;
|
||||
int cnt, flags = info->flags;
|
||||
char hex[41] = "";
|
||||
struct commit_list *tried;
|
||||
struct rev_info *revs = info->revs;
|
||||
|
||||
if (!revs->commits && !(flags & BISECT_SHOW_TRIED))
|
||||
if (!revs->commits)
|
||||
return 1;
|
||||
|
||||
revs->commits = filter_skipped(revs->commits, &tried,
|
||||
@ -294,9 +294,6 @@ static int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
|
||||
printf("------\n");
|
||||
}
|
||||
|
||||
if (flags & BISECT_SHOW_TRIED)
|
||||
show_tried_revs(tried);
|
||||
|
||||
print_var_str("bisect_rev", hex);
|
||||
print_var_int("bisect_nr", cnt - 1);
|
||||
print_var_int("bisect_good", all - reaches - 1);
|
||||
@ -315,7 +312,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
||||
int bisect_list = 0;
|
||||
int bisect_show_vars = 0;
|
||||
int bisect_find_all = 0;
|
||||
int quiet = 0;
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
init_revisions(&revs, prefix);
|
||||
@ -328,7 +324,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
||||
if (revs.bisect)
|
||||
bisect_list = 1;
|
||||
|
||||
quiet = DIFF_OPT_TST(&revs.diffopt, QUICK);
|
||||
if (DIFF_OPT_TST(&revs.diffopt, QUICK))
|
||||
info.flags |= REV_LIST_QUIET;
|
||||
for (i = 1 ; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
||||
@ -347,7 +344,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
||||
if (!strcmp(arg, "--bisect-all")) {
|
||||
bisect_list = 1;
|
||||
bisect_find_all = 1;
|
||||
info.bisect_show_flags = BISECT_SHOW_ALL;
|
||||
info.flags |= BISECT_SHOW_ALL;
|
||||
revs.show_decorations = 1;
|
||||
continue;
|
||||
}
|
||||
@ -398,10 +395,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
||||
return show_bisect_vars(&info, reaches, all);
|
||||
}
|
||||
|
||||
traverse_commit_list(&revs,
|
||||
quiet ? finish_commit : show_commit,
|
||||
quiet ? finish_object : show_object,
|
||||
&info);
|
||||
traverse_commit_list(&revs, show_commit, show_object, &info);
|
||||
|
||||
if (revs.count) {
|
||||
if (revs.left_right && revs.cherry_mark)
|
||||
|
@ -8,13 +8,15 @@ static const char * const git_symbolic_ref_usage[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static int shorten;
|
||||
|
||||
static void check_symref(const char *HEAD, int quiet)
|
||||
{
|
||||
unsigned char sha1[20];
|
||||
int flag;
|
||||
const char *refs_heads_master = resolve_ref_unsafe(HEAD, sha1, 0, &flag);
|
||||
const char *refname = resolve_ref_unsafe(HEAD, sha1, 0, &flag);
|
||||
|
||||
if (!refs_heads_master)
|
||||
if (!refname)
|
||||
die("No such ref: %s", HEAD);
|
||||
else if (!(flag & REF_ISSYMREF)) {
|
||||
if (!quiet)
|
||||
@ -22,7 +24,9 @@ static void check_symref(const char *HEAD, int quiet)
|
||||
else
|
||||
exit(1);
|
||||
}
|
||||
puts(refs_heads_master);
|
||||
if (shorten)
|
||||
refname = shorten_unambiguous_ref(refname, 0);
|
||||
puts(refname);
|
||||
}
|
||||
|
||||
int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
|
||||
@ -32,6 +36,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
|
||||
struct option options[] = {
|
||||
OPT__QUIET(&quiet,
|
||||
"suppress error message for non-symbolic (detached) refs"),
|
||||
OPT_BOOL(0, "short", &shorten, "shorten ref output"),
|
||||
OPT_STRING('m', NULL, &msg, "reason", "reason of the update"),
|
||||
OPT_END(),
|
||||
};
|
||||
|
2
bundle.c
2
bundle.c
@ -273,7 +273,7 @@ int create_bundle(struct bundle_header *header, const char *path,
|
||||
if (!get_sha1_hex(buf.buf + 1, sha1)) {
|
||||
struct object *object = parse_object(sha1);
|
||||
object->flags |= UNINTERESTING;
|
||||
add_pending_object(&revs, object, buf.buf);
|
||||
add_pending_object(&revs, object, xstrdup(buf.buf));
|
||||
}
|
||||
} else if (!get_sha1_hex(buf.buf, sha1)) {
|
||||
struct object *object = parse_object(sha1);
|
||||
|
2
cache.h
2
cache.h
@ -950,7 +950,9 @@ struct cache_def {
|
||||
extern int has_symlink_leading_path(const char *name, int len);
|
||||
extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
|
||||
extern int check_leading_path(const char *name, int len);
|
||||
extern int threaded_check_leading_path(struct cache_def *cache, const char *name, int len);
|
||||
extern int has_dirs_only_path(const char *name, int len, int prefix_len);
|
||||
extern int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len);
|
||||
extern void schedule_dir_for_removal(const char *name, int len);
|
||||
extern void remove_scheduled_dirs(void);
|
||||
|
||||
|
@ -137,7 +137,7 @@ __git_ps1_show_upstream ()
|
||||
svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]}
|
||||
svn_upstream=${svn_upstream%@*}
|
||||
local n_stop="${#svn_remote[@]}"
|
||||
for ((n=1; n <= n_stop; ++n)); do
|
||||
for ((n=1; n <= n_stop; n++)); do
|
||||
svn_upstream=${svn_upstream#${svn_remote[$n]}}
|
||||
done
|
||||
|
||||
@ -166,10 +166,8 @@ __git_ps1_show_upstream ()
|
||||
for commit in $commits
|
||||
do
|
||||
case "$commit" in
|
||||
"<"*) let ++behind
|
||||
;;
|
||||
*) let ++ahead
|
||||
;;
|
||||
"<"*) ((behind++)) ;;
|
||||
*) ((ahead++)) ;;
|
||||
esac
|
||||
done
|
||||
count="$behind $ahead"
|
||||
@ -726,6 +724,9 @@ __git_complete_remote_or_refspec ()
|
||||
{
|
||||
local cur_="$cur" cmd="${words[1]}"
|
||||
local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
|
||||
if [ "$cmd" = "remote" ]; then
|
||||
((c++))
|
||||
fi
|
||||
while [ $c -lt $cword ]; do
|
||||
i="${words[c]}"
|
||||
case "$i" in
|
||||
@ -743,7 +744,7 @@ __git_complete_remote_or_refspec ()
|
||||
-*) ;;
|
||||
*) remote="$i"; break ;;
|
||||
esac
|
||||
c=$((++c))
|
||||
((c++))
|
||||
done
|
||||
if [ -z "$remote" ]; then
|
||||
__gitcomp_nl "$(__git_remotes)"
|
||||
@ -776,7 +777,7 @@ __git_complete_remote_or_refspec ()
|
||||
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
|
||||
fi
|
||||
;;
|
||||
pull)
|
||||
pull|remote)
|
||||
if [ $lhs = 1 ]; then
|
||||
__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
|
||||
else
|
||||
@ -983,7 +984,7 @@ __git_find_on_cmdline ()
|
||||
return
|
||||
fi
|
||||
done
|
||||
c=$((++c))
|
||||
((c++))
|
||||
done
|
||||
}
|
||||
|
||||
@ -994,7 +995,7 @@ __git_has_doubledash ()
|
||||
if [ "--" = "${words[c]}" ]; then
|
||||
return 0
|
||||
fi
|
||||
c=$((++c))
|
||||
((c++))
|
||||
done
|
||||
return 1
|
||||
}
|
||||
@ -1117,7 +1118,7 @@ _git_branch ()
|
||||
-d|-m) only_local_ref="y" ;;
|
||||
-r) has_r="y" ;;
|
||||
esac
|
||||
c=$((++c))
|
||||
((c++))
|
||||
done
|
||||
|
||||
case "$cur" in
|
||||
@ -2091,6 +2092,7 @@ _git_config ()
|
||||
core.whitespace
|
||||
core.worktree
|
||||
diff.autorefreshindex
|
||||
diff.statGraphWidth
|
||||
diff.external
|
||||
diff.ignoreSubmodules
|
||||
diff.mnemonicprefix
|
||||
@ -2277,7 +2279,7 @@ _git_config ()
|
||||
|
||||
_git_remote ()
|
||||
{
|
||||
local subcommands="add rename rm show prune update set-head"
|
||||
local subcommands="add rename rm set-head set-branches set-url show prune update"
|
||||
local subcommand="$(__git_find_on_cmdline "$subcommands")"
|
||||
if [ -z "$subcommand" ]; then
|
||||
__gitcomp "$subcommands"
|
||||
@ -2285,9 +2287,12 @@ _git_remote ()
|
||||
fi
|
||||
|
||||
case "$subcommand" in
|
||||
rename|rm|show|prune)
|
||||
rename|rm|set-url|show|prune)
|
||||
__gitcomp_nl "$(__git_remotes)"
|
||||
;;
|
||||
set-head|set-branches)
|
||||
__git_complete_remote_or_refspec
|
||||
;;
|
||||
update)
|
||||
local i c='' IFS=$'\n'
|
||||
for i in $(git --git-dir="$(__gitdir)" config --get-regexp "remotes\..*" 2>/dev/null); do
|
||||
@ -2568,7 +2573,7 @@ _git_tag ()
|
||||
f=1
|
||||
;;
|
||||
esac
|
||||
c=$((++c))
|
||||
((c++))
|
||||
done
|
||||
|
||||
case "$prev" in
|
||||
@ -2621,7 +2626,7 @@ _git ()
|
||||
--help) command="help"; break ;;
|
||||
*) command="$i"; break ;;
|
||||
esac
|
||||
c=$((++c))
|
||||
((c++))
|
||||
done
|
||||
|
||||
if [ -z "$command" ]; then
|
||||
|
31
contrib/diffall/README
Normal file
31
contrib/diffall/README
Normal file
@ -0,0 +1,31 @@
|
||||
The git-diffall script provides a directory based diff mechanism
|
||||
for git.
|
||||
|
||||
To determine what diff viewer is used, the script requires either
|
||||
the 'diff.tool' or 'merge.tool' configuration option to be set.
|
||||
|
||||
This script is compatible with most common forms used to specify a
|
||||
range of revisions to diff:
|
||||
|
||||
1. git diffall: shows diff between working tree and staged changes
|
||||
2. git diffall --cached [<commit>]: shows diff between staged
|
||||
changes and HEAD (or other named commit)
|
||||
3. git diffall <commit>: shows diff between working tree and named
|
||||
commit
|
||||
4. git diffall <commit> <commit>: show diff between two named commits
|
||||
5. git diffall <commit>..<commit>: same as above
|
||||
6. git diffall <commit>...<commit>: show the changes on the branch
|
||||
containing and up to the second, starting at a common ancestor
|
||||
of both <commit>
|
||||
|
||||
Note: all forms take an optional path limiter [-- <path>*]
|
||||
|
||||
The '--extcmd=<command>' option allows the user to specify a custom
|
||||
command for viewing diffs. When given, configured defaults are
|
||||
ignored and the script runs $command $LOCAL $REMOTE. Additionally,
|
||||
$BASE is set in the environment.
|
||||
|
||||
This script is based on an example provided by Thomas Rast on the
|
||||
Git list [1]:
|
||||
|
||||
[1] http://thread.gmane.org/gmane.comp.version-control.git/124807
|
261
contrib/diffall/git-diffall
Executable file
261
contrib/diffall/git-diffall
Executable file
@ -0,0 +1,261 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2010 - 2012, Tim Henigan <tim.henigan@gmail.com>
|
||||
#
|
||||
# Perform a directory diff between commits in the repository using
|
||||
# the external diff or merge tool specified in the user's config.
|
||||
|
||||
USAGE='[--cached] [--copy-back] [-x|--extcmd=<command>] <commit>{0,2} [-- <path>*]
|
||||
|
||||
--cached Compare to the index rather than the working tree.
|
||||
|
||||
--copy-back Copy files back to the working tree when the diff
|
||||
tool exits (in case they were modified by the
|
||||
user). This option is only valid if the diff
|
||||
compared with the working tree.
|
||||
|
||||
-x=<command>
|
||||
--extcmd=<command> Specify a custom command for viewing diffs.
|
||||
git-diffall ignores the configured defaults and
|
||||
runs $command $LOCAL $REMOTE when this option is
|
||||
specified. Additionally, $BASE is set in the
|
||||
environment.
|
||||
'
|
||||
|
||||
SUBDIRECTORY_OK=1
|
||||
. "$(git --exec-path)/git-sh-setup"
|
||||
|
||||
TOOL_MODE=diff
|
||||
. "$(git --exec-path)/git-mergetool--lib"
|
||||
|
||||
merge_tool="$(get_merge_tool)"
|
||||
if test -z "$merge_tool"
|
||||
then
|
||||
echo "Error: Either the 'diff.tool' or 'merge.tool' option must be set."
|
||||
usage
|
||||
fi
|
||||
|
||||
start_dir=$(pwd)
|
||||
|
||||
# needed to access tar utility
|
||||
cdup=$(git rev-parse --show-cdup) &&
|
||||
cd "$cdup" || {
|
||||
echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# mktemp is not available on all platforms (missing from msysgit)
|
||||
# Use a hard-coded tmp dir if it is not available
|
||||
tmp="$(mktemp -d -t tmp.XXXXXX 2>/dev/null)" || {
|
||||
tmp=/tmp/git-diffall-tmp.$$
|
||||
mkdir "$tmp" || exit 1
|
||||
}
|
||||
|
||||
trap 'rm -rf "$tmp" 2>/dev/null' EXIT
|
||||
|
||||
left=
|
||||
right=
|
||||
paths=
|
||||
dashdash_seen=
|
||||
compare_staged=
|
||||
merge_base=
|
||||
left_dir=
|
||||
right_dir=
|
||||
diff_tool=
|
||||
copy_back=
|
||||
|
||||
while test $# != 0
|
||||
do
|
||||
case "$1" in
|
||||
-h|--h|--he|--hel|--help)
|
||||
usage
|
||||
;;
|
||||
--cached)
|
||||
compare_staged=1
|
||||
;;
|
||||
--copy-back)
|
||||
copy_back=1
|
||||
;;
|
||||
-x|--e|--ex|--ext|--extc|--extcm|--extcmd)
|
||||
if test $# = 1
|
||||
then
|
||||
echo You must specify the tool for use with --extcmd
|
||||
usage
|
||||
else
|
||||
diff_tool=$2
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
--)
|
||||
dashdash_seen=1
|
||||
;;
|
||||
-*)
|
||||
echo Invalid option: "$1"
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
# could be commit, commit range or path limiter
|
||||
case "$1" in
|
||||
*...*)
|
||||
left=${1%...*}
|
||||
right=${1#*...}
|
||||
merge_base=1
|
||||
;;
|
||||
*..*)
|
||||
left=${1%..*}
|
||||
right=${1#*..}
|
||||
;;
|
||||
*)
|
||||
if test -n "$dashdash_seen"
|
||||
then
|
||||
paths="$paths$1 "
|
||||
elif test -z "$left"
|
||||
then
|
||||
left=$1
|
||||
elif test -z "$right"
|
||||
then
|
||||
right=$1
|
||||
else
|
||||
paths="$paths$1 "
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Determine the set of files which changed
|
||||
if test -n "$left" && test -n "$right"
|
||||
then
|
||||
left_dir="cmt-$(git rev-parse --short $left)"
|
||||
right_dir="cmt-$(git rev-parse --short $right)"
|
||||
|
||||
if test -n "$compare_staged"
|
||||
then
|
||||
usage
|
||||
elif test -n "$merge_base"
|
||||
then
|
||||
git diff --name-only "$left"..."$right" -- $paths >"$tmp/filelist"
|
||||
else
|
||||
git diff --name-only "$left" "$right" -- $paths >"$tmp/filelist"
|
||||
fi
|
||||
elif test -n "$left"
|
||||
then
|
||||
left_dir="cmt-$(git rev-parse --short $left)"
|
||||
|
||||
if test -n "$compare_staged"
|
||||
then
|
||||
right_dir="staged"
|
||||
git diff --name-only --cached "$left" -- $paths >"$tmp/filelist"
|
||||
else
|
||||
right_dir="working_tree"
|
||||
git diff --name-only "$left" -- $paths >"$tmp/filelist"
|
||||
fi
|
||||
else
|
||||
left_dir="HEAD"
|
||||
|
||||
if test -n "$compare_staged"
|
||||
then
|
||||
right_dir="staged"
|
||||
git diff --name-only --cached -- $paths >"$tmp/filelist"
|
||||
else
|
||||
right_dir="working_tree"
|
||||
git diff --name-only -- $paths >"$tmp/filelist"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Exit immediately if there are no diffs
|
||||
if test ! -s "$tmp/filelist"
|
||||
then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -n "$copy_back" && test "$right_dir" != "working_tree"
|
||||
then
|
||||
echo "--copy-back is only valid when diff includes the working tree."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create the named tmp directories that will hold the files to be compared
|
||||
mkdir -p "$tmp/$left_dir" "$tmp/$right_dir"
|
||||
|
||||
# Populate the tmp/right_dir directory with the files to be compared
|
||||
if test -n "$right"
|
||||
then
|
||||
while read name
|
||||
do
|
||||
ls_list=$(git ls-tree $right "$name")
|
||||
if test -n "$ls_list"
|
||||
then
|
||||
mkdir -p "$tmp/$right_dir/$(dirname "$name")"
|
||||
git show "$right":"$name" >"$tmp/$right_dir/$name" || true
|
||||
fi
|
||||
done < "$tmp/filelist"
|
||||
elif test -n "$compare_staged"
|
||||
then
|
||||
while read name
|
||||
do
|
||||
ls_list=$(git ls-files -- "$name")
|
||||
if test -n "$ls_list"
|
||||
then
|
||||
mkdir -p "$tmp/$right_dir/$(dirname "$name")"
|
||||
git show :"$name" >"$tmp/$right_dir/$name"
|
||||
fi
|
||||
done < "$tmp/filelist"
|
||||
else
|
||||
# Mac users have gnutar rather than tar
|
||||
(tar --ignore-failed-read -c -T "$tmp/filelist" | (cd "$tmp/$right_dir" && tar -x)) || {
|
||||
gnutar --ignore-failed-read -c -T "$tmp/filelist" | (cd "$tmp/$right_dir" && gnutar -x)
|
||||
}
|
||||
fi
|
||||
|
||||
# Populate the tmp/left_dir directory with the files to be compared
|
||||
while read name
|
||||
do
|
||||
if test -n "$left"
|
||||
then
|
||||
ls_list=$(git ls-tree $left "$name")
|
||||
if test -n "$ls_list"
|
||||
then
|
||||
mkdir -p "$tmp/$left_dir/$(dirname "$name")"
|
||||
git show "$left":"$name" >"$tmp/$left_dir/$name" || true
|
||||
fi
|
||||
else
|
||||
if test -n "$compare_staged"
|
||||
then
|
||||
ls_list=$(git ls-tree HEAD "$name")
|
||||
if test -n "$ls_list"
|
||||
then
|
||||
mkdir -p "$tmp/$left_dir/$(dirname "$name")"
|
||||
git show HEAD:"$name" >"$tmp/$left_dir/$name"
|
||||
fi
|
||||
else
|
||||
mkdir -p "$tmp/$left_dir/$(dirname "$name")"
|
||||
git show :"$name" >"$tmp/$left_dir/$name"
|
||||
fi
|
||||
fi
|
||||
done < "$tmp/filelist"
|
||||
|
||||
cd "$tmp"
|
||||
LOCAL="$left_dir"
|
||||
REMOTE="$right_dir"
|
||||
|
||||
if test -n "$diff_tool"
|
||||
then
|
||||
export BASE
|
||||
eval $diff_tool '"$LOCAL"' '"$REMOTE"'
|
||||
else
|
||||
run_merge_tool "$merge_tool" false
|
||||
fi
|
||||
|
||||
# Copy files back to the working dir, if requested
|
||||
if test -n "$copy_back" && test "$right_dir" = "working_tree"
|
||||
then
|
||||
cd "$start_dir"
|
||||
git_top_dir=$(git rev-parse --show-toplevel)
|
||||
find "$tmp/$right_dir" -type f |
|
||||
while read file
|
||||
do
|
||||
cp "$file" "$git_top_dir/${file#$tmp/$right_dir/}"
|
||||
done
|
||||
fi
|
28
convert.c
28
convert.c
@ -452,6 +452,7 @@ static struct convert_driver {
|
||||
struct convert_driver *next;
|
||||
const char *smudge;
|
||||
const char *clean;
|
||||
int required;
|
||||
} *user_convert, **user_convert_tail;
|
||||
|
||||
static int read_convert_config(const char *var, const char *value, void *cb)
|
||||
@ -495,6 +496,11 @@ static int read_convert_config(const char *var, const char *value, void *cb)
|
||||
if (!strcmp("clean", ep))
|
||||
return git_config_string(&drv->clean, var, value);
|
||||
|
||||
if (!strcmp("required", ep)) {
|
||||
drv->required = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -773,13 +779,19 @@ int convert_to_git(const char *path, const char *src, size_t len,
|
||||
{
|
||||
int ret = 0;
|
||||
const char *filter = NULL;
|
||||
int required = 0;
|
||||
struct conv_attrs ca;
|
||||
|
||||
convert_attrs(&ca, path);
|
||||
if (ca.drv)
|
||||
if (ca.drv) {
|
||||
filter = ca.drv->clean;
|
||||
required = ca.drv->required;
|
||||
}
|
||||
|
||||
ret |= apply_filter(path, src, len, dst, filter);
|
||||
if (!ret && required)
|
||||
die("%s: clean filter '%s' failed", path, ca.drv->name);
|
||||
|
||||
if (ret && dst) {
|
||||
src = dst->buf;
|
||||
len = dst->len;
|
||||
@ -797,13 +809,16 @@ static int convert_to_working_tree_internal(const char *path, const char *src,
|
||||
size_t len, struct strbuf *dst,
|
||||
int normalizing)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0, ret_filter = 0;
|
||||
const char *filter = NULL;
|
||||
int required = 0;
|
||||
struct conv_attrs ca;
|
||||
|
||||
convert_attrs(&ca, path);
|
||||
if (ca.drv)
|
||||
if (ca.drv) {
|
||||
filter = ca.drv->smudge;
|
||||
required = ca.drv->required;
|
||||
}
|
||||
|
||||
ret |= ident_to_worktree(path, src, len, dst, ca.ident);
|
||||
if (ret) {
|
||||
@ -822,7 +837,12 @@ static int convert_to_working_tree_internal(const char *path, const char *src,
|
||||
len = dst->len;
|
||||
}
|
||||
}
|
||||
return ret | apply_filter(path, src, len, dst, filter);
|
||||
|
||||
ret_filter = apply_filter(path, src, len, dst, filter);
|
||||
if (!ret_filter && required)
|
||||
die("%s: smudge filter %s failed", path, ca.drv->name);
|
||||
|
||||
return ret | ret_filter;
|
||||
}
|
||||
|
||||
int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)
|
||||
|
36
ctype.c
36
ctype.c
@ -25,3 +25,39 @@ unsigned char sane_ctype[256] = {
|
||||
A, A, A, A, A, A, A, A, A, A, A, R, R, 0, P, 0, /* 112..127 */
|
||||
/* Nothing in the 128.. range */
|
||||
};
|
||||
|
||||
/* For case-insensitive kwset */
|
||||
const char tolower_trans_tbl[256] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
' ', '!', '"', '#', '$', '%', '&', 0x27,
|
||||
'(', ')', '*', '+', ',', '-', '.', '/',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', ':', ';', '<', '=', '>', '?',
|
||||
'@', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
||||
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
|
||||
'x', 'y', 'z', '[', 0x5c, ']', '^', '_',
|
||||
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
||||
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
|
||||
'x', 'y', 'z', '{', '|', '}', '~', 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||||
};
|
||||
|
118
diff.c
118
diff.c
@ -31,6 +31,7 @@ static const char *external_diff_cmd_cfg;
|
||||
int diff_auto_refresh_index = 1;
|
||||
static int diff_mnemonic_prefix;
|
||||
static int diff_no_prefix;
|
||||
static int diff_stat_graph_width;
|
||||
static int diff_dirstat_permille_default = 30;
|
||||
static struct diff_options default_diff_options;
|
||||
|
||||
@ -156,6 +157,10 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
|
||||
diff_no_prefix = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "diff.statgraphwidth")) {
|
||||
diff_stat_graph_width = git_config_int(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "diff.external"))
|
||||
return git_config_string(&external_diff_cmd_cfg, var, value);
|
||||
if (!strcmp(var, "diff.wordregex"))
|
||||
@ -1375,7 +1380,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
|
||||
int i, len, add, del, adds = 0, dels = 0;
|
||||
uintmax_t max_change = 0, max_len = 0;
|
||||
int total_files = data->nr;
|
||||
int width, name_width, count;
|
||||
int width, name_width, graph_width, number_width = 4, count;
|
||||
const char *reset, *add_c, *del_c;
|
||||
const char *line_prefix = "";
|
||||
int extra_shown = 0;
|
||||
@ -1389,25 +1394,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
|
||||
line_prefix = msg->buf;
|
||||
}
|
||||
|
||||
width = options->stat_width ? options->stat_width : 80;
|
||||
name_width = options->stat_name_width ? options->stat_name_width : 50;
|
||||
count = options->stat_count ? options->stat_count : data->nr;
|
||||
|
||||
/* Sanity: give at least 5 columns to the graph,
|
||||
* but leave at least 10 columns for the name.
|
||||
*/
|
||||
if (width < 25)
|
||||
width = 25;
|
||||
if (name_width < 10)
|
||||
name_width = 10;
|
||||
else if (width < name_width + 15)
|
||||
name_width = width - 15;
|
||||
|
||||
/* Find the longest filename and max number of changes */
|
||||
reset = diff_get_color_opt(options, DIFF_RESET);
|
||||
add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
|
||||
del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
|
||||
|
||||
/*
|
||||
* Find the longest filename and max number of changes
|
||||
*/
|
||||
for (i = 0; (i < count) && (i < data->nr); i++) {
|
||||
struct diffstat_file *file = data->files[i];
|
||||
uintmax_t change = file->added + file->deleted;
|
||||
@ -1428,19 +1423,72 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
|
||||
}
|
||||
count = i; /* min(count, data->nr) */
|
||||
|
||||
/* Compute the width of the graph part;
|
||||
* 10 is for one blank at the beginning of the line plus
|
||||
* " | count " between the name and the graph.
|
||||
/*
|
||||
* We have width = stat_width or term_columns() columns total.
|
||||
* We want a maximum of min(max_len, stat_name_width) for the name part.
|
||||
* We want a maximum of min(max_change, stat_graph_width) for the +- part.
|
||||
* We also need 1 for " " and 4 + decimal_width(max_change)
|
||||
* for " | NNNN " and one the empty column at the end, altogether
|
||||
* 6 + decimal_width(max_change).
|
||||
*
|
||||
* From here on, name_width is the width of the name area,
|
||||
* and width is the width of the graph area.
|
||||
* If there's not enough space, we will use the smaller of
|
||||
* stat_name_width (if set) and 5/8*width for the filename,
|
||||
* and the rest for constant elements + graph part, but no more
|
||||
* than stat_graph_width for the graph part.
|
||||
* (5/8 gives 50 for filename and 30 for the constant parts + graph
|
||||
* for the standard terminal size).
|
||||
*
|
||||
* In other words: stat_width limits the maximum width, and
|
||||
* stat_name_width fixes the maximum width of the filename,
|
||||
* and is also used to divide available columns if there
|
||||
* aren't enough.
|
||||
*/
|
||||
name_width = (name_width < max_len) ? name_width : max_len;
|
||||
if (width < (name_width + 10) + max_change)
|
||||
width = width - (name_width + 10);
|
||||
else
|
||||
width = max_change;
|
||||
|
||||
if (options->stat_width == -1)
|
||||
width = term_columns();
|
||||
else
|
||||
width = options->stat_width ? options->stat_width : 80;
|
||||
|
||||
if (options->stat_graph_width == -1)
|
||||
options->stat_graph_width = diff_stat_graph_width;
|
||||
|
||||
/*
|
||||
* Guarantee 3/8*16==6 for the graph part
|
||||
* and 5/8*16==10 for the filename part
|
||||
*/
|
||||
if (width < 16 + 6 + number_width)
|
||||
width = 16 + 6 + number_width;
|
||||
|
||||
/*
|
||||
* First assign sizes that are wanted, ignoring available width.
|
||||
*/
|
||||
graph_width = (options->stat_graph_width &&
|
||||
options->stat_graph_width < max_change) ?
|
||||
options->stat_graph_width : max_change;
|
||||
name_width = (options->stat_name_width > 0 &&
|
||||
options->stat_name_width < max_len) ?
|
||||
options->stat_name_width : max_len;
|
||||
|
||||
/*
|
||||
* Adjust adjustable widths not to exceed maximum width
|
||||
*/
|
||||
if (name_width + number_width + 6 + graph_width > width) {
|
||||
if (graph_width > width * 3/8 - number_width - 6)
|
||||
graph_width = width * 3/8 - number_width - 6;
|
||||
if (options->stat_graph_width &&
|
||||
graph_width > options->stat_graph_width)
|
||||
graph_width = options->stat_graph_width;
|
||||
if (name_width > width - number_width - 6 - graph_width)
|
||||
name_width = width - number_width - 6 - graph_width;
|
||||
else
|
||||
graph_width = width - number_width - 6 - name_width;
|
||||
}
|
||||
|
||||
/*
|
||||
* From here name_width is the width of the name area,
|
||||
* and graph_width is the width of the graph area.
|
||||
* max_change is used to scale graph properly.
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
const char *prefix = "";
|
||||
char *name = data->files[i]->print_name;
|
||||
@ -1496,18 +1544,18 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
|
||||
adds += add;
|
||||
dels += del;
|
||||
|
||||
if (width <= max_change) {
|
||||
if (graph_width <= max_change) {
|
||||
int total = add + del;
|
||||
|
||||
total = scale_linear(add + del, width, max_change);
|
||||
total = scale_linear(add + del, graph_width, max_change);
|
||||
if (total < 2 && add && del)
|
||||
/* width >= 2 due to the sanity check */
|
||||
total = 2;
|
||||
if (add < del) {
|
||||
add = scale_linear(add, width, max_change);
|
||||
add = scale_linear(add, graph_width, max_change);
|
||||
del = total - add;
|
||||
} else {
|
||||
del = scale_linear(del, width, max_change);
|
||||
del = scale_linear(del, graph_width, max_change);
|
||||
add = total - del;
|
||||
}
|
||||
}
|
||||
@ -2207,7 +2255,7 @@ static void builtin_diff(const char *name_a,
|
||||
struct emit_callback ecbdata;
|
||||
const struct userdiff_funcname *pe;
|
||||
|
||||
if (!DIFF_XDL_TST(o, WHITESPACE_FLAGS) || must_show_header) {
|
||||
if (must_show_header) {
|
||||
fprintf(o->file, "%s", header.buf);
|
||||
strbuf_reset(&header);
|
||||
}
|
||||
@ -3299,6 +3347,7 @@ static int stat_opt(struct diff_options *options, const char **av)
|
||||
char *end;
|
||||
int width = options->stat_width;
|
||||
int name_width = options->stat_name_width;
|
||||
int graph_width = options->stat_graph_width;
|
||||
int count = options->stat_count;
|
||||
int argcount = 1;
|
||||
|
||||
@ -3327,6 +3376,16 @@ static int stat_opt(struct diff_options *options, const char **av)
|
||||
name_width = strtoul(av[1], &end, 10);
|
||||
argcount = 2;
|
||||
}
|
||||
} else if (!prefixcmp(arg, "-graph-width")) {
|
||||
arg += strlen("-graph-width");
|
||||
if (*arg == '=')
|
||||
graph_width = strtoul(arg + 1, &end, 10);
|
||||
else if (!*arg && !av[1])
|
||||
die("Option '--stat-graph-width' requires a value");
|
||||
else if (!*arg) {
|
||||
graph_width = strtoul(av[1], &end, 10);
|
||||
argcount = 2;
|
||||
}
|
||||
} else if (!prefixcmp(arg, "-count")) {
|
||||
arg += strlen("-count");
|
||||
if (*arg == '=')
|
||||
@ -3352,6 +3411,7 @@ static int stat_opt(struct diff_options *options, const char **av)
|
||||
return 0;
|
||||
options->output_format |= DIFF_FORMAT_DIFFSTAT;
|
||||
options->stat_name_width = name_width;
|
||||
options->stat_graph_width = graph_width;
|
||||
options->stat_width = width;
|
||||
options->stat_count = count;
|
||||
return argcount;
|
||||
|
2
diff.h
2
diff.h
@ -82,6 +82,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
|
||||
#define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27)
|
||||
#define DIFF_OPT_DIRSTAT_BY_LINE (1 << 28)
|
||||
#define DIFF_OPT_FUNCCONTEXT (1 << 29)
|
||||
#define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30)
|
||||
|
||||
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
|
||||
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
|
||||
@ -129,6 +130,7 @@ struct diff_options {
|
||||
|
||||
int stat_width;
|
||||
int stat_name_width;
|
||||
int stat_graph_width;
|
||||
int stat_count;
|
||||
const char *word_regex;
|
||||
enum diff_words_type word_diff;
|
||||
|
@ -138,8 +138,12 @@ static void diffcore_pickaxe_grep(struct diff_options *o)
|
||||
{
|
||||
int err;
|
||||
regex_t regex;
|
||||
int cflags = REG_EXTENDED | REG_NEWLINE;
|
||||
|
||||
err = regcomp(®ex, o->pickaxe, REG_EXTENDED | REG_NEWLINE);
|
||||
if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))
|
||||
cflags |= REG_ICASE;
|
||||
|
||||
err = regcomp(®ex, o->pickaxe, cflags);
|
||||
if (err) {
|
||||
char errbuf[1024];
|
||||
regerror(err, ®ex, errbuf, 1024);
|
||||
@ -237,7 +241,8 @@ static void diffcore_pickaxe_count(struct diff_options *o)
|
||||
}
|
||||
regexp = ®ex;
|
||||
} else {
|
||||
kws = kwsalloc(NULL);
|
||||
kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)
|
||||
? tolower_trans_tbl : NULL);
|
||||
kwsincr(kws, needle, len);
|
||||
kwsprep(kws);
|
||||
}
|
||||
|
@ -2712,7 +2712,7 @@ static void parse_new_tag(void)
|
||||
/* Obtain the new tag name from the rest of our command */
|
||||
sp = strchr(command_buf.buf, ' ') + 1;
|
||||
t = pool_alloc(sizeof(struct tag));
|
||||
t->next_tag = NULL;
|
||||
memset(t, 0, sizeof(struct tag));
|
||||
t->name = pool_strdup(sp);
|
||||
if (last_tag)
|
||||
last_tag->next_tag = t;
|
||||
|
11
git-am.sh
11
git-am.sh
@ -128,15 +128,18 @@ fall_back_3way () {
|
||||
mkdir "$dotest/patch-merge-tmp-dir"
|
||||
|
||||
# First see if the patch records the index info that we can use.
|
||||
git apply --build-fake-ancestor "$dotest/patch-merge-tmp-index" \
|
||||
"$dotest/patch" &&
|
||||
cmd="git apply $git_apply_opt --build-fake-ancestor" &&
|
||||
cmd="$cmd "'"$dotest/patch-merge-tmp-index" "$dotest/patch"' &&
|
||||
eval "$cmd" &&
|
||||
GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
|
||||
git write-tree >"$dotest/patch-merge-base+" ||
|
||||
cannot_fallback "$(gettext "Repository lacks necessary blobs to fall back on 3-way merge.")"
|
||||
|
||||
say Using index info to reconstruct a base tree...
|
||||
if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
|
||||
git apply --cached <"$dotest/patch"
|
||||
|
||||
cmd='GIT_INDEX_FILE="$dotest/patch-merge-tmp-index"'
|
||||
cmd="$cmd git apply --cached $git_apply_opt"' <"$dotest/patch"'
|
||||
if eval "$cmd"
|
||||
then
|
||||
mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base"
|
||||
mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index"
|
||||
|
@ -457,6 +457,9 @@ static inline int has_extension(const char *filename, const char *ext)
|
||||
return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
|
||||
}
|
||||
|
||||
/* in ctype.c, for kwset users */
|
||||
extern const char tolower_trans_tbl[256];
|
||||
|
||||
/* Sane ctype - no locale, and works with signed chars */
|
||||
#undef isascii
|
||||
#undef isspace
|
||||
|
@ -57,34 +57,31 @@ error_on_missing_default_upstream () {
|
||||
op_prep="$3"
|
||||
example="$4"
|
||||
branch_name=$(git symbolic-ref -q HEAD)
|
||||
# If there's only one remote, use that in the suggestion
|
||||
remote="<remote>"
|
||||
if test $(git remote | wc -l) = 1
|
||||
then
|
||||
remote=$(git remote)
|
||||
fi
|
||||
|
||||
if test -z "$branch_name"
|
||||
then
|
||||
echo "You are not currently on a branch, so I cannot use any
|
||||
'branch.<branchname>.merge' in your configuration file.
|
||||
Please specify which branch you want to $op_type $op_prep on the command
|
||||
line and try again (e.g. '$example').
|
||||
See git-${cmd}(1) for details."
|
||||
echo "You are not currently on a branch. Please specify which
|
||||
branch you want to $op_type $op_prep. See git-${cmd}(1) for details.
|
||||
|
||||
$example
|
||||
"
|
||||
else
|
||||
echo "You asked me to $cmd without telling me which branch you
|
||||
want to $op_type $op_prep, and 'branch.${branch_name#refs/heads/}.merge' in
|
||||
your configuration file does not tell me, either. Please
|
||||
specify which branch you want to use on the command line and
|
||||
try again (e.g. '$example').
|
||||
See git-${cmd}(1) for details.
|
||||
echo "There is no tracking information for the current branch.
|
||||
Please specify which branch you want to $op_type $op_prep.
|
||||
See git-${cmd}(1) for details
|
||||
|
||||
If you often $op_type $op_prep the same branch, you may want to
|
||||
use something like the following in your configuration file:
|
||||
[branch \"${branch_name#refs/heads/}\"]
|
||||
remote = <nickname>
|
||||
merge = <remote-ref>"
|
||||
test rebase = "$op_type" &&
|
||||
echo " rebase = true"
|
||||
echo "
|
||||
[remote \"<nickname>\"]
|
||||
url = <url>
|
||||
fetch = <refspec>
|
||||
$example
|
||||
|
||||
See git-config(1) for details."
|
||||
If you wish to set tracking information for this branch you can do so with:
|
||||
|
||||
git branch --set-upstream ${branch_name#refs/heads/} $remote/<branch>
|
||||
"
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ error_on_no_merge_candidates () {
|
||||
elif [ -z "$curr_branch" -o -z "$upstream" ]; then
|
||||
. git-parse-remote
|
||||
error_on_missing_default_upstream "pull" $op_type $op_prep \
|
||||
"git pull <repository> <refspec>"
|
||||
"git pull <remote> <branch>"
|
||||
else
|
||||
echo "Your configuration specifies to $op_type $op_prep the ref '${upstream#refs/heads/}'"
|
||||
echo "from the remote, but no such ref was fetched."
|
||||
|
@ -380,7 +380,7 @@ then
|
||||
then
|
||||
. git-parse-remote
|
||||
error_on_missing_default_upstream "rebase" "rebase" \
|
||||
"against" "git rebase <upstream branch>"
|
||||
"against" "git rebase <branch>"
|
||||
fi
|
||||
;;
|
||||
*) upstream_name="$1"
|
||||
|
@ -1081,7 +1081,16 @@ sub evaluate_and_validate_params {
|
||||
if (length($searchtext) < 2) {
|
||||
die_error(403, "At least two characters are required for search parameter");
|
||||
}
|
||||
$search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext;
|
||||
if ($search_use_regexp) {
|
||||
$search_regexp = $searchtext;
|
||||
if (!eval { qr/$search_regexp/; 1; }) {
|
||||
(my $error = $@) =~ s/ at \S+ line \d+.*\n?//;
|
||||
die_error(400, "Invalid search regexp '$search_regexp'",
|
||||
esc_html($error));
|
||||
}
|
||||
} else {
|
||||
$search_regexp = quotemeta $searchtext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1715,6 +1724,88 @@ sub chop_and_escape_str {
|
||||
}
|
||||
}
|
||||
|
||||
# Highlight selected fragments of string, using given CSS class,
|
||||
# and escape HTML. It is assumed that fragments do not overlap.
|
||||
# Regions are passed as list of pairs (array references).
|
||||
#
|
||||
# Example: esc_html_hl_regions("foobar", "mark", [ 0, 3 ]) returns
|
||||
# '<span class="mark">foo</span>bar'
|
||||
sub esc_html_hl_regions {
|
||||
my ($str, $css_class, @sel) = @_;
|
||||
return esc_html($str) unless @sel;
|
||||
|
||||
my $out = '';
|
||||
my $pos = 0;
|
||||
|
||||
for my $s (@sel) {
|
||||
$out .= esc_html(substr($str, $pos, $s->[0] - $pos))
|
||||
if ($s->[0] - $pos > 0);
|
||||
$out .= $cgi->span({-class => $css_class},
|
||||
esc_html(substr($str, $s->[0], $s->[1] - $s->[0])));
|
||||
|
||||
$pos = $s->[1];
|
||||
}
|
||||
$out .= esc_html(substr($str, $pos))
|
||||
if ($pos < length($str));
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
# return positions of beginning and end of each match
|
||||
sub matchpos_list {
|
||||
my ($str, $regexp) = @_;
|
||||
return unless (defined $str && defined $regexp);
|
||||
|
||||
my @matches;
|
||||
while ($str =~ /$regexp/g) {
|
||||
push @matches, [$-[0], $+[0]];
|
||||
}
|
||||
return @matches;
|
||||
}
|
||||
|
||||
# highlight match (if any), and escape HTML
|
||||
sub esc_html_match_hl {
|
||||
my ($str, $regexp) = @_;
|
||||
return esc_html($str) unless defined $regexp;
|
||||
|
||||
my @matches = matchpos_list($str, $regexp);
|
||||
return esc_html($str) unless @matches;
|
||||
|
||||
return esc_html_hl_regions($str, 'match', @matches);
|
||||
}
|
||||
|
||||
|
||||
# highlight match (if any) of shortened string, and escape HTML
|
||||
sub esc_html_match_hl_chopped {
|
||||
my ($str, $chopped, $regexp) = @_;
|
||||
return esc_html_match_hl($str, $regexp) unless defined $chopped;
|
||||
|
||||
my @matches = matchpos_list($str, $regexp);
|
||||
return esc_html($chopped) unless @matches;
|
||||
|
||||
# filter matches so that we mark chopped string
|
||||
my $tail = "... "; # see chop_str
|
||||
unless ($chopped =~ s/\Q$tail\E$//) {
|
||||
$tail = '';
|
||||
}
|
||||
my $chop_len = length($chopped);
|
||||
my $tail_len = length($tail);
|
||||
my @filtered;
|
||||
|
||||
for my $m (@matches) {
|
||||
if ($m->[0] > $chop_len) {
|
||||
push @filtered, [ $chop_len, $chop_len + $tail_len ] if ($tail_len > 0);
|
||||
last;
|
||||
} elsif ($m->[1] > $chop_len) {
|
||||
push @filtered, [ $m->[0], $chop_len + $tail_len ];
|
||||
last;
|
||||
}
|
||||
push @filtered, $m;
|
||||
}
|
||||
|
||||
return esc_html_hl_regions($chopped . $tail, 'match', @filtered);
|
||||
}
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## functions returning short strings
|
||||
|
||||
@ -5165,7 +5256,7 @@ sub git_patchset_body {
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
sub git_project_search_form {
|
||||
my ($searchtext, $search_use_regexp);
|
||||
my ($searchtext, $search_use_regexp) = @_;
|
||||
|
||||
my $limit = '';
|
||||
if ($project_filter) {
|
||||
@ -5359,10 +5450,17 @@ sub git_project_list_rows {
|
||||
print "</td>\n";
|
||||
}
|
||||
print "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
|
||||
-class => "list"}, esc_html($pr->{'path'})) . "</td>\n" .
|
||||
-class => "list"},
|
||||
esc_html_match_hl($pr->{'path'}, $search_regexp)) .
|
||||
"</td>\n" .
|
||||
"<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
|
||||
-class => "list", -title => $pr->{'descr_long'}},
|
||||
esc_html($pr->{'descr'})) . "</td>\n" .
|
||||
-class => "list",
|
||||
-title => $pr->{'descr_long'}},
|
||||
$search_regexp
|
||||
? esc_html_match_hl_chopped($pr->{'descr_long'},
|
||||
$pr->{'descr'}, $search_regexp)
|
||||
: esc_html($pr->{'descr'})) .
|
||||
"</td>\n" .
|
||||
"<td><i>" . chop_and_escape_str($pr->{'owner'}, 15) . "</i></td>\n";
|
||||
print "<td class=\"". age_class($pr->{'age'}) . "\">" .
|
||||
(defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n" .
|
||||
|
11
grep.c
11
grep.c
@ -168,15 +168,10 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
|
||||
p->fixed = 0;
|
||||
|
||||
if (p->fixed) {
|
||||
if (opt->regflags & REG_ICASE || p->ignore_case) {
|
||||
static char trans[256];
|
||||
int i;
|
||||
for (i = 0; i < 256; i++)
|
||||
trans[i] = tolower(i);
|
||||
p->kws = kwsalloc(trans);
|
||||
} else {
|
||||
if (opt->regflags & REG_ICASE || p->ignore_case)
|
||||
p->kws = kwsalloc(tolower_trans_tbl);
|
||||
else
|
||||
p->kws = kwsalloc(NULL);
|
||||
}
|
||||
kwsincr(p->kws, p->pattern, p->patternlen);
|
||||
kwsprep(p->kws);
|
||||
return;
|
||||
|
4
http.c
4
http.c
@ -295,8 +295,10 @@ static CURL *get_curl_handle(void)
|
||||
if (curl_ftp_no_epsv)
|
||||
curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0);
|
||||
|
||||
if (curl_http_proxy)
|
||||
if (curl_http_proxy) {
|
||||
curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
|
||||
curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
21
mergetools/deltawalker
Normal file
21
mergetools/deltawalker
Normal file
@ -0,0 +1,21 @@
|
||||
diff_cmd () {
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
merge_cmd () {
|
||||
# Adding $(pwd)/ in front of $MERGED should not be necessary.
|
||||
# However without it, DeltaWalker (at least v1.9.8 on Windows)
|
||||
# crashes with a JRE exception. The DeltaWalker user manual,
|
||||
# shows $(pwd)/ whenever the '-merged' options is given.
|
||||
# Adding it here seems to work around the problem.
|
||||
if $base_present
|
||||
then
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" -merged="$(pwd)/$MERGED"
|
||||
else
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" -merged="$(pwd)/$MERGED"
|
||||
fi >/dev/null 2>&1
|
||||
}
|
||||
|
||||
translate_merge_tool_path() {
|
||||
echo DeltaWalker
|
||||
}
|
@ -193,13 +193,14 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
|
||||
arg_end = arg + strlen(arg);
|
||||
|
||||
for (; options->type != OPTION_END; options++) {
|
||||
const char *rest;
|
||||
int flags = 0;
|
||||
const char *rest, *long_name = options->long_name;
|
||||
int flags = 0, opt_flags = 0;
|
||||
|
||||
if (!options->long_name)
|
||||
if (!long_name)
|
||||
continue;
|
||||
|
||||
rest = skip_prefix(arg, options->long_name);
|
||||
again:
|
||||
rest = skip_prefix(arg, long_name);
|
||||
if (options->type == OPTION_ARGUMENT) {
|
||||
if (!rest)
|
||||
continue;
|
||||
@ -212,7 +213,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
|
||||
}
|
||||
if (!rest) {
|
||||
/* abbreviated? */
|
||||
if (!strncmp(options->long_name, arg, arg_end - arg)) {
|
||||
if (!strncmp(long_name, arg, arg_end - arg)) {
|
||||
is_abbreviated:
|
||||
if (abbrev_option) {
|
||||
/*
|
||||
@ -227,7 +228,7 @@ is_abbreviated:
|
||||
if (!(flags & OPT_UNSET) && *arg_end)
|
||||
p->opt = arg_end + 1;
|
||||
abbrev_option = options;
|
||||
abbrev_flags = flags;
|
||||
abbrev_flags = flags ^ opt_flags;
|
||||
continue;
|
||||
}
|
||||
/* negation allowed? */
|
||||
@ -239,12 +240,18 @@ is_abbreviated:
|
||||
goto is_abbreviated;
|
||||
}
|
||||
/* negated? */
|
||||
if (strncmp(arg, "no-", 3))
|
||||
if (prefixcmp(arg, "no-")) {
|
||||
if (!prefixcmp(long_name, "no-")) {
|
||||
long_name += 3;
|
||||
opt_flags |= OPT_UNSET;
|
||||
goto again;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
flags |= OPT_UNSET;
|
||||
rest = skip_prefix(arg + 3, options->long_name);
|
||||
rest = skip_prefix(arg + 3, long_name);
|
||||
/* abbreviated and negated? */
|
||||
if (!rest && !prefixcmp(options->long_name, arg + 3))
|
||||
if (!rest && !prefixcmp(long_name, arg + 3))
|
||||
goto is_abbreviated;
|
||||
if (!rest)
|
||||
continue;
|
||||
@ -254,7 +261,7 @@ is_abbreviated:
|
||||
continue;
|
||||
p->opt = rest + 1;
|
||||
}
|
||||
return get_value(p, options, flags);
|
||||
return get_value(p, options, flags ^ opt_flags);
|
||||
}
|
||||
|
||||
if (ambiguous_option)
|
||||
@ -386,6 +393,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
||||
case -1:
|
||||
return parse_options_usage(ctx, usagestr, options, 1);
|
||||
case -2:
|
||||
if (ctx->opt)
|
||||
check_typos(arg + 1, options);
|
||||
goto unknown;
|
||||
}
|
||||
if (ctx->opt)
|
||||
@ -526,7 +535,7 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
|
||||
continue;
|
||||
|
||||
pos = fprintf(outfile, " ");
|
||||
if (opts->short_name && !(opts->flags & PARSE_OPT_NEGHELP)) {
|
||||
if (opts->short_name) {
|
||||
if (opts->flags & PARSE_OPT_NODASH)
|
||||
pos += fprintf(outfile, "%c", opts->short_name);
|
||||
else
|
||||
@ -535,9 +544,7 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
|
||||
if (opts->long_name && opts->short_name)
|
||||
pos += fprintf(outfile, ", ");
|
||||
if (opts->long_name)
|
||||
pos += fprintf(outfile, "--%s%s",
|
||||
(opts->flags & PARSE_OPT_NEGHELP) ? "no-" : "",
|
||||
opts->long_name);
|
||||
pos += fprintf(outfile, "--%s", opts->long_name);
|
||||
if (opts->type == OPTION_NUMBER)
|
||||
pos += fprintf(outfile, "-NUM");
|
||||
|
||||
|
@ -40,7 +40,6 @@ enum parse_opt_option_flags {
|
||||
PARSE_OPT_LASTARG_DEFAULT = 16,
|
||||
PARSE_OPT_NODASH = 32,
|
||||
PARSE_OPT_LITERAL_ARGHELP = 64,
|
||||
PARSE_OPT_NEGHELP = 128,
|
||||
PARSE_OPT_SHELL_EVAL = 256
|
||||
};
|
||||
|
||||
@ -90,9 +89,6 @@ typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx,
|
||||
* PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets
|
||||
* (i.e. '<argh>') in the help message.
|
||||
* Useful for options with multiple parameters.
|
||||
* PARSE_OPT_NEGHELP: says that the long option should always be shown with
|
||||
* the --no prefix in the usage message. Sometimes
|
||||
* useful for users of OPTION_NEGBIT.
|
||||
*
|
||||
* `callback`::
|
||||
* pointer to the callback to use for OPTION_CALLBACK or
|
||||
|
107
po/README
107
po/README
@ -1,33 +1,79 @@
|
||||
Core GIT Translations
|
||||
=====================
|
||||
|
||||
This directory holds the translations for the core of Git. This
|
||||
document describes how to add to and maintain these translations, and
|
||||
how to mark source strings for translation.
|
||||
This directory holds the translations for the core of Git. This document
|
||||
describes how you can contribute to the effort of enhancing the language
|
||||
coverage and maintaining the translation.
|
||||
|
||||
The localization (l10n) coordinator, Jiang Xin <worldhello.net@gmail.com>,
|
||||
coordinates our localization effort in the l10 coordinator repository:
|
||||
|
||||
https://github.com/git-l10n/git-po/
|
||||
|
||||
As a contributor for a language XX, you should first check TEAMS file in
|
||||
this directory to see whether a dedicated repository for your language XX
|
||||
exists. Fork the dedicated repository and start to work if it exists.
|
||||
|
||||
If you are the first contributor for the language XX, please fork this
|
||||
repository, prepare and/or update the translated message file po/XX.po
|
||||
(described later), and ask the l10n coordinator to pull your work.
|
||||
|
||||
If there are multiple contributors for the same language, please first
|
||||
coordinate among yourselves and nominate the team leader for your
|
||||
language, so that the l10n coordinator only needs to interact with one
|
||||
person per language.
|
||||
|
||||
The overall data-flow looks like this:
|
||||
|
||||
+-------------------+ +------------------+
|
||||
| Git source code | ---(1)---> | L10n coordinator |
|
||||
| repository | <---(4)--- | repository |
|
||||
+-------------------+ +------------------+
|
||||
| ^
|
||||
(2) (3)
|
||||
V |
|
||||
+------------------+
|
||||
| Language Team XX |
|
||||
+------------------+
|
||||
|
||||
* Translatable strings are marked in the source file.
|
||||
* L10n coordinator pulls from the source (1)
|
||||
* L10n coordinator updates the message template po/git.pot
|
||||
* Language team pulls from L10n coordinator (2)
|
||||
* Language team updates the message file po/XX.po
|
||||
* L10n coordinator pulls from Language team (3)
|
||||
* L10n coordinator asks the result to be pulled (4).
|
||||
|
||||
|
||||
Generating a .pot file
|
||||
----------------------
|
||||
Maintaining the po/git.pot file
|
||||
-------------------------------
|
||||
|
||||
(This is done by the l10n coordinator).
|
||||
|
||||
The po/git.pot file contains a message catalog extracted from Git's
|
||||
sources. You need to generate it to add new translations with
|
||||
msginit(1), or update existing ones with msgmerge(1).
|
||||
sources. The l10n coordinator maintains it by adding new translations with
|
||||
msginit(1), or update existing ones with msgmerge(1). In order to update
|
||||
the Git sources to extract the messages from, the l10n coordinator is
|
||||
expected to pull from the main git repository at strategic point in
|
||||
history (e.g. when a major release and release candidates are tagged),
|
||||
and then run "make pot" at the top-level directory.
|
||||
|
||||
Since the file can be automatically generated it's not checked into
|
||||
git.git. To generate it do, at the top-level:
|
||||
|
||||
make pot
|
||||
Language contributors use this file to prepare translations for their
|
||||
language, but they are not expected to modify it.
|
||||
|
||||
|
||||
Initializing a .po file
|
||||
-----------------------
|
||||
Initializing a XX.po file
|
||||
-------------------------
|
||||
|
||||
To add a new translation first generate git.pot (see above) and then
|
||||
in the po/ directory do:
|
||||
(This is done by the language teams).
|
||||
|
||||
If your language XX does not have translated message file po/XX.po yet,
|
||||
you add a translation for the first time by running:
|
||||
|
||||
msginit --locale=XX
|
||||
|
||||
Where XX is your locale, e.g. "is", "de" or "pt_BR".
|
||||
in the po/ directory, where XX is the locale, e.g. "de", "is", "pt_BR",
|
||||
"zh_CN", etc.
|
||||
|
||||
Then edit the automatically generated copyright info in your new XX.po
|
||||
to be correct, e.g. for Icelandic:
|
||||
@ -46,21 +92,36 @@ just "Git":
|
||||
|
||||
perl -pi -e 's/(?<="Project-Id-Version: )PACKAGE VERSION/Git/' XX.po
|
||||
|
||||
Once you are done testing the translation (see below), commit the result
|
||||
and ask the l10n coordinator to pull from you.
|
||||
|
||||
Updating a .po file
|
||||
-------------------
|
||||
|
||||
If there's an existing *.po file for your language but you need to
|
||||
update the translation you first need to generate git.pot (see above)
|
||||
and then in the po/ directory do:
|
||||
Updating a XX.po file
|
||||
---------------------
|
||||
|
||||
(This is done by the language teams).
|
||||
|
||||
If you are replacing translation strings in an existing XX.po file to
|
||||
improve the translation, just edit the file.
|
||||
|
||||
If there's an existing XX.po file for your language, but the repository
|
||||
of the l10n coordinator has newer po/git.pot file, you would need to first
|
||||
pull from the l10n coordinator (see the beginning of this document for its
|
||||
URL), and then update the existing translation by running:
|
||||
|
||||
msgmerge --add-location --backup=off -U XX.po git.pot
|
||||
|
||||
Where XX.po is the file you want to update.
|
||||
in the po/ directory, where XX.po is the file you want to update.
|
||||
|
||||
Once you are done testing the translation (see below), commit the result
|
||||
and ask the l10n coordinator to pull from you.
|
||||
|
||||
|
||||
Testing your changes
|
||||
--------------------
|
||||
|
||||
(This is done by the language teams, after creating or updating XX.po file).
|
||||
|
||||
Before you submit your changes go back to the top-level and do:
|
||||
|
||||
make
|
||||
@ -75,6 +136,8 @@ with a newline or not.
|
||||
Marking strings for translation
|
||||
-------------------------------
|
||||
|
||||
(This is done by the core developers).
|
||||
|
||||
Before strings can be translated they first have to be marked for
|
||||
translation.
|
||||
|
||||
|
15
po/TEAMS
Normal file
15
po/TEAMS
Normal file
@ -0,0 +1,15 @@
|
||||
Core Git translation language teams
|
||||
(please keep the list sorted alphabetically on language field)
|
||||
|
||||
Language: is (Icelandic)
|
||||
Leader: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
|
||||
|
||||
Language: zh_CN (Simplified Chinese)
|
||||
Repository: https://github.com/gotgit/git-po-zh_CN/
|
||||
Leader: Jiang Xin <worldhello.net@gmail.com>
|
||||
Members: Riku <lu.riku AT gmail.com>
|
||||
Zhuang Ya <zhuangya AT me.com>
|
||||
Lian Cheng <rhythm.mail AT gmail.com>
|
||||
Yichao Yu <yyc1992 AT gmail.com>
|
||||
ws3389 <willsmith3389 AT gmail.com>
|
||||
Thynson <lanxingcan AT gmail.com>
|
@ -1582,6 +1582,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
|
||||
revs->grep_filter.regflags |= REG_EXTENDED;
|
||||
} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
|
||||
revs->grep_filter.regflags |= REG_ICASE;
|
||||
DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
|
||||
} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
|
||||
revs->grep_filter.fixed = 1;
|
||||
} else if (!strcmp(arg, "--all-match")) {
|
||||
|
17
sequencer.c
17
sequencer.c
@ -123,7 +123,7 @@ static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
static void print_advice(int show_hint)
|
||||
static void print_advice(int show_hint, struct replay_opts *opts)
|
||||
{
|
||||
char *msg = getenv("GIT_CHERRY_PICK_HELP");
|
||||
|
||||
@ -138,10 +138,15 @@ static void print_advice(int show_hint)
|
||||
return;
|
||||
}
|
||||
|
||||
if (show_hint)
|
||||
advise(_("after resolving the conflicts, mark the corrected paths\n"
|
||||
"with 'git add <paths>' or 'git rm <paths>'\n"
|
||||
"and commit the result with 'git commit'"));
|
||||
if (show_hint) {
|
||||
if (opts->no_commit)
|
||||
advise(_("after resolving the conflicts, mark the corrected paths\n"
|
||||
"with 'git add <paths>' or 'git rm <paths>'"));
|
||||
else
|
||||
advise(_("after resolving the conflicts, mark the corrected paths\n"
|
||||
"with 'git add <paths>' or 'git rm <paths>'\n"
|
||||
"and commit the result with 'git commit'"));
|
||||
}
|
||||
}
|
||||
|
||||
static void write_message(struct strbuf *msgbuf, const char *filename)
|
||||
@ -423,7 +428,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
||||
: _("could not apply %s... %s"),
|
||||
find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV),
|
||||
msg.subject);
|
||||
print_advice(res == 1);
|
||||
print_advice(res == 1, opts);
|
||||
rerere(opts->allow_rerere_auto);
|
||||
} else {
|
||||
if (!opts->no_commit)
|
||||
|
28
symlinks.c
28
symlinks.c
@ -219,7 +219,20 @@ int has_symlink_leading_path(const char *name, int len)
|
||||
*/
|
||||
int check_leading_path(const char *name, int len)
|
||||
{
|
||||
struct cache_def *cache = &default_cache; /* FIXME */
|
||||
return threaded_check_leading_path(&default_cache, name, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return zero if path 'name' has a leading symlink component or
|
||||
* if some leading path component does not exists.
|
||||
*
|
||||
* Return -1 if leading path exists and is a directory.
|
||||
*
|
||||
* Return path length if leading path exists and is neither a
|
||||
* directory nor a symlink.
|
||||
*/
|
||||
int threaded_check_leading_path(struct cache_def *cache, const char *name, int len)
|
||||
{
|
||||
int flags;
|
||||
int match_len = lstat_cache_matchlen(cache, name, len, &flags,
|
||||
FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT);
|
||||
@ -240,7 +253,18 @@ int check_leading_path(const char *name, int len)
|
||||
*/
|
||||
int has_dirs_only_path(const char *name, int len, int prefix_len)
|
||||
{
|
||||
struct cache_def *cache = &default_cache; /* FIXME */
|
||||
return threaded_has_dirs_only_path(&default_cache, name, len, prefix_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return non-zero if all path components of 'name' exists as a
|
||||
* directory. If prefix_len > 0, we will test with the stat()
|
||||
* function instead of the lstat() function for a prefix length of
|
||||
* 'prefix_len', thus we then allow for symlinks in the prefix part as
|
||||
* long as those points to real existing directories.
|
||||
*/
|
||||
int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len)
|
||||
{
|
||||
return lstat_cache(cache, name, len,
|
||||
FL_DIR|FL_FULLPATH, prefix_len) &
|
||||
FL_DIR;
|
||||
|
29
t/perf/p4000-diff-algorithms.sh
Executable file
29
t/perf/p4000-diff-algorithms.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description="Tests diff generation performance"
|
||||
|
||||
. ./perf-lib.sh
|
||||
|
||||
test_perf_default_repo
|
||||
|
||||
test_perf 'log -3000 (baseline)' '
|
||||
git log -1000 >/dev/null
|
||||
'
|
||||
|
||||
test_perf 'log --raw -3000 (tree-only)' '
|
||||
git log --raw -3000 >/dev/null
|
||||
'
|
||||
|
||||
test_perf 'log -p -3000 (Myers)' '
|
||||
git log -p -3000 >/dev/null
|
||||
'
|
||||
|
||||
test_perf 'log -p -3000 --histogram' '
|
||||
git log -p -3000 --histogram >/dev/null
|
||||
'
|
||||
|
||||
test_perf 'log -p -3000 --patience' '
|
||||
git log -p -3000 --patience >/dev/null
|
||||
'
|
||||
|
||||
test_done
|
549
t/t0000-basic.sh
549
t/t0000-basic.sh
@ -34,69 +34,69 @@ fi
|
||||
# git init has been done in an empty repository.
|
||||
# make sure it is empty.
|
||||
|
||||
find .git/objects -type f -print >should-be-empty
|
||||
test_expect_success \
|
||||
'.git/objects should be empty after git init in an empty repo.' \
|
||||
'cmp -s /dev/null should-be-empty'
|
||||
test_expect_success '.git/objects should be empty after git init in an empty repo' '
|
||||
find .git/objects -type f -print >should-be-empty &&
|
||||
test_line_count = 0 should-be-empty
|
||||
'
|
||||
|
||||
# also it should have 2 subdirectories; no fan-out anymore, pack, and info.
|
||||
# 3 is counting "objects" itself
|
||||
find .git/objects -type d -print >full-of-directories
|
||||
test_expect_success \
|
||||
'.git/objects should have 3 subdirectories.' \
|
||||
'test $(wc -l < full-of-directories) = 3'
|
||||
test_expect_success '.git/objects should have 3 subdirectories' '
|
||||
find .git/objects -type d -print >full-of-directories &&
|
||||
test_line_count = 3 full-of-directories
|
||||
'
|
||||
|
||||
################################################################
|
||||
# Test harness
|
||||
test_expect_success 'success is reported like this' '
|
||||
:
|
||||
:
|
||||
'
|
||||
test_expect_failure 'pretend we have a known breakage' '
|
||||
false
|
||||
false
|
||||
'
|
||||
|
||||
test_expect_success 'pretend we have fixed a known breakage (run in sub test-lib)' "
|
||||
mkdir passing-todo &&
|
||||
(cd passing-todo &&
|
||||
cat >passing-todo.sh <<EOF &&
|
||||
#!$SHELL_PATH
|
||||
mkdir passing-todo &&
|
||||
(cd passing-todo &&
|
||||
cat >passing-todo.sh <<-EOF &&
|
||||
#!$SHELL_PATH
|
||||
|
||||
test_description='A passing TODO test
|
||||
test_description='A passing TODO test
|
||||
|
||||
This is run in a sub test-lib so that we do not get incorrect passing
|
||||
metrics
|
||||
'
|
||||
This is run in a sub test-lib so that we do not get incorrect
|
||||
passing metrics
|
||||
'
|
||||
|
||||
# Point to the t/test-lib.sh, which isn't in ../ as usual
|
||||
TEST_DIRECTORY=\"$TEST_DIRECTORY\"
|
||||
. \"\$TEST_DIRECTORY\"/test-lib.sh
|
||||
# Point to the t/test-lib.sh, which isn't in ../ as usual
|
||||
TEST_DIRECTORY=\"$TEST_DIRECTORY\"
|
||||
. \"\$TEST_DIRECTORY\"/test-lib.sh
|
||||
|
||||
test_expect_failure 'pretend we have fixed a known breakage' '
|
||||
:
|
||||
'
|
||||
test_expect_failure 'pretend we have fixed a known breakage' '
|
||||
:
|
||||
'
|
||||
|
||||
test_done
|
||||
EOF
|
||||
chmod +x passing-todo.sh &&
|
||||
./passing-todo.sh >out 2>err &&
|
||||
! test -s err &&
|
||||
sed -e 's/^> //' >expect <<EOF &&
|
||||
> ok 1 - pretend we have fixed a known breakage # TODO known breakage
|
||||
> # fixed 1 known breakage(s)
|
||||
> # passed all 1 test(s)
|
||||
> 1..1
|
||||
EOF
|
||||
test_cmp expect out)
|
||||
test_done
|
||||
EOF
|
||||
chmod +x passing-todo.sh &&
|
||||
./passing-todo.sh >out 2>err &&
|
||||
! test -s err &&
|
||||
sed -e 's/^> //' >expect <<-\\EOF &&
|
||||
> ok 1 - pretend we have fixed a known breakage # TODO known breakage
|
||||
> # fixed 1 known breakage(s)
|
||||
> # passed all 1 test(s)
|
||||
> 1..1
|
||||
EOF
|
||||
test_cmp expect out)
|
||||
"
|
||||
test_set_prereq HAVEIT
|
||||
haveit=no
|
||||
test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
|
||||
test_have_prereq HAVEIT &&
|
||||
haveit=yes
|
||||
test_have_prereq HAVEIT &&
|
||||
haveit=yes
|
||||
'
|
||||
donthaveit=yes
|
||||
test_expect_success DONTHAVEIT 'unmet prerequisite causes test to be skipped' '
|
||||
donthaveit=no
|
||||
donthaveit=no
|
||||
'
|
||||
if test $haveit$donthaveit != yesyes
|
||||
then
|
||||
@ -107,17 +107,17 @@ fi
|
||||
test_set_prereq HAVETHIS
|
||||
haveit=no
|
||||
test_expect_success HAVETHIS,HAVEIT 'test runs if prerequisites are satisfied' '
|
||||
test_have_prereq HAVEIT &&
|
||||
test_have_prereq HAVETHIS &&
|
||||
haveit=yes
|
||||
test_have_prereq HAVEIT &&
|
||||
test_have_prereq HAVETHIS &&
|
||||
haveit=yes
|
||||
'
|
||||
donthaveit=yes
|
||||
test_expect_success HAVEIT,DONTHAVEIT 'unmet prerequisites causes test to be skipped' '
|
||||
donthaveit=no
|
||||
donthaveit=no
|
||||
'
|
||||
donthaveiteither=yes
|
||||
test_expect_success DONTHAVEIT,HAVEIT 'unmet prerequisites causes test to be skipped' '
|
||||
donthaveiteither=no
|
||||
donthaveiteither=no
|
||||
'
|
||||
if test $haveit$donthaveit$donthaveiteither != yesyesyes
|
||||
then
|
||||
@ -127,7 +127,7 @@ fi
|
||||
|
||||
clean=no
|
||||
test_expect_success 'tests clean up after themselves' '
|
||||
test_when_finished clean=yes
|
||||
test_when_finished clean=yes
|
||||
'
|
||||
|
||||
if test $clean != yes
|
||||
@ -137,106 +137,100 @@ then
|
||||
fi
|
||||
|
||||
test_expect_success 'tests clean up even on failures' "
|
||||
mkdir failing-cleanup &&
|
||||
(cd failing-cleanup &&
|
||||
cat >failing-cleanup.sh <<EOF &&
|
||||
#!$SHELL_PATH
|
||||
mkdir failing-cleanup &&
|
||||
(
|
||||
cd failing-cleanup &&
|
||||
|
||||
test_description='Failing tests with cleanup commands'
|
||||
cat >failing-cleanup.sh <<-EOF &&
|
||||
#!$SHELL_PATH
|
||||
|
||||
# Point to the t/test-lib.sh, which isn't in ../ as usual
|
||||
TEST_DIRECTORY=\"$TEST_DIRECTORY\"
|
||||
. \"\$TEST_DIRECTORY\"/test-lib.sh
|
||||
test_description='Failing tests with cleanup commands'
|
||||
|
||||
test_expect_success 'tests clean up even after a failure' '
|
||||
touch clean-after-failure &&
|
||||
test_when_finished rm clean-after-failure &&
|
||||
(exit 1)
|
||||
'
|
||||
# Point to the t/test-lib.sh, which isn't in ../ as usual
|
||||
TEST_DIRECTORY=\"$TEST_DIRECTORY\"
|
||||
. \"\$TEST_DIRECTORY\"/test-lib.sh
|
||||
|
||||
test_expect_success 'failure to clean up causes the test to fail' '
|
||||
test_when_finished \"(exit 2)\"
|
||||
'
|
||||
test_expect_success 'tests clean up even after a failure' '
|
||||
touch clean-after-failure &&
|
||||
test_when_finished rm clean-after-failure &&
|
||||
(exit 1)
|
||||
'
|
||||
test_expect_success 'failure to clean up causes the test to fail' '
|
||||
test_when_finished \"(exit 2)\"
|
||||
'
|
||||
test_done
|
||||
|
||||
test_done
|
||||
EOF
|
||||
chmod +x failing-cleanup.sh &&
|
||||
test_must_fail ./failing-cleanup.sh >out 2>err &&
|
||||
! test -s err &&
|
||||
! test -f \"trash directory.failing-cleanup/clean-after-failure\" &&
|
||||
sed -e 's/Z$//' -e 's/^> //' >expect <<\EOF &&
|
||||
> not ok - 1 tests clean up even after a failure
|
||||
> # Z
|
||||
> # touch clean-after-failure &&
|
||||
> # test_when_finished rm clean-after-failure &&
|
||||
> # (exit 1)
|
||||
> # Z
|
||||
> not ok - 2 failure to clean up causes the test to fail
|
||||
> # Z
|
||||
> # test_when_finished \"(exit 2)\"
|
||||
> # Z
|
||||
> # failed 2 among 2 test(s)
|
||||
> 1..2
|
||||
EOF
|
||||
test_cmp expect out)
|
||||
EOF
|
||||
|
||||
chmod +x failing-cleanup.sh &&
|
||||
test_must_fail ./failing-cleanup.sh >out 2>err &&
|
||||
! test -s err &&
|
||||
! test -f \"trash directory.failing-cleanup/clean-after-failure\" &&
|
||||
sed -e 's/Z$//' -e 's/^> //' >expect <<-\\EOF &&
|
||||
> not ok - 1 tests clean up even after a failure
|
||||
> # Z
|
||||
> # touch clean-after-failure &&
|
||||
> # test_when_finished rm clean-after-failure &&
|
||||
> # (exit 1)
|
||||
> # Z
|
||||
> not ok - 2 failure to clean up causes the test to fail
|
||||
> # Z
|
||||
> # test_when_finished \"(exit 2)\"
|
||||
> # Z
|
||||
> # failed 2 among 2 test(s)
|
||||
> 1..2
|
||||
EOF
|
||||
test_cmp expect out
|
||||
)
|
||||
"
|
||||
|
||||
################################################################
|
||||
# Basics of the basics
|
||||
|
||||
# updating a new file without --add should fail.
|
||||
test_expect_success 'git update-index without --add should fail adding.' '
|
||||
test_must_fail git update-index should-be-empty
|
||||
test_expect_success 'git update-index without --add should fail adding' '
|
||||
test_must_fail git update-index should-be-empty
|
||||
'
|
||||
|
||||
# and with --add it should succeed, even if it is empty (it used to fail).
|
||||
test_expect_success \
|
||||
'git update-index with --add should succeed.' \
|
||||
'git update-index --add should-be-empty'
|
||||
|
||||
test_expect_success \
|
||||
'writing tree out with git write-tree' \
|
||||
'tree=$(git write-tree)'
|
||||
|
||||
# we know the shape and contents of the tree and know the object ID for it.
|
||||
test_expect_success \
|
||||
'validate object ID of a known tree.' \
|
||||
'test "$tree" = 7bb943559a305bdd6bdee2cef6e5df2413c3d30a'
|
||||
|
||||
# Removing paths.
|
||||
rm -f should-be-empty full-of-directories
|
||||
test_expect_success 'git update-index without --remove should fail removing.' '
|
||||
test_must_fail git update-index should-be-empty
|
||||
test_expect_success 'git update-index with --add should succeed' '
|
||||
git update-index --add should-be-empty
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'git update-index with --remove should be able to remove.' \
|
||||
'git update-index --remove should-be-empty'
|
||||
test_expect_success 'writing tree out with git write-tree' '
|
||||
tree=$(git write-tree)
|
||||
'
|
||||
|
||||
# we know the shape and contents of the tree and know the object ID for it.
|
||||
test_expect_success 'validate object ID of a known tree' '
|
||||
test "$tree" = 7bb943559a305bdd6bdee2cef6e5df2413c3d30a
|
||||
'
|
||||
|
||||
# Removing paths.
|
||||
test_expect_success 'git update-index without --remove should fail removing' '
|
||||
rm -f should-be-empty full-of-directories &&
|
||||
test_must_fail git update-index should-be-empty
|
||||
'
|
||||
|
||||
test_expect_success 'git update-index with --remove should be able to remove' '
|
||||
git update-index --remove should-be-empty
|
||||
'
|
||||
|
||||
# Empty tree can be written with recent write-tree.
|
||||
test_expect_success \
|
||||
'git write-tree should be able to write an empty tree.' \
|
||||
'tree=$(git write-tree)'
|
||||
test_expect_success 'git write-tree should be able to write an empty tree' '
|
||||
tree=$(git write-tree)
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'validate object ID of a known tree.' \
|
||||
'test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904'
|
||||
test_expect_success 'validate object ID of a known tree' '
|
||||
test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904
|
||||
'
|
||||
|
||||
# Various types of objects
|
||||
|
||||
# Some filesystems do not support symblic links; on such systems
|
||||
# some expected values are different
|
||||
mkdir path2 path3 path3/subp3
|
||||
paths='path0 path2/file2 path3/file3 path3/subp3/file3'
|
||||
for p in $paths
|
||||
do
|
||||
echo "hello $p" >$p
|
||||
done
|
||||
if test_have_prereq SYMLINKS
|
||||
then
|
||||
for p in $paths
|
||||
do
|
||||
ln -s "hello $p" ${p}sym
|
||||
done
|
||||
expectfilter=cat
|
||||
expectedtree=087704a96baf1c2d1c869a8b084481e121c88b5b
|
||||
expectedptree1=21ae8269cacbe57ae09138dcc3a2887f904d02b3
|
||||
@ -248,135 +242,154 @@ else
|
||||
expectedptree2=ce580448f0148b985a513b693fdf7d802cacb44f
|
||||
fi
|
||||
|
||||
test_expect_success \
|
||||
'adding various types of objects with git update-index --add.' \
|
||||
'find path* ! -type d -print | xargs git update-index --add'
|
||||
|
||||
test_expect_success 'adding various types of objects with git update-index --add' '
|
||||
mkdir path2 path3 path3/subp3 &&
|
||||
paths="path0 path2/file2 path3/file3 path3/subp3/file3" &&
|
||||
(
|
||||
for p in $paths
|
||||
do
|
||||
echo "hello $p" >$p || exit 1
|
||||
if test_have_prereq SYMLINKS
|
||||
then
|
||||
ln -s "hello $p" ${p}sym || exit 1
|
||||
fi
|
||||
done
|
||||
) &&
|
||||
find path* ! -type d -print | xargs git update-index --add
|
||||
'
|
||||
|
||||
# Show them and see that matches what we expect.
|
||||
test_expect_success \
|
||||
'showing stage with git ls-files --stage' \
|
||||
'git ls-files --stage >current'
|
||||
test_expect_success 'showing stage with git ls-files --stage' '
|
||||
git ls-files --stage >current
|
||||
'
|
||||
|
||||
$expectfilter >expected <<\EOF
|
||||
100644 f87290f8eb2cbbea7857214459a0739927eab154 0 path0
|
||||
120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0 path0sym
|
||||
100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0 path2/file2
|
||||
120000 d8ce161addc5173867a3c3c730924388daedbc38 0 path2/file2sym
|
||||
100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0 path3/file3
|
||||
120000 8599103969b43aff7e430efea79ca4636466794f 0 path3/file3sym
|
||||
100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0 path3/subp3/file3
|
||||
120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0 path3/subp3/file3sym
|
||||
EOF
|
||||
test_expect_success \
|
||||
'validate git ls-files output for a known tree.' \
|
||||
'test_cmp expected current'
|
||||
test_expect_success 'validate git ls-files output for a known tree' '
|
||||
$expectfilter >expected <<-\EOF &&
|
||||
100644 f87290f8eb2cbbea7857214459a0739927eab154 0 path0
|
||||
120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0 path0sym
|
||||
100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0 path2/file2
|
||||
120000 d8ce161addc5173867a3c3c730924388daedbc38 0 path2/file2sym
|
||||
100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0 path3/file3
|
||||
120000 8599103969b43aff7e430efea79ca4636466794f 0 path3/file3sym
|
||||
100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0 path3/subp3/file3
|
||||
120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0 path3/subp3/file3sym
|
||||
EOF
|
||||
test_cmp expected current
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'writing tree out with git write-tree.' \
|
||||
'tree=$(git write-tree)'
|
||||
test_expect_success \
|
||||
'validate object ID for a known tree.' \
|
||||
'test "$tree" = "$expectedtree"'
|
||||
test_expect_success 'writing tree out with git write-tree' '
|
||||
tree=$(git write-tree)
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'showing tree with git ls-tree' \
|
||||
'git ls-tree $tree >current'
|
||||
cat >expected <<\EOF
|
||||
100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0
|
||||
120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym
|
||||
040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2
|
||||
040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3
|
||||
EOF
|
||||
test_expect_success SYMLINKS \
|
||||
'git ls-tree output for a known tree.' \
|
||||
'test_cmp expected current'
|
||||
test_expect_success 'validate object ID for a known tree' '
|
||||
test "$tree" = "$expectedtree"
|
||||
'
|
||||
|
||||
test_expect_success 'showing tree with git ls-tree' '
|
||||
git ls-tree $tree >current
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'git ls-tree output for a known tree' '
|
||||
cat >expected <<-\EOF &&
|
||||
100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0
|
||||
120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym
|
||||
040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2
|
||||
040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3
|
||||
EOF
|
||||
test_cmp expected current
|
||||
'
|
||||
|
||||
# This changed in ls-tree pathspec change -- recursive does
|
||||
# not show tree nodes anymore.
|
||||
test_expect_success \
|
||||
'showing tree with git ls-tree -r' \
|
||||
'git ls-tree -r $tree >current'
|
||||
$expectfilter >expected <<\EOF
|
||||
100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0
|
||||
120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym
|
||||
100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2
|
||||
120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym
|
||||
100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3
|
||||
120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym
|
||||
100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3
|
||||
120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym
|
||||
EOF
|
||||
test_expect_success \
|
||||
'git ls-tree -r output for a known tree.' \
|
||||
'test_cmp expected current'
|
||||
|
||||
# But with -r -t we can have both.
|
||||
test_expect_success \
|
||||
'showing tree with git ls-tree -r -t' \
|
||||
'git ls-tree -r -t $tree >current'
|
||||
cat >expected <<\EOF
|
||||
100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0
|
||||
120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym
|
||||
040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2
|
||||
100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2
|
||||
120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym
|
||||
040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3
|
||||
100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3
|
||||
120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym
|
||||
040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3
|
||||
100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3
|
||||
120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym
|
||||
EOF
|
||||
test_expect_success SYMLINKS \
|
||||
'git ls-tree -r output for a known tree.' \
|
||||
'test_cmp expected current'
|
||||
|
||||
test_expect_success \
|
||||
'writing partial tree out with git write-tree --prefix.' \
|
||||
'ptree=$(git write-tree --prefix=path3)'
|
||||
test_expect_success \
|
||||
'validate object ID for a known tree.' \
|
||||
'test "$ptree" = "$expectedptree1"'
|
||||
|
||||
test_expect_success \
|
||||
'writing partial tree out with git write-tree --prefix.' \
|
||||
'ptree=$(git write-tree --prefix=path3/subp3)'
|
||||
test_expect_success \
|
||||
'validate object ID for a known tree.' \
|
||||
'test "$ptree" = "$expectedptree2"'
|
||||
|
||||
cat >badobjects <<EOF
|
||||
100644 blob 1000000000000000000000000000000000000000 dir/file1
|
||||
100644 blob 2000000000000000000000000000000000000000 dir/file2
|
||||
100644 blob 3000000000000000000000000000000000000000 dir/file3
|
||||
100644 blob 4000000000000000000000000000000000000000 dir/file4
|
||||
100644 blob 5000000000000000000000000000000000000000 dir/file5
|
||||
EOF
|
||||
|
||||
rm .git/index
|
||||
test_expect_success \
|
||||
'put invalid objects into the index.' \
|
||||
'git update-index --index-info < badobjects'
|
||||
|
||||
test_expect_success 'writing this tree without --missing-ok.' '
|
||||
test_must_fail git write-tree
|
||||
test_expect_success 'showing tree with git ls-tree -r' '
|
||||
git ls-tree -r $tree >current
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'writing this tree with --missing-ok.' \
|
||||
'git write-tree --missing-ok'
|
||||
test_expect_success 'git ls-tree -r output for a known tree' '
|
||||
$expectfilter >expected <<-\EOF &&
|
||||
100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0
|
||||
120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym
|
||||
100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2
|
||||
120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym
|
||||
100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3
|
||||
120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym
|
||||
100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3
|
||||
120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym
|
||||
EOF
|
||||
test_cmp expected current
|
||||
'
|
||||
|
||||
# But with -r -t we can have both.
|
||||
test_expect_success 'showing tree with git ls-tree -r -t' '
|
||||
git ls-tree -r -t $tree >current
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'git ls-tree -r output for a known tree' '
|
||||
cat >expected <<-\EOF &&
|
||||
100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0
|
||||
120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym
|
||||
040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2
|
||||
100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2
|
||||
120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym
|
||||
040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3
|
||||
100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3
|
||||
120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym
|
||||
040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3
|
||||
100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3
|
||||
120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym
|
||||
EOF
|
||||
test_cmp expected current
|
||||
'
|
||||
|
||||
test_expect_success 'writing partial tree out with git write-tree --prefix' '
|
||||
ptree=$(git write-tree --prefix=path3)
|
||||
'
|
||||
|
||||
test_expect_success 'validate object ID for a known tree' '
|
||||
test "$ptree" = "$expectedptree1"
|
||||
'
|
||||
|
||||
test_expect_success 'writing partial tree out with git write-tree --prefix' '
|
||||
ptree=$(git write-tree --prefix=path3/subp3)
|
||||
'
|
||||
|
||||
test_expect_success 'validate object ID for a known tree' '
|
||||
test "$ptree" = "$expectedptree2"
|
||||
'
|
||||
|
||||
test_expect_success 'put invalid objects into the index' '
|
||||
rm -f .git/index &&
|
||||
cat >badobjects <<-\EOF &&
|
||||
100644 blob 1000000000000000000000000000000000000000 dir/file1
|
||||
100644 blob 2000000000000000000000000000000000000000 dir/file2
|
||||
100644 blob 3000000000000000000000000000000000000000 dir/file3
|
||||
100644 blob 4000000000000000000000000000000000000000 dir/file4
|
||||
100644 blob 5000000000000000000000000000000000000000 dir/file5
|
||||
EOF
|
||||
git update-index --index-info <badobjects
|
||||
'
|
||||
|
||||
test_expect_success 'writing this tree without --missing-ok' '
|
||||
test_must_fail git write-tree
|
||||
'
|
||||
|
||||
test_expect_success 'writing this tree with --missing-ok' '
|
||||
git write-tree --missing-ok
|
||||
'
|
||||
|
||||
|
||||
################################################################
|
||||
rm .git/index
|
||||
test_expect_success \
|
||||
'git read-tree followed by write-tree should be idempotent.' \
|
||||
'git read-tree $tree &&
|
||||
test -f .git/index &&
|
||||
newtree=$(git write-tree) &&
|
||||
test "$newtree" = "$tree"'
|
||||
test_expect_success 'git read-tree followed by write-tree should be idempotent' '
|
||||
rm -f .git/index
|
||||
git read-tree $tree &&
|
||||
test -f .git/index &&
|
||||
newtree=$(git write-tree) &&
|
||||
test "$newtree" = "$tree"
|
||||
'
|
||||
|
||||
$expectfilter >expected <<\EOF
|
||||
test_expect_success 'validate git diff-files output for a know cache/work tree state' '
|
||||
$expectfilter >expected <<\EOF &&
|
||||
:100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M path0
|
||||
:120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M path0sym
|
||||
:100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M path2/file2
|
||||
@ -386,45 +399,47 @@ $expectfilter >expected <<\EOF
|
||||
:100644 100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0000000000000000000000000000000000000000 M path3/subp3/file3
|
||||
:120000 120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0000000000000000000000000000000000000000 M path3/subp3/file3sym
|
||||
EOF
|
||||
test_expect_success \
|
||||
'validate git diff-files output for a know cache/work tree state.' \
|
||||
'git diff-files >current && test_cmp current expected >/dev/null'
|
||||
git diff-files >current &&
|
||||
test_cmp current expected
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'git update-index --refresh should succeed.' \
|
||||
'git update-index --refresh'
|
||||
test_expect_success 'git update-index --refresh should succeed' '
|
||||
git update-index --refresh
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'no diff after checkout and git update-index --refresh.' \
|
||||
'git diff-files >current && cmp -s current /dev/null'
|
||||
test_expect_success 'no diff after checkout and git update-index --refresh' '
|
||||
git diff-files >current &&
|
||||
cmp -s current /dev/null
|
||||
'
|
||||
|
||||
################################################################
|
||||
P=$expectedtree
|
||||
test_expect_success \
|
||||
'git commit-tree records the correct tree in a commit.' \
|
||||
'commit0=$(echo NO | git commit-tree $P) &&
|
||||
tree=$(git show --pretty=raw $commit0 |
|
||||
sed -n -e "s/^tree //p" -e "/^author /q") &&
|
||||
test "z$tree" = "z$P"'
|
||||
|
||||
test_expect_success \
|
||||
'git commit-tree records the correct parent in a commit.' \
|
||||
'commit1=$(echo NO | git commit-tree $P -p $commit0) &&
|
||||
parent=$(git show --pretty=raw $commit1 |
|
||||
sed -n -e "s/^parent //p" -e "/^author /q") &&
|
||||
test "z$commit0" = "z$parent"'
|
||||
test_expect_success 'git commit-tree records the correct tree in a commit' '
|
||||
commit0=$(echo NO | git commit-tree $P) &&
|
||||
tree=$(git show --pretty=raw $commit0 |
|
||||
sed -n -e "s/^tree //p" -e "/^author /q") &&
|
||||
test "z$tree" = "z$P"
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'git commit-tree omits duplicated parent in a commit.' \
|
||||
'commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) &&
|
||||
parent=$(git show --pretty=raw $commit2 |
|
||||
sed -n -e "s/^parent //p" -e "/^author /q" |
|
||||
sort -u) &&
|
||||
test "z$commit0" = "z$parent" &&
|
||||
numparent=$(git show --pretty=raw $commit2 |
|
||||
sed -n -e "s/^parent //p" -e "/^author /q" |
|
||||
wc -l) &&
|
||||
test $numparent = 1'
|
||||
test_expect_success 'git commit-tree records the correct parent in a commit' '
|
||||
commit1=$(echo NO | git commit-tree $P -p $commit0) &&
|
||||
parent=$(git show --pretty=raw $commit1 |
|
||||
sed -n -e "s/^parent //p" -e "/^author /q") &&
|
||||
test "z$commit0" = "z$parent"
|
||||
'
|
||||
|
||||
test_expect_success 'git commit-tree omits duplicated parent in a commit' '
|
||||
commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) &&
|
||||
parent=$(git show --pretty=raw $commit2 |
|
||||
sed -n -e "s/^parent //p" -e "/^author /q" |
|
||||
sort -u) &&
|
||||
test "z$commit0" = "z$parent" &&
|
||||
numparent=$(git show --pretty=raw $commit2 |
|
||||
sed -n -e "s/^parent //p" -e "/^author /q" |
|
||||
wc -l) &&
|
||||
test $numparent = 1
|
||||
'
|
||||
|
||||
test_expect_success 'update-index D/F conflict' '
|
||||
mv path0 tmp &&
|
||||
|
@ -153,4 +153,41 @@ test_expect_success 'filter shell-escaped filenames' '
|
||||
:
|
||||
'
|
||||
|
||||
test_expect_success 'required filter success' '
|
||||
git config filter.required.smudge cat &&
|
||||
git config filter.required.clean cat &&
|
||||
git config filter.required.required true &&
|
||||
|
||||
echo "*.r filter=required" >.gitattributes &&
|
||||
|
||||
echo test >test.r &&
|
||||
git add test.r &&
|
||||
rm -f test.r &&
|
||||
git checkout -- test.r
|
||||
'
|
||||
|
||||
test_expect_success 'required filter smudge failure' '
|
||||
git config filter.failsmudge.smudge false &&
|
||||
git config filter.failsmudge.clean cat &&
|
||||
git config filter.failsmudge.required true &&
|
||||
|
||||
echo "*.fs filter=failsmudge" >.gitattributes &&
|
||||
|
||||
echo test >test.fs &&
|
||||
git add test.fs &&
|
||||
rm -f test.fs &&
|
||||
test_must_fail git checkout -- test.fs
|
||||
'
|
||||
|
||||
test_expect_success 'required filter clean failure' '
|
||||
git config filter.failclean.smudge cat &&
|
||||
git config filter.failclean.clean false &&
|
||||
git config filter.failclean.required true &&
|
||||
|
||||
echo "*.fc filter=failclean" >.gitattributes &&
|
||||
|
||||
echo test >test.fc &&
|
||||
test_must_fail git add test.fc
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -10,7 +10,10 @@ test_description='our own option parser'
|
||||
cat > expect << EOF
|
||||
usage: test-parse-options <options>
|
||||
|
||||
-b, --boolean get a boolean
|
||||
--yes get a boolean
|
||||
-D, --no-doubt begins with 'no-'
|
||||
-B, --no-fear be brave
|
||||
-b, --boolean increment by one
|
||||
-4, --or4 bitwise-or boolean with ...0100
|
||||
--neg-or4 same as --no-or4
|
||||
|
||||
@ -53,6 +56,59 @@ test_expect_success 'test help' '
|
||||
|
||||
mv expect expect.err
|
||||
|
||||
cat >expect.template <<EOF
|
||||
boolean: 0
|
||||
integer: 0
|
||||
timestamp: 0
|
||||
string: (not set)
|
||||
abbrev: 7
|
||||
verbose: 0
|
||||
quiet: no
|
||||
dry run: no
|
||||
file: (not set)
|
||||
EOF
|
||||
|
||||
check() {
|
||||
what="$1" &&
|
||||
shift &&
|
||||
expect="$1" &&
|
||||
shift &&
|
||||
sed "s/^$what .*/$what $expect/" <expect.template >expect &&
|
||||
test-parse-options $* >output 2>output.err &&
|
||||
test ! -s output.err &&
|
||||
test_cmp expect output
|
||||
}
|
||||
|
||||
check_unknown() {
|
||||
case "$1" in
|
||||
--*)
|
||||
echo error: unknown option \`${1#--}\' >expect ;;
|
||||
-*)
|
||||
echo error: unknown switch \`${1#-}\' >expect ;;
|
||||
esac &&
|
||||
cat expect.err >>expect &&
|
||||
test_must_fail test-parse-options $* >output 2>output.err &&
|
||||
test ! -s output &&
|
||||
test_cmp expect output.err
|
||||
}
|
||||
|
||||
test_expect_success 'OPT_BOOL() #1' 'check boolean: 1 --yes'
|
||||
test_expect_success 'OPT_BOOL() #2' 'check boolean: 1 --no-doubt'
|
||||
test_expect_success 'OPT_BOOL() #3' 'check boolean: 1 -D'
|
||||
test_expect_success 'OPT_BOOL() #4' 'check boolean: 1 --no-fear'
|
||||
test_expect_success 'OPT_BOOL() #5' 'check boolean: 1 -B'
|
||||
|
||||
test_expect_success 'OPT_BOOL() is idempotent #1' 'check boolean: 1 --yes --yes'
|
||||
test_expect_success 'OPT_BOOL() is idempotent #2' 'check boolean: 1 -DB'
|
||||
|
||||
test_expect_success 'OPT_BOOL() negation #1' 'check boolean: 0 -D --no-yes'
|
||||
test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt'
|
||||
|
||||
test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown --fear'
|
||||
test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown --no-no-fear'
|
||||
|
||||
test_expect_success 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt'
|
||||
|
||||
cat > expect << EOF
|
||||
boolean: 2
|
||||
integer: 1729
|
||||
@ -180,6 +236,16 @@ test_expect_success 'detect possible typos' '
|
||||
test_cmp typo.err output.err
|
||||
'
|
||||
|
||||
cat > typo.err << EOF
|
||||
error: did you mean \`--ambiguous\` (with two dashes ?)
|
||||
EOF
|
||||
|
||||
test_expect_success 'detect possible typos' '
|
||||
test_must_fail test-parse-options -ambiguous > output 2> output.err &&
|
||||
test ! -s output &&
|
||||
test_cmp typo.err output.err
|
||||
'
|
||||
|
||||
cat > expect <<EOF
|
||||
boolean: 0
|
||||
integer: 0
|
||||
@ -296,7 +362,7 @@ test_expect_success 'OPT_NEGBIT() works' '
|
||||
test_cmp expect output
|
||||
'
|
||||
|
||||
test_expect_success 'OPT_BOOLEAN() with PARSE_OPT_NODASH works' '
|
||||
test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
|
||||
test-parse-options + + + + + + > output 2> output.err &&
|
||||
test ! -s output.err &&
|
||||
test_cmp expect output
|
||||
|
@ -8,10 +8,13 @@ test_expect_success 'setup helper scripts' '
|
||||
cat >dump <<-\EOF &&
|
||||
whoami=`echo $0 | sed s/.*git-credential-//`
|
||||
echo >&2 "$whoami: $*"
|
||||
while IFS== read key value; do
|
||||
OIFS=$IFS
|
||||
IFS==
|
||||
while read key value; do
|
||||
echo >&2 "$whoami: $key=$value"
|
||||
eval "$key=$value"
|
||||
done
|
||||
IFS=$OIFS
|
||||
EOF
|
||||
|
||||
write_script git-credential-useless <<-\EOF &&
|
||||
|
@ -27,12 +27,8 @@ test_expect_success 'loose objects borrowed from alternate are not missing' '
|
||||
git init &&
|
||||
echo ../../../.git/objects >.git/objects/info/alternates &&
|
||||
test_commit C fileC one &&
|
||||
git fsck >../out 2>&1
|
||||
git fsck --no-dangling >../actual 2>&1
|
||||
) &&
|
||||
{
|
||||
grep -v dangling out >actual ||
|
||||
:
|
||||
} &&
|
||||
test_cmp empty actual
|
||||
'
|
||||
|
||||
|
@ -653,4 +653,8 @@ test_expect_success 'refuse --edit-description on unborn branch for now' '
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success '--merged catches invalid object names' '
|
||||
test_must_fail git branch --merged 0000000000000000000000000000000000000000
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -160,14 +160,12 @@ rm -f B
|
||||
|
||||
test_expect_success 'fail when upstream arg is missing and not on branch' '
|
||||
git checkout topic &&
|
||||
test_must_fail git rebase >output.out &&
|
||||
grep "You are not currently on a branch" output.out
|
||||
test_must_fail git rebase
|
||||
'
|
||||
|
||||
test_expect_success 'fail when upstream arg is missing and not configured' '
|
||||
git checkout -b no-config topic &&
|
||||
test_must_fail git rebase >output.out &&
|
||||
grep "branch.no-config.merge" output.out
|
||||
test_must_fail git rebase
|
||||
'
|
||||
|
||||
test_expect_success 'default to @{upstream} when upstream arg is missing' '
|
||||
|
@ -59,6 +59,20 @@ test_expect_success 'advice from failed cherry-pick' "
|
||||
test_i18ncmp expected actual
|
||||
"
|
||||
|
||||
test_expect_success 'advice from failed cherry-pick --no-commit' "
|
||||
pristine_detach initial &&
|
||||
|
||||
picked=\$(git rev-parse --short picked) &&
|
||||
cat <<-EOF >expected &&
|
||||
error: could not apply \$picked... picked
|
||||
hint: after resolving the conflicts, mark the corrected paths
|
||||
hint: with 'git add <paths>' or 'git rm <paths>'
|
||||
EOF
|
||||
test_must_fail git cherry-pick --no-commit picked 2>actual &&
|
||||
|
||||
test_i18ncmp expected actual
|
||||
"
|
||||
|
||||
test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '
|
||||
pristine_detach initial &&
|
||||
test_must_fail git cherry-pick picked &&
|
||||
|
@ -9,85 +9,110 @@ test_description='Test diff of symlinks.
|
||||
. ./test-lib.sh
|
||||
. "$TEST_DIRECTORY"/diff-lib.sh
|
||||
|
||||
cat > expected << EOF
|
||||
diff --git a/frotz b/frotz
|
||||
new file mode 120000
|
||||
index 0000000..7c465af
|
||||
--- /dev/null
|
||||
+++ b/frotz
|
||||
@@ -0,0 +1 @@
|
||||
+xyzzy
|
||||
\ No newline at end of file
|
||||
EOF
|
||||
test_expect_success SYMLINKS 'diff new symlink and file' '
|
||||
cat >expected <<-\EOF &&
|
||||
diff --git a/frotz b/frotz
|
||||
new file mode 120000
|
||||
index 0000000..7c465af
|
||||
--- /dev/null
|
||||
+++ b/frotz
|
||||
@@ -0,0 +1 @@
|
||||
+xyzzy
|
||||
\ No newline at end of file
|
||||
diff --git a/nitfol b/nitfol
|
||||
new file mode 100644
|
||||
index 0000000..7c465af
|
||||
--- /dev/null
|
||||
+++ b/nitfol
|
||||
@@ -0,0 +1 @@
|
||||
+xyzzy
|
||||
EOF
|
||||
ln -s xyzzy frotz &&
|
||||
echo xyzzy >nitfol &&
|
||||
git update-index &&
|
||||
tree=$(git write-tree) &&
|
||||
git update-index --add frotz nitfol &&
|
||||
GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current &&
|
||||
compare_diff_patch expected current
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS \
|
||||
'diff new symlink' \
|
||||
'ln -s xyzzy frotz &&
|
||||
git update-index &&
|
||||
tree=$(git write-tree) &&
|
||||
git update-index --add frotz &&
|
||||
GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree > current &&
|
||||
compare_diff_patch current expected'
|
||||
test_expect_success SYMLINKS 'diff unchanged symlink and file' '
|
||||
tree=$(git write-tree) &&
|
||||
git update-index frotz nitfol &&
|
||||
test -z "$(git diff-index --name-only $tree)"
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS \
|
||||
'diff unchanged symlink' \
|
||||
'tree=$(git write-tree) &&
|
||||
git update-index frotz &&
|
||||
test -z "$(git diff-index --name-only $tree)"'
|
||||
test_expect_success SYMLINKS 'diff removed symlink and file' '
|
||||
cat >expected <<-\EOF &&
|
||||
diff --git a/frotz b/frotz
|
||||
deleted file mode 120000
|
||||
index 7c465af..0000000
|
||||
--- a/frotz
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-xyzzy
|
||||
\ No newline at end of file
|
||||
diff --git a/nitfol b/nitfol
|
||||
deleted file mode 100644
|
||||
index 7c465af..0000000
|
||||
--- a/nitfol
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-xyzzy
|
||||
EOF
|
||||
mv frotz frotz2 &&
|
||||
mv nitfol nitfol2 &&
|
||||
git diff-index -M -p $tree >current &&
|
||||
compare_diff_patch expected current
|
||||
'
|
||||
|
||||
cat > expected << EOF
|
||||
diff --git a/frotz b/frotz
|
||||
deleted file mode 120000
|
||||
index 7c465af..0000000
|
||||
--- a/frotz
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-xyzzy
|
||||
\ No newline at end of file
|
||||
EOF
|
||||
test_expect_success SYMLINKS 'diff identical, but newly created symlink and file' '
|
||||
>expected &&
|
||||
rm -f frotz nitfol &&
|
||||
echo xyzzy >nitfol &&
|
||||
test-chmtime +10 nitfol &&
|
||||
ln -s xyzzy frotz &&
|
||||
git diff-index -M -p $tree >current &&
|
||||
compare_diff_patch expected current &&
|
||||
|
||||
test_expect_success SYMLINKS \
|
||||
'diff removed symlink' \
|
||||
'mv frotz frotz2 &&
|
||||
git diff-index -M -p $tree > current &&
|
||||
compare_diff_patch current expected'
|
||||
>expected &&
|
||||
git diff-index -M -p -w $tree >current &&
|
||||
compare_diff_patch expected current
|
||||
'
|
||||
|
||||
cat > expected << EOF
|
||||
diff --git a/frotz b/frotz
|
||||
EOF
|
||||
test_expect_success SYMLINKS 'diff different symlink and file' '
|
||||
cat >expected <<-\EOF &&
|
||||
diff --git a/frotz b/frotz
|
||||
index 7c465af..df1db54 120000
|
||||
--- a/frotz
|
||||
+++ b/frotz
|
||||
@@ -1 +1 @@
|
||||
-xyzzy
|
||||
\ No newline at end of file
|
||||
+yxyyz
|
||||
\ No newline at end of file
|
||||
diff --git a/nitfol b/nitfol
|
||||
index 7c465af..df1db54 100644
|
||||
--- a/nitfol
|
||||
+++ b/nitfol
|
||||
@@ -1 +1 @@
|
||||
-xyzzy
|
||||
+yxyyz
|
||||
EOF
|
||||
rm -f frotz &&
|
||||
ln -s yxyyz frotz &&
|
||||
echo yxyyz >nitfol &&
|
||||
git diff-index -M -p $tree >current &&
|
||||
compare_diff_patch expected current
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS \
|
||||
'diff identical, but newly created symlink' \
|
||||
'ln -s xyzzy frotz &&
|
||||
git diff-index -M -p $tree > current &&
|
||||
compare_diff_patch current expected'
|
||||
|
||||
cat > expected << EOF
|
||||
diff --git a/frotz b/frotz
|
||||
index 7c465af..df1db54 120000
|
||||
--- a/frotz
|
||||
+++ b/frotz
|
||||
@@ -1 +1 @@
|
||||
-xyzzy
|
||||
\ No newline at end of file
|
||||
+yxyyz
|
||||
\ No newline at end of file
|
||||
EOF
|
||||
|
||||
test_expect_success SYMLINKS \
|
||||
'diff different symlink' \
|
||||
'rm frotz &&
|
||||
ln -s yxyyz frotz &&
|
||||
git diff-index -M -p $tree > current &&
|
||||
compare_diff_patch current expected'
|
||||
|
||||
test_expect_success SYMLINKS \
|
||||
'diff symlinks with non-existing targets' \
|
||||
'ln -s narf pinky &&
|
||||
ln -s take\ over brain &&
|
||||
test_must_fail git diff --no-index pinky brain > output 2> output.err &&
|
||||
grep narf output &&
|
||||
! grep error output.err'
|
||||
test_expect_success SYMLINKS 'diff symlinks with non-existing targets' '
|
||||
ln -s narf pinky &&
|
||||
ln -s take\ over brain &&
|
||||
test_must_fail git diff --no-index pinky brain >output 2>output.err &&
|
||||
grep narf output &&
|
||||
! test -s output.err
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'setup symlinks with attributes' '
|
||||
echo "*.bin diff=bin" >>.gitattributes &&
|
||||
@ -96,19 +121,19 @@ test_expect_success SYMLINKS 'setup symlinks with attributes' '
|
||||
git add -N file.bin link.bin
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
diff --git a/file.bin b/file.bin
|
||||
index e69de29..d95f3ad 100644
|
||||
Binary files a/file.bin and b/file.bin differ
|
||||
diff --git a/link.bin b/link.bin
|
||||
index e69de29..dce41ec 120000
|
||||
--- a/link.bin
|
||||
+++ b/link.bin
|
||||
@@ -0,0 +1 @@
|
||||
+file.bin
|
||||
\ No newline at end of file
|
||||
EOF
|
||||
test_expect_success SYMLINKS 'symlinks do not respect userdiff config by path' '
|
||||
cat >expect <<-\EOF &&
|
||||
diff --git a/file.bin b/file.bin
|
||||
index e69de29..d95f3ad 100644
|
||||
Binary files a/file.bin and b/file.bin differ
|
||||
diff --git a/link.bin b/link.bin
|
||||
index e69de29..dce41ec 120000
|
||||
--- a/link.bin
|
||||
+++ b/link.bin
|
||||
@@ -0,0 +1 @@
|
||||
+file.bin
|
||||
\ No newline at end of file
|
||||
EOF
|
||||
git config diff.bin.binary true &&
|
||||
git diff file.bin link.bin >actual &&
|
||||
test_cmp expect actual
|
||||
|
220
t/t4052-stat-output.sh
Executable file
220
t/t4052-stat-output.sh
Executable file
@ -0,0 +1,220 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2012 Zbigniew Jędrzejewski-Szmek
|
||||
#
|
||||
|
||||
test_description='test --stat output of various commands'
|
||||
|
||||
. ./test-lib.sh
|
||||
. "$TEST_DIRECTORY"/lib-terminal.sh
|
||||
|
||||
# 120 character name
|
||||
name=aaaaaaaaaa
|
||||
name=$name$name$name$name$name$name$name$name$name$name$name$name
|
||||
test_expect_success 'preparation' '
|
||||
>"$name" &&
|
||||
git add "$name" &&
|
||||
git commit -m message &&
|
||||
echo a >"$name" &&
|
||||
git commit -m message "$name"
|
||||
'
|
||||
|
||||
while read cmd args
|
||||
do
|
||||
cat >expect <<-'EOF'
|
||||
...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +
|
||||
EOF
|
||||
test_expect_success "$cmd: small change with long name gives more space to the name" '
|
||||
git $cmd $args >output &&
|
||||
grep " | " output >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<-'EOF'
|
||||
...aaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +
|
||||
EOF
|
||||
test_expect_success "$cmd --stat=width: a long name is given more room when the bar is short" '
|
||||
git $cmd $args --stat=40 >output &&
|
||||
grep " | " output >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success "$cmd --stat-width=width with long name" '
|
||||
git $cmd $args --stat-width=40 >output &&
|
||||
grep " | " output >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<-'EOF'
|
||||
...aaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +
|
||||
EOF
|
||||
test_expect_success "$cmd --stat=...,name-width with long name" '
|
||||
git $cmd $args --stat=60,30 >output &&
|
||||
grep " | " output >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success "$cmd --stat-name-width with long name" '
|
||||
git $cmd $args --stat-name-width=30 >output &&
|
||||
grep " | " output >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
done <<\EOF
|
||||
format-patch -1 --stdout
|
||||
diff HEAD^ HEAD --stat
|
||||
show --stat
|
||||
log -1 --stat
|
||||
EOF
|
||||
|
||||
|
||||
test_expect_success 'preparation for big change tests' '
|
||||
>abcd &&
|
||||
git add abcd &&
|
||||
git commit -m message &&
|
||||
i=0 &&
|
||||
while test $i -lt 1000
|
||||
do
|
||||
echo $i && i=$(($i + 1))
|
||||
done >abcd &&
|
||||
git commit -m message abcd
|
||||
'
|
||||
|
||||
cat >expect80 <<'EOF'
|
||||
abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
EOF
|
||||
|
||||
cat >expect200 <<'EOF'
|
||||
abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
EOF
|
||||
|
||||
while read verb expect cmd args
|
||||
do
|
||||
test_expect_success "$cmd $verb COLUMNS (big change)" '
|
||||
COLUMNS=200 git $cmd $args >output
|
||||
grep " | " output >actual &&
|
||||
test_cmp "$expect" actual
|
||||
'
|
||||
done <<\EOF
|
||||
ignores expect80 format-patch -1 --stdout
|
||||
respects expect200 diff HEAD^ HEAD --stat
|
||||
respects expect200 show --stat
|
||||
respects expect200 log -1 --stat
|
||||
EOF
|
||||
|
||||
cat >expect40 <<'EOF'
|
||||
abcd | 1000 ++++++++++++++++++++++++++
|
||||
EOF
|
||||
|
||||
while read verb expect cmd args
|
||||
do
|
||||
test_expect_success "$cmd $verb not enough COLUMNS (big change)" '
|
||||
COLUMNS=40 git $cmd $args >output
|
||||
grep " | " output >actual &&
|
||||
test_cmp "$expect" actual
|
||||
'
|
||||
|
||||
test_expect_success "$cmd $verb statGraphWidth config" '
|
||||
git -c diff.statGraphWidth=26 $cmd $args >output
|
||||
grep " | " output >actual &&
|
||||
test_cmp "$expect" actual
|
||||
'
|
||||
done <<\EOF
|
||||
ignores expect80 format-patch -1 --stdout
|
||||
respects expect40 diff HEAD^ HEAD --stat
|
||||
respects expect40 show --stat
|
||||
respects expect40 log -1 --stat
|
||||
EOF
|
||||
|
||||
|
||||
cat >expect <<'EOF'
|
||||
abcd | 1000 ++++++++++++++++++++++++++
|
||||
EOF
|
||||
while read cmd args
|
||||
do
|
||||
test_expect_success "$cmd --stat=width with big change" '
|
||||
git $cmd $args --stat=40 >output
|
||||
grep " | " output >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success "$cmd --stat-width=width with big change" '
|
||||
git $cmd $args --stat-width=40 >output
|
||||
grep " | " output >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success "$cmd --stat-graph--width with big change" '
|
||||
git $cmd $args --stat-graph-width=26 >output
|
||||
grep " | " output >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
done <<\EOF
|
||||
format-patch -1 --stdout
|
||||
diff HEAD^ HEAD --stat
|
||||
show --stat
|
||||
log -1 --stat
|
||||
EOF
|
||||
|
||||
test_expect_success 'preparation for long filename tests' '
|
||||
cp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
|
||||
git add aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
|
||||
git commit -m message
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++
|
||||
EOF
|
||||
while read cmd args
|
||||
do
|
||||
test_expect_success "$cmd --stat=width with big change is more balanced" '
|
||||
git $cmd $args --stat-width=60 >output &&
|
||||
grep " | " output >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
done <<\EOF
|
||||
format-patch -1 --stdout
|
||||
diff HEAD^ HEAD --stat
|
||||
show --stat
|
||||
log -1 --stat
|
||||
EOF
|
||||
|
||||
cat >expect80 <<'EOF'
|
||||
...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++
|
||||
EOF
|
||||
cat >expect200 <<'EOF'
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
EOF
|
||||
while read verb expect cmd args
|
||||
do
|
||||
test_expect_success "$cmd $verb COLUMNS (long filename)" '
|
||||
COLUMNS=200 git $cmd $args >output
|
||||
grep " | " output >actual &&
|
||||
test_cmp "$expect" actual
|
||||
'
|
||||
done <<\EOF
|
||||
ignores expect80 format-patch -1 --stdout
|
||||
respects expect200 diff HEAD^ HEAD --stat
|
||||
respects expect200 show --stat
|
||||
respects expect200 log -1 --stat
|
||||
EOF
|
||||
|
||||
cat >expect <<'EOF'
|
||||
abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
EOF
|
||||
test_expect_success 'merge --stat respects COLUMNS (big change)' '
|
||||
git checkout -b branch HEAD^^ &&
|
||||
COLUMNS=100 git merge --stat --no-ff master^ >output &&
|
||||
grep " | " output >actual
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++
|
||||
EOF
|
||||
test_expect_success 'merge --stat respects COLUMNS (long filename)' '
|
||||
COLUMNS=100 git merge --stat --no-ff master >output &&
|
||||
grep " | " output >actual
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
@ -123,6 +123,7 @@ test_expect_success setup '
|
||||
git commit -m "added another file" &&
|
||||
|
||||
git format-patch --stdout master >lorem-move.patch &&
|
||||
git format-patch --no-prefix --stdout master >lorem-zero.patch &&
|
||||
|
||||
git checkout -b rename &&
|
||||
git mv file renamed &&
|
||||
@ -286,6 +287,20 @@ test_expect_success 'am -3 falls back to 3-way merge' '
|
||||
git diff --exit-code lorem
|
||||
'
|
||||
|
||||
test_expect_success 'am -3 -p0 can read --no-prefix patch' '
|
||||
rm -fr .git/rebase-apply &&
|
||||
git reset --hard &&
|
||||
git checkout -b lorem3 master2 &&
|
||||
sed -n -e "3,\$p" msg >file &&
|
||||
head -n 9 msg >>file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
git commit -m "copied stuff" &&
|
||||
git am -3 -p0 lorem-zero.patch &&
|
||||
! test -d .git/rebase-apply &&
|
||||
git diff --exit-code lorem
|
||||
'
|
||||
|
||||
test_expect_success 'am can rename a file' '
|
||||
grep "^rename from" rename.patch &&
|
||||
rm -fr .git/rebase-apply &&
|
||||
|
119
t/t4209-log-pickaxe.sh
Executable file
119
t/t4209-log-pickaxe.sh
Executable file
@ -0,0 +1,119 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='log --grep/--author/--regexp-ignore-case/-S/-G'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success setup '
|
||||
>file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
git commit -m initial &&
|
||||
|
||||
echo Picked >file &&
|
||||
test_tick &&
|
||||
git commit -a --author="Another Person <another@example.com>" -m second
|
||||
'
|
||||
|
||||
test_expect_success 'log --grep' '
|
||||
git log --grep=initial --format=%H >actual &&
|
||||
git rev-parse --verify HEAD^ >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log --grep --regexp-ignore-case' '
|
||||
git log --regexp-ignore-case --grep=InItial --format=%H >actual &&
|
||||
git rev-parse --verify HEAD^ >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log --grep -i' '
|
||||
git log -i --grep=InItial --format=%H >actual &&
|
||||
git rev-parse --verify HEAD^ >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log --author --regexp-ignore-case' '
|
||||
git log --regexp-ignore-case --author=person --format=%H >actual &&
|
||||
git rev-parse --verify HEAD >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log --author -i' '
|
||||
git log -i --author=person --format=%H >actual &&
|
||||
git rev-parse --verify HEAD >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -G (nomatch)' '
|
||||
git log -Gpicked --format=%H >actual &&
|
||||
>expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -G (match)' '
|
||||
git log -GPicked --format=%H >actual &&
|
||||
git rev-parse --verify HEAD >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -G --regexp-ignore-case (nomatch)' '
|
||||
git log --regexp-ignore-case -Gpickle --format=%H >actual &&
|
||||
>expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -G -i (nomatch)' '
|
||||
git log -i -Gpickle --format=%H >actual &&
|
||||
>expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -G --regexp-ignore-case (match)' '
|
||||
git log --regexp-ignore-case -Gpicked --format=%H >actual &&
|
||||
git rev-parse --verify HEAD >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -G -i (match)' '
|
||||
git log -i -Gpicked --format=%H >actual &&
|
||||
git rev-parse --verify HEAD >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -S (nomatch)' '
|
||||
git log -Spicked --format=%H >actual &&
|
||||
>expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -S (match)' '
|
||||
git log -SPicked --format=%H >actual &&
|
||||
git rev-parse --verify HEAD >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -S --regexp-ignore-case (match)' '
|
||||
git log --regexp-ignore-case -Spicked --format=%H >actual &&
|
||||
git rev-parse --verify HEAD >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -S -i (match)' '
|
||||
git log -i -Spicked --format=%H >actual &&
|
||||
git rev-parse --verify HEAD >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -S --regexp-ignore-case (nomatch)' '
|
||||
git log --regexp-ignore-case -Spickle --format=%H >actual &&
|
||||
>expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log -S -i (nomatch)' '
|
||||
git log -i -Spickle --format=%H >actual &&
|
||||
>expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
@ -14,6 +14,14 @@ test_bundle_object_count () {
|
||||
test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l)
|
||||
}
|
||||
|
||||
convert_bundle_to_pack () {
|
||||
while read x && test -n "$x"
|
||||
do
|
||||
:;
|
||||
done
|
||||
cat
|
||||
}
|
||||
|
||||
test_expect_success setup '
|
||||
echo >file original &&
|
||||
git add file &&
|
||||
@ -206,13 +214,7 @@ test_expect_success 'unbundle 1' '
|
||||
|
||||
test_expect_success 'bundle 1 has only 3 files ' '
|
||||
cd "$D" &&
|
||||
(
|
||||
while read x && test -n "$x"
|
||||
do
|
||||
:;
|
||||
done
|
||||
cat
|
||||
) <bundle1 >bundle.pack &&
|
||||
convert_bundle_to_pack <bundle1 >bundle.pack &&
|
||||
git index-pack bundle.pack &&
|
||||
test_bundle_object_count bundle.pack 3
|
||||
'
|
||||
@ -229,13 +231,7 @@ test_expect_success 'bundle does not prerequisite objects' '
|
||||
git add file2 &&
|
||||
git commit -m add.file2 file2 &&
|
||||
git bundle create bundle3 -1 HEAD &&
|
||||
(
|
||||
while read x && test -n "$x"
|
||||
do
|
||||
:;
|
||||
done
|
||||
cat
|
||||
) <bundle3 >bundle.pack &&
|
||||
convert_bundle_to_pack <bundle3 >bundle.pack &&
|
||||
git index-pack bundle.pack &&
|
||||
test_bundle_object_count bundle.pack 3
|
||||
'
|
||||
@ -433,14 +429,31 @@ test_expect_success 'fetch --dry-run' '
|
||||
'
|
||||
|
||||
test_expect_success "should be able to fetch with duplicate refspecs" '
|
||||
mkdir dups &&
|
||||
cd dups &&
|
||||
git init &&
|
||||
git config branch.master.remote three &&
|
||||
git config remote.three.url ../three/.git &&
|
||||
git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
|
||||
git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
|
||||
git fetch three
|
||||
mkdir dups &&
|
||||
(
|
||||
cd dups &&
|
||||
git init &&
|
||||
git config branch.master.remote three &&
|
||||
git config remote.three.url ../three/.git &&
|
||||
git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
|
||||
git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
|
||||
git fetch three
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'all boundary commits are excluded' '
|
||||
test_commit base &&
|
||||
test_commit oneside &&
|
||||
git checkout HEAD^ &&
|
||||
test_commit otherside &&
|
||||
git checkout master &&
|
||||
test_tick &&
|
||||
git merge otherside &&
|
||||
ad=$(git log --no-walk --format=%ad HEAD) &&
|
||||
git bundle create twoside-boundary.bdl master --since="$ad" &&
|
||||
convert_bundle_to_pack <twoside-boundary.bdl >twoside-boundary.pack &&
|
||||
pack=$(git index-pack --fix-thin --stdin <twoside-boundary.pack) &&
|
||||
test_bundle_object_count .git/objects/pack/pack-${pack##pack }.pack 3
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -5,7 +5,6 @@ test_description='git ls-remote'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success setup '
|
||||
|
||||
>file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
@ -18,45 +17,33 @@ test_expect_success setup '
|
||||
) >expected.all &&
|
||||
|
||||
git remote add self "$(pwd)/.git"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'ls-remote --tags .git' '
|
||||
|
||||
git ls-remote --tags .git >actual &&
|
||||
test_cmp expected.tag actual
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'ls-remote .git' '
|
||||
|
||||
git ls-remote .git >actual &&
|
||||
test_cmp expected.all actual
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'ls-remote --tags self' '
|
||||
|
||||
git ls-remote --tags self >actual &&
|
||||
test_cmp expected.tag actual
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'ls-remote self' '
|
||||
|
||||
git ls-remote self >actual &&
|
||||
test_cmp expected.all actual
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'dies when no remote specified and no default remotes found' '
|
||||
|
||||
test_must_fail git ls-remote
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'use "origin" when no remote specified' '
|
||||
|
||||
URL="$(pwd)/.git" &&
|
||||
echo "From $URL" >exp_err &&
|
||||
|
||||
@ -65,18 +52,14 @@ test_expect_success 'use "origin" when no remote specified' '
|
||||
|
||||
test_cmp exp_err actual_err &&
|
||||
test_cmp expected.all actual
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'suppress "From <url>" with -q' '
|
||||
|
||||
git ls-remote -q 2>actual_err &&
|
||||
test_must_fail test_cmp exp_err actual_err
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'use branch.<name>.remote if possible' '
|
||||
|
||||
#
|
||||
# Test that we are indeed using branch.<name>.remote, not "origin", even
|
||||
# though the "origin" remote has been set.
|
||||
@ -99,14 +82,13 @@ test_expect_success 'use branch.<name>.remote if possible' '
|
||||
git ls-remote 2>actual_err >actual &&
|
||||
test_cmp exp_err actual_err &&
|
||||
test_cmp exp actual
|
||||
|
||||
'
|
||||
|
||||
cat >exp <<EOF
|
||||
fatal: 'refs*master' does not appear to be a git repository
|
||||
fatal: The remote end hung up unexpectedly
|
||||
EOF
|
||||
test_expect_success 'confuses pattern as remote when no remote specified' '
|
||||
cat >exp <<-\EOF &&
|
||||
fatal: '\''refs*master'\'' does not appear to be a git repository
|
||||
fatal: The remote end hung up unexpectedly
|
||||
EOF
|
||||
#
|
||||
# Do not expect "git ls-remote <pattern>" to work; ls-remote, correctly,
|
||||
# confuses <pattern> for <remote>. Although ugly, this behaviour is akin
|
||||
@ -120,7 +102,6 @@ test_expect_success 'confuses pattern as remote when no remote specified' '
|
||||
# role as a pattern.
|
||||
test_must_fail git ls-remote refs*master >actual 2>&1 &&
|
||||
test_cmp exp actual
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'die with non-2 for wrong repository even with --exit-code' '
|
||||
|
@ -54,8 +54,8 @@ test_expect_success 'ridiculously long subject in boundary' '
|
||||
git bundle list-heads long-subject-bundle.bdl >heads &&
|
||||
test -s heads &&
|
||||
git fetch long-subject-bundle.bdl &&
|
||||
sed -n "/^-/{p;q}" long-subject-bundle.bdl >boundary &&
|
||||
grep "^-$_x40 " boundary
|
||||
sed -n "/^-/{p;q;}" long-subject-bundle.bdl >boundary &&
|
||||
grep "^-[0-9a-f]\\{40\\} " boundary
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -134,4 +134,14 @@ our $maxload = undef;
|
||||
EOF
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# invalid arguments
|
||||
|
||||
test_expect_success 'invalid arguments: invalid regexp (in project search)' '
|
||||
gitweb_run "a=project_list;s=*\.git;sr=1" &&
|
||||
grep "Status: 400" gitweb.headers &&
|
||||
grep "400 - Invalid.*regexp" gitweb.body
|
||||
'
|
||||
test_debug 'cat gitweb.headers'
|
||||
|
||||
test_done
|
||||
|
@ -42,10 +42,11 @@ TZ=UTC
|
||||
TERM=dumb
|
||||
export LANG LC_ALL PAGER TERM TZ
|
||||
EDITOR=:
|
||||
unset VISUAL
|
||||
unset EMAIL
|
||||
unset LANGUAGE
|
||||
unset $(perl -e '
|
||||
# A call to "unset" with no arguments causes at least Solaris 10
|
||||
# /usr/xpg4/bin/sh and /bin/ksh to bail out. So keep the unsets
|
||||
# deriving from the command substitution clustered with the other
|
||||
# ones.
|
||||
unset VISUAL EMAIL LANGUAGE $(perl -e '
|
||||
my @env = keys %ENV;
|
||||
my $ok = join("|", qw(
|
||||
TRACE
|
||||
|
@ -37,7 +37,11 @@ int main(int argc, const char **argv)
|
||||
NULL
|
||||
};
|
||||
struct option options[] = {
|
||||
OPT_BOOLEAN('b', "boolean", &boolean, "get a boolean"),
|
||||
OPT_BOOL(0, "yes", &boolean, "get a boolean"),
|
||||
OPT_BOOL('D', "no-doubt", &boolean, "begins with 'no-'"),
|
||||
{ OPTION_SET_INT, 'B', "no-fear", &boolean, NULL,
|
||||
"be brave", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
|
||||
OPT_COUNTUP('b', "boolean", &boolean, "increment by one"),
|
||||
OPT_BIT('4', "or4", &boolean,
|
||||
"bitwise-or boolean with ...0100", 4),
|
||||
OPT_NEGBIT(0, "neg-or4", &boolean, "same as --no-or4", 4),
|
||||
@ -62,11 +66,11 @@ int main(int argc, const char **argv)
|
||||
OPT_ARGUMENT("quux", "means --quux"),
|
||||
OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
|
||||
number_callback),
|
||||
{ OPTION_BOOLEAN, '+', NULL, &boolean, NULL, "same as -b",
|
||||
{ OPTION_COUNTUP, '+', NULL, &boolean, NULL, "same as -b",
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH },
|
||||
{ OPTION_BOOLEAN, 0, "ambiguous", &ambiguous, NULL,
|
||||
{ OPTION_COUNTUP, 0, "ambiguous", &ambiguous, NULL,
|
||||
"positive ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG },
|
||||
{ OPTION_BOOLEAN, 0, "no-ambiguous", &ambiguous, NULL,
|
||||
{ OPTION_COUNTUP, 0, "no-ambiguous", &ambiguous, NULL,
|
||||
"negative ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG },
|
||||
OPT_GROUP("Standard options"),
|
||||
OPT__ABBREV(&abbrev),
|
||||
|
Loading…
Reference in New Issue
Block a user