Merge v1.7.10-rc0 for git l10n update

This commit is contained in:
Jiang Xin 2012-03-08 10:17:21 +08:00
commit 13ef396635
72 changed files with 2027 additions and 676 deletions

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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>`.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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].

View file

@ -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:

View file

@ -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::

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
DEF_VER=v1.7.9.GIT
DEF_VER=v1.7.10-rc0
LF='
'

View file

@ -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;

View file

@ -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, "");

View file

@ -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);

View file

@ -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()
};

View file

@ -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"),

View file

@ -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,

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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(),
};

View file

@ -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);

View file

@ -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);

View file

@ -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
View 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
View 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

View file

@ -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
View file

@ -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
View file

@ -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
View file

@ -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;

View file

@ -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(&regex, o->pickaxe, REG_EXTENDED | REG_NEWLINE);
if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))
cflags |= REG_ICASE;
err = regcomp(&regex, o->pickaxe, cflags);
if (err) {
char errbuf[1024];
regerror(err, &regex, errbuf, 1024);
@ -237,7 +241,8 @@ static void diffcore_pickaxe_count(struct diff_options *o)
}
regexp = &regex;
} else {
kws = kwsalloc(NULL);
kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)
? tolower_trans_tbl : NULL);
kwsincr(kws, needle, len);
kwsprep(kws);
}

View file

@ -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;

View file

@ -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"

View file

@ -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

View file

@ -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
}

View file

@ -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."

View file

@ -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"

View file

@ -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
View file

@ -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
View file

@ -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
View 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
}

View file

@ -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 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
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 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
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 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
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");

View file

@ -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
View file

@ -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
View 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>

View file

@ -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")) {

View file

@ -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)

View file

@ -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
View 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

View file

@ -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 &&

View file

@ -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

View file

@ -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

View file

@ -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 &&

View file

@ -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
'

View file

@ -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

View file

@ -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' '

View file

@ -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 &&

View file

@ -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
View 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

View file

@ -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
View 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

View file

@ -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

View file

@ -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' '

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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),