summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes-1.6.5.1.txt20
-rw-r--r--Documentation/RelNotes-1.6.5.txt20
-rw-r--r--Documentation/RelNotes-1.6.6.txt60
-rw-r--r--Documentation/config.txt8
-rw-r--r--Documentation/git-branch.txt26
-rw-r--r--Documentation/git-check-ref-format.txt9
-rw-r--r--Documentation/git-clone.txt5
-rw-r--r--Documentation/git-fmt-merge-msg.txt4
-rw-r--r--Documentation/git-merge.txt11
-rw-r--r--Documentation/git-push.txt5
-rw-r--r--Documentation/git-replace.txt21
-rw-r--r--Documentation/git-stash.txt3
-rw-r--r--Documentation/git.txt12
-rw-r--r--Documentation/glossary-content.txt6
-rw-r--r--Documentation/pt_BR/gittutorial.txt22
-rw-r--r--Documentation/technical/racy-git.txt10
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile25
-rw-r--r--README2
l---------RelNotes2
-rw-r--r--archive.c7
-rw-r--r--builtin-apply.c61
-rw-r--r--builtin-clone.c3
-rw-r--r--builtin-describe.c13
-rw-r--r--builtin-fetch.c107
-rw-r--r--builtin-grep.c2
-rw-r--r--builtin-ls-files.c15
-rw-r--r--builtin-push.c4
-rw-r--r--builtin-show-branch.c14
-rw-r--r--cache.h4
-rw-r--r--command-list.txt1
-rw-r--r--commit.h2
-rw-r--r--compat/vcbuild/scripts/clink.pl2
-rw-r--r--compat/vcbuild/scripts/lib.pl2
-rwxr-xr-xcontrib/completion/git-completion.bash30
-rw-r--r--contrib/emacs/git-blame.el156
-rwxr-xr-xcontrib/fast-import/import-tars.perl2
-rw-r--r--diff.c409
-rw-r--r--fast-import.c9
-rwxr-xr-xgit-add--interactive.perl2
-rwxr-xr-xgit-am.sh2
-rw-r--r--git-compat-util.h10
-rwxr-xr-xgit-instaweb.sh16
-rwxr-xr-xgit-pull.sh25
-rwxr-xr-xgit-send-email.perl8
-rwxr-xr-xgit-svn.perl30
-rw-r--r--git.c4
-rw-r--r--gitweb/gitweb.css6
-rwxr-xr-xgitweb/gitweb.perl75
-rw-r--r--index-pack.c4
-rw-r--r--log-tree.c5
-rw-r--r--pretty.c2
-rw-r--r--progress.c8
-rw-r--r--remote-curl.c2
-rw-r--r--revision.c2
-rw-r--r--revision.h3
-rw-r--r--sha1_file.c4
-rwxr-xr-xt/t3003-ls-files-exclude.sh32
-rwxr-xr-xt/t3202-show-branch-octopus.sh8
-rwxr-xr-xt/t3701-add-interactive.sh14
-rw-r--r--t/t4013/diff.log_--decorate=full_--all2
-rw-r--r--t/t4013/diff.log_--decorate_--all2
-rwxr-xr-xt/t4015-diff-whitespace.sh11
-rwxr-xr-xt/t4019-diff-wserror.sh11
-rwxr-xr-xt/t4124-apply-ws-rule.sh91
-rwxr-xr-xt/t5000-tar-tree.sh12
-rwxr-xr-xt/t5303-pack-corruption-resilience.sh9
-rwxr-xr-xt/t6050-replace.sh7
-rwxr-xr-xt/t7002-grep.sh66
-rwxr-xr-xt/t9001-send-email.sh94
-rw-r--r--usage.c6
-rw-r--r--ws.c19
72 files changed, 1259 insertions, 449 deletions
diff --git a/Documentation/RelNotes-1.6.5.1.txt b/Documentation/RelNotes-1.6.5.1.txt
new file mode 100644
index 0000000000..309ba181b2
--- /dev/null
+++ b/Documentation/RelNotes-1.6.5.1.txt
@@ -0,0 +1,20 @@
+GIT v1.6.5.1 Release Notes
+==========================
+
+Fixes since v1.6.5
+------------------
+
+ * An corrupt pack could make codepath to read objects into an
+ infinite loop.
+
+ * Download throughput display was always shown in KiB/s but on fast links
+ it is more appropriate to show it in MiB/s.
+
+ * "git grep -f filename" used uninitialized variable and segfaulted.
+
+ * "git clone -b branch" gave a wrong commit object name to post-checkout
+ hook.
+
+ * "git pull" over http did not work on msys.
+
+Other minor documentation updates are included.
diff --git a/Documentation/RelNotes-1.6.5.txt b/Documentation/RelNotes-1.6.5.txt
index d260b03723..ee141c19ad 100644
--- a/Documentation/RelNotes-1.6.5.txt
+++ b/Documentation/RelNotes-1.6.5.txt
@@ -53,6 +53,10 @@ Updates since v1.6.4
* Unnecessary inefficiency in deepening of a shallow repository has
been removed.
+ * "git clone" does not grab objects that it does not need (i.e.
+ referenced only from refs outside refs/heads and refs/tags
+ hierarchy) anymore.
+
* The "git" main binary used to link with libcurl, which then dragged
in a large number of external libraries. When using basic plumbing
commands in scripts, this unnecessarily slowed things down. We now
@@ -154,18 +158,12 @@ Updates since v1.6.4
* With GIT_TEST_OPTS="--root=/p/a/t/h", tests can be run outside the
source directory; using tmpfs may give faster turnaround.
+ * With NO_PERL_MAKEMAKER set, DESTDIR= is now honoured, so you can
+ build for one location, and install into another location to tar it
+ up.
Fixes since v1.6.4
------------------
-# All of the fixes in v1.6.4.X maintenance series are included in this
-# release, unless otherwise noted.
-
-# Here are fixes that this release has, but have not been backported to
-# v1.6.4.X series.
-
---
-exec >/var/tmp/1
-O=v1.6.5-rc1-44-ga16753d
-echo O=$(git describe master)
-git shortlog --no-merges $O..master --not maint
+All of the fixes in v1.6.4.X maintenance series are included in this
+release, unless otherwise noted.
diff --git a/Documentation/RelNotes-1.6.6.txt b/Documentation/RelNotes-1.6.6.txt
new file mode 100644
index 0000000000..5f1fecb5ec
--- /dev/null
+++ b/Documentation/RelNotes-1.6.6.txt
@@ -0,0 +1,60 @@
+GIT v1.6.6 Release Notes
+========================
+
+In git 1.7.0, which is planned to be the release after 1.6.6, "git
+push" into a branch that is currently checked out will be refused by
+default.
+
+You can choose what should happen upon such a push by setting the
+configuration variable receive.denyCurrentBranch in the receiving
+repository.
+
+Also, "git push $there :$killed" to delete the branch $killed in a remote
+repository $there, when $killed branch is the current branch pointed at by
+its HEAD, will be refused by default.
+
+You can choose what should happen upon such a push by setting the
+configuration variable receive.denyDeleteCurrent in the receiving
+repository.
+
+To ease the transition plan, the receiving repository of such a
+push running this release will issue a big warning when the
+configuration variable is missing. Please refer to:
+
+ http://git.or.cz/gitwiki/GitFaq#non-bare
+ http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007
+
+for more details on the reason why this change is needed and the
+transition plan.
+
+Updates since v1.6.5
+--------------------
+
+(subsystems)
+
+(portability)
+
+(performance)
+
+(usability, bells and whistles)
+
+ * "git log --decorate" shows the location of HEAD as well.
+
+(developers)
+
+Fixes since v1.6.5
+------------------
+
+All of the fixes in v1.6.5.X maintenance series are included in this
+release, unless otherwise noted.
+
+ * "git apply" and "git diff" (including patch output from "git log -p")
+ now flags trailing blank lines as whitespace errors correctly (only
+ "apply --whitespace=fix" stripped them but "apply --whitespace=warn"
+ did not even warn).
+
+ * Two whitespace error classes, 'blank-at-eof' and 'blank-at-eol', have
+ been introduced (settable by core.whitespace configuration variable and
+ whitespace attribute). The 'trailing-space' whitespace error class has
+ become a short-hand to cover both of these and there is no behaviour
+ change for existing set-ups.
diff --git a/Documentation/config.txt b/Documentation/config.txt
index be0b8cacaa..5a8f57cbf7 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -416,13 +416,17 @@ core.whitespace::
consider them as errors. You can prefix `-` to disable
any of them (e.g. `-trailing-space`):
+
-* `trailing-space` treats trailing whitespaces at the end of the line
+* `blank-at-eol` treats trailing whitespaces at the end of the line
as an error (enabled by default).
* `space-before-tab` treats a space character that appears immediately
before a tab character in the initial indent part of the line as an
error (enabled by default).
* `indent-with-non-tab` treats a line that is indented with 8 or more
space characters as an error (not enabled by default).
+* `blank-at-eof` treats blank lines added at the end of file as an error
+ (enabled by default).
+* `trailing-space` is a short-hand to cover both `blank-at-eol` and
+ `blank-at-eof`.
* `cr-at-eol` treats a carriage-return at the end of line as
part of the line terminator, i.e. with it, `trailing-space`
does not trigger if the character before such a carriage-return
@@ -539,7 +543,7 @@ branch.<name>.merge::
branch.<name>.mergeoptions::
Sets default options for merging into branch <name>. The syntax and
- supported options are equal to that of linkgit:git-merge[1], but
+ supported options are the same as those of linkgit:git-merge[1], but
option values containing whitespace characters are currently not
supported.
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index aad71dc59a..0e836809c2 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -30,10 +30,8 @@ commit) will be listed. With `--no-merged` only branches not merged into
the named commit will be listed. If the <commit> argument is missing it
defaults to 'HEAD' (i.e. the tip of the current branch).
-In the command's second form, a new branch named <branchname> will be created.
-It will start out with a head equal to the one given as <start-point>.
-If no <start-point> is given, the branch will be created with a head
-equal to that of the currently checked out branch.
+The command's second form creates a new branch head named <branchname>
+which points to the current 'HEAD', or <start-point> if given.
Note that this will create the new branch, but it will not switch the
working tree to it; use "git checkout <newbranch>" to switch to the
@@ -134,11 +132,13 @@ start-point is either a local or remote branch.
--contains <commit>::
Only list branches which contain the specified commit.
---merged::
- Only list branches which are fully contained by HEAD.
+--merged [<commit>]::
+ Only list branches whose tips are reachable from the
+ specified commit (HEAD if not specified).
---no-merged::
- Do not list branches which are fully contained by HEAD.
+--no-merged [<commit>]::
+ Only list branches whose tips are not reachable from the
+ specified commit (HEAD if not specified).
<branchname>::
The name of the branch to create or delete.
@@ -147,9 +147,9 @@ start-point is either a local or remote branch.
may restrict the characters allowed in a branch name.
<start-point>::
- The new branch will be created with a HEAD equal to this. It may
- be given as a branch name, a commit-id, or a tag. If this option
- is omitted, the current branch is assumed.
+ The new branch head will point to this commit. It may be
+ given as a branch name, a commit-id, or a tag. If this
+ option is omitted, the current HEAD will be used instead.
<oldbranch>::
The name of an existing branch to rename.
@@ -214,7 +214,9 @@ SEE ALSO
--------
linkgit:git-check-ref-format[1],
linkgit:git-fetch[1],
-linkgit:git-remote[1].
+linkgit:git-remote[1],
+link:user-manual.html#what-is-a-branch[``Understanding history: What is
+a branch?''] in the Git User's Manual.
Author
------
diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt
index 0b7982ea76..e9b3b40af4 100644
--- a/Documentation/git-check-ref-format.txt
+++ b/Documentation/git-check-ref-format.txt
@@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'git check-ref-format' <refname>
-'git check-ref-format' [--branch] <branchname-shorthand>
+'git check-ref-format' --branch <branchname-shorthand>
DESCRIPTION
-----------
@@ -63,8 +63,11 @@ reference name expressions (see linkgit:git-rev-parse[1]):
. at-open-brace `@{` is used as a notation to access a reflog entry.
-With the `--branch` option, it expands a branch name shorthand and
-prints the name of the branch the shorthand refers to.
+With the `--branch` option, it expands the ``previous branch syntax''
+`@{-n}`. For example, `@{-1}` is a way to refer the last branch you
+were on. This option should be used by porcelains to accept this
+syntax anywhere a branch name is expected, so they can act as if you
+typed the branch name.
EXAMPLE
-------
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index aacf4fd327..5ebcba1c7c 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -19,8 +19,9 @@ DESCRIPTION
Clones a repository into a newly created directory, creates
remote-tracking branches for each branch in the cloned repository
-(visible using `git branch -r`), and creates and checks out an initial
-branch equal to the cloned repository's currently active branch.
+(visible using `git branch -r`), and creates and checks out an
+initial branch that is forked from the cloned repository's
+currently active branch.
After the clone, a plain `git fetch` without arguments will update
all the remote-tracking branches, and a `git pull` without
diff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.txt
index 1c24796d66..a586950b48 100644
--- a/Documentation/git-fmt-merge-msg.txt
+++ b/Documentation/git-fmt-merge-msg.txt
@@ -18,8 +18,8 @@ Takes the list of merged objects on stdin and produces a suitable
commit message to be used for the merge commit, usually to be
passed as the '<merge-message>' argument of 'git-merge'.
-This script is intended mostly for internal use by scripts
-automatically invoking 'git-merge'.
+This command is intended mostly for internal use by scripts
+automatically invoking 'git merge'.
OPTIONS
-------
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index af68d694a0..d05f324462 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -28,9 +28,10 @@ OPTIONS
include::merge-options.txt[]
-m <msg>::
- The commit message to be used for the merge commit (in case
- it is created). The 'git-fmt-merge-msg' script can be used
- to give a good default for automated 'git-merge' invocations.
+ Set the commit message to be used for the merge commit (in
+ case one is created). The 'git fmt-merge-msg' command can be
+ used to give a good default for automated 'git merge'
+ invocations.
<remote>...::
Other branch heads to merge into our branch. You need at
@@ -49,8 +50,8 @@ include::merge-config.txt[]
branch.<name>.mergeoptions::
Sets default options for merging into branch <name>. The syntax and
- supported options are equal to that of 'git-merge', but option values
- containing whitespace characters are currently not supported.
+ supported options are the same as those of 'git merge', but option
+ values containing whitespace characters are currently not supported.
HOW MERGE WORKS
---------------
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index ba6a8a2fb2..37c88953d1 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -138,6 +138,11 @@ useful if you write an alias or script around 'git-push'.
--verbose::
Run verbosely.
+-q::
+--quiet::
+ Suppress all output, including the listing of updated refs,
+ unless an error occurs.
+
include::urls-remotes.txt[]
OUTPUT
diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt
index 915cb77b29..8adc1ef55c 100644
--- a/Documentation/git-replace.txt
+++ b/Documentation/git-replace.txt
@@ -23,6 +23,26 @@ replacement object.
Unless `-f` is given, the replace reference must not yet exist in
`.git/refs/replace/` directory.
+Replace references will be used by default by all git commands except
+those doing reachability traversal (prune, pack transfer and fsck).
+
+It is possible to disable use of replacement refs for any command
+using the --no-replace-objects option just after "git".
+
+For example if commit "foo" has been replaced by commit "bar":
+
+------------------------------------------------
+$ git --no-replace-object cat-file commit foo
+------------------------------------------------
+
+show information about commit "foo", while:
+
+------------------------------------------------
+$ git cat-file commit foo
+------------------------------------------------
+
+show information about commit "bar".
+
OPTIONS
-------
-f::
@@ -54,6 +74,7 @@ SEE ALSO
--------
linkgit:git-tag[1]
linkgit:git-branch[1]
+linkgit:git[1]
Author
------
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 3f14b727b8..fafe728f89 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -78,7 +78,8 @@ stash@{1}: On master: 9cc0589... Add git-stash
----------------------------------------------------------------
+
The command takes options applicable to the 'git-log'
-command to control what is shown and how. See linkgit:git-log[1].
+command to control what is shown and how. If no options are set, the
+default is `-n 10`. See linkgit:git-log[1].
show [<stash>]::
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 20b573e37c..df46a34371 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]
- [-p|--paginate|--no-pager]
+ [-p|--paginate|--no-pager] [--no-replace-objects]
[--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]
[--help] COMMAND [ARGS]
@@ -43,6 +43,12 @@ unreleased) version of git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
+* link:v1.6.5/git.html[documentation for release 1.6.5]
+
+* release notes for
+ link:RelNotes-1.6.5.1.txt[1.6.5.1],
+ link:RelNotes-1.6.5.txt[1.6.5].
+
* link:v1.6.4.4/git.html[documentation for release 1.6.4.4]
* release notes for
@@ -232,6 +238,10 @@ help ...`.
environment is not set, it is set to the current working
directory.
+--no-replace-objects::
+ Do not use replacement refs to replace git objects. See
+ linkgit:git-replace[1] for more information.
+
FURTHER DOCUMENTATION
---------------------
diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index 572374f7a6..43d84d15e9 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -456,6 +456,6 @@ This commit is referred to as a "merge commit", or sometimes just a
of 'A' is 'origin/B' sometimes we say "'A' is tracking 'origin/B'".
[[def_working_tree]]working tree::
- The tree of actual checked out files. The working tree is
- normally equal to the <<def_HEAD,HEAD>> plus any local changes
- that you have made but not yet committed.
+ The tree of actual checked out files. The working tree normally
+ contains the contents of the <<def_HEAD,HEAD>> commit's tree,
+ plus any local changes that you have made but not yet committed.
diff --git a/Documentation/pt_BR/gittutorial.txt b/Documentation/pt_BR/gittutorial.txt
index 81e7ad7df4..beba065252 100644
--- a/Documentation/pt_BR/gittutorial.txt
+++ b/Documentation/pt_BR/gittutorial.txt
@@ -1,15 +1,15 @@
gittutorial(7)
==============
-NAME
+NOME
----
gittutorial - Um tutorial de introdução ao git (para versão 1.5.1 ou mais nova)
-SYNOPSIS
+SINOPSE
--------
git *
-DESCRIPTION
+DESCRIÇÃO
-----------
Este tutorial explica como importar um novo projeto para o git,
@@ -64,11 +64,11 @@ Git irá responder
Initialized empty Git repository in .git/
------------------------------------------------
-Você agora iniciou seu diretório de trabalho--você deve ter notado um
-novo diretório criado, com o nome de ".git".
+Agora que você iniciou seu diretório de trabalho, você deve ter notado que um
+novo diretório foi criado com o nome de ".git".
A seguir, diga ao git para gravar um instantâneo do conteúdo de todos os
-arquivos sob o diretório corrente (note o '.'), com 'git-add':
+arquivos sob o diretório atual (note o '.'), com 'git-add':
------------------------------------------------
$ git add .
@@ -126,8 +126,8 @@ mudanças com:
$ git commit
------------------------------------------------
-Isto irá novamente te pedir por uma mensagem descrevendo a mudança, e,
-então, gravar a nova versão do projeto.
+Ao executar esse comando, ele irá te pedir uma mensagem descrevendo a mudança,
+e, então, irá gravar a nova versão do projeto.
Alternativamente, ao invés de executar 'git-add' antes, você pode usar
@@ -143,7 +143,7 @@ idéia começar a mensagem com uma simples e curta (menos de 50
caracteres) linha sumarizando a mudança, seguida de uma linha em branco
e, então, uma descrição mais detalhada. Ferramentas que transformam
commits em email, por exemplo, usam a primeira linha no campo de
-cabeçalho Subject: e o resto no corpo.
+cabeçalho "Subject:" e o resto no corpo.
Git rastreia conteúdo, não arquivos
----------------------------
@@ -155,7 +155,7 @@ usado tanto para arquivos novos e arquivos recentemente modificados, e
em ambos os casos, ele tira o instantâneo dos arquivos dados e armazena
o conteúdo no índice, pronto para inclusão do próximo commit.
-Visualizando história do projeto
+Visualizando a história do projeto
-----------------------
Em qualquer ponto você pode visualizar a história das suas mudanças
@@ -165,7 +165,7 @@ usando
$ git log
------------------------------------------------
-Se você também quer ver a diferença completa a cada passo, use
+Se você também quiser ver a diferença completa a cada passo, use
------------------------------------------------
$ git log -p
diff --git a/Documentation/technical/racy-git.txt b/Documentation/technical/racy-git.txt
index 48bb97f0b1..53aa0c82c2 100644
--- a/Documentation/technical/racy-git.txt
+++ b/Documentation/technical/racy-git.txt
@@ -42,10 +42,12 @@ compared, but this is not enabled by default because this member
is not stable on network filesystems. With `USE_NSEC`
compile-time option, `st_mtim.tv_nsec` and `st_ctim.tv_nsec`
members are also compared, but this is not enabled by default
-because the value of this member becomes meaningless once the
-inode is evicted from the inode cache on filesystems that do not
-store it on disk.
-
+because in-core timestamps can have finer granularity than
+on-disk timestamps, resulting in meaningless changes when an
+inode is evicted from the inode cache. See commit 8ce13b0
+of git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
+([PATCH] Sync in core time granuality with filesystems,
+2005-01-04).
Racy git
--------
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index d7d9a9a063..710d361233 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v1.6.4.GIT
+DEF_VER=v1.6.5.GIT
LF='
'
diff --git a/Makefile b/Makefile
index 12defd4c97..42b7d60e19 100644
--- a/Makefile
+++ b/Makefile
@@ -153,7 +153,11 @@ all::
#
# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
#
-# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
+# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72
+# (not v1.73 or v1.71).
+#
+# Define ASCIIDOC_NO_ROFF if your DocBook XSL escapes raw roff directives
+# (versions 1.72 and later and 1.68.1 and earlier).
#
# Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's
# MakeMaker (e.g. using ActiveState under Cygwin).
@@ -734,6 +738,7 @@ ifeq ($(uname_S),SunOS)
NO_MKSTEMPS = YesPlease
NO_REGEX = YesPlease
NO_EXTERNAL_GREP = YesPlease
+ THREADED_DELTA_SEARCH = YesPlease
ifeq ($(uname_R),5.7)
NEEDS_RESOLV = YesPlease
NO_IPV6 = YesPlease
@@ -840,11 +845,18 @@ ifeq ($(uname_S),IRIX)
NO_MEMMEM = YesPlease
NO_MKSTEMPS = YesPlease
NO_MKDTEMP = YesPlease
+ # When compiled with the MIPSpro 7.4.4m compiler, and without pthreads
+ # (i.e. NO_PTHREADS is set), and _with_ MMAP (i.e. NO_MMAP is not set),
+ # git dies with a segmentation fault when trying to access the first
+ # entry of a reflog. The conservative choice is made to always set
+ # NO_MMAP. If you suspect that your compiler is not affected by this
+ # issue, comment out the NO_MMAP statement.
NO_MMAP = YesPlease
NO_EXTERNAL_GREP = UnfortunatelyYes
SNPRINTF_RETURNS_BOGUS = YesPlease
SHELL_PATH = /usr/gnu/bin/bash
NEEDS_LIBGEN = YesPlease
+ THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),IRIX64)
NO_SETENV=YesPlease
@@ -853,11 +865,18 @@ ifeq ($(uname_S),IRIX64)
NO_MEMMEM = YesPlease
NO_MKSTEMPS = YesPlease
NO_MKDTEMP = YesPlease
+ # When compiled with the MIPSpro 7.4.4m compiler, and without pthreads
+ # (i.e. NO_PTHREADS is set), and _with_ MMAP (i.e. NO_MMAP is not set),
+ # git dies with a segmentation fault when trying to access the first
+ # entry of a reflog. The conservative choice is made to always set
+ # NO_MMAP. If you suspect that your compiler is not affected by this
+ # issue, comment out the NO_MMAP statement.
NO_MMAP = YesPlease
NO_EXTERNAL_GREP = UnfortunatelyYes
SNPRINTF_RETURNS_BOGUS = YesPlease
SHELL_PATH=/usr/gnu/bin/bash
NEEDS_LIBGEN = YesPlease
+ THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),HP-UX)
NO_IPV6=YesPlease
@@ -914,7 +933,7 @@ ifdef MSVC
CC = compat/vcbuild/scripts/clink.pl
AR = compat/vcbuild/scripts/lib.pl
CFLAGS =
- BASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32-D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
+ BASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -DSTRIP_EXTENSION=\".exe\"
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
@@ -1808,7 +1827,7 @@ distclean: clean
$(RM) configure
clean:
- $(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o \
+ $(RM) *.o block-sha1/*.o arm/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o \
$(LIB_FILE) $(XDIFF_LIB)
$(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
$(RM) $(TEST_PROGRAMS)
diff --git a/README b/README
index c932ab3105..67cfeb2016 100644
--- a/README
+++ b/README
@@ -37,7 +37,7 @@ CVS users may also want to read Documentation/gitcvs-migration.txt
("man gitcvs-migration" or "git help cvs-migration" if git is
installed).
-Many Git online resources are accessible from http://git.or.cz/
+Many Git online resources are accessible from http://git-scm.com/
including full documentation and Git related tools.
The user discussion and development of Git take place on the Git
diff --git a/RelNotes b/RelNotes
index b62449d2e2..5274ceed4e 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.6.5.txt \ No newline at end of file
+Documentation/RelNotes-1.6.6.txt \ No newline at end of file
diff --git a/archive.c b/archive.c
index 73b8e8a56d..0cc79d2a24 100644
--- a/archive.c
+++ b/archive.c
@@ -115,6 +115,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
strbuf_reset(&path);
strbuf_grow(&path, PATH_MAX);
+ strbuf_add(&path, args->base, args->baselen);
strbuf_add(&path, base, baselen);
strbuf_addstr(&path, filename);
path_without_prefix = path.buf + args->baselen;
@@ -187,8 +188,8 @@ int write_archive_entries(struct archiver_args *args,
git_attr_set_direction(GIT_ATTR_INDEX, &the_index);
}
- err = read_tree_recursive(args->tree, args->base, args->baselen, 0,
- args->pathspec, write_archive_entry, &context);
+ err = read_tree_recursive(args->tree, "", 0, 0, args->pathspec,
+ write_archive_entry, &context);
if (err == READ_TREE_RECURSIVE)
err = 0;
return err;
@@ -211,7 +212,7 @@ static const struct archiver *lookup_archiver(const char *name)
static void parse_pathspec_arg(const char **pathspec,
struct archiver_args *ar_args)
{
- ar_args->pathspec = get_pathspec(ar_args->base, pathspec);
+ ar_args->pathspec = get_pathspec("", pathspec);
}
static void parse_treeish_arg(const char **argv,
diff --git a/builtin-apply.c b/builtin-apply.c
index c8372a0a80..f667368d16 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -153,6 +153,7 @@ struct fragment {
const char *patch;
int size;
int rejected;
+ int linenr;
struct fragment *next;
};
@@ -1227,23 +1228,29 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
return -1;
}
-static void check_whitespace(const char *line, int len, unsigned ws_rule)
+static void record_ws_error(unsigned result, const char *line, int len, int linenr)
{
char *err;
- unsigned result = ws_check(line + 1, len - 1, ws_rule);
+
if (!result)
return;
whitespace_error++;
if (squelch_whitespace_errors &&
squelch_whitespace_errors < whitespace_error)
- ;
- else {
- err = whitespace_error_string(result);
- fprintf(stderr, "%s:%d: %s.\n%.*s\n",
- patch_input_file, linenr, err, len - 2, line + 1);
- free(err);
- }
+ return;
+
+ err = whitespace_error_string(result);
+ fprintf(stderr, "%s:%d: %s.\n%.*s\n",
+ patch_input_file, linenr, err, len, line);
+ free(err);
+}
+
+static void check_whitespace(const char *line, int len, unsigned ws_rule)
+{
+ unsigned result = ws_check(line + 1, len - 1, ws_rule);
+
+ record_ws_error(result, line + 1, len - 2, linenr);
}
/*
@@ -1359,6 +1366,7 @@ static int parse_single_patch(char *line, unsigned long size, struct patch *patc
int len;
fragment = xcalloc(1, sizeof(*fragment));
+ fragment->linenr = linenr;
len = parse_fragment(line, size, patch, fragment);
if (len <= 0)
die("corrupt patch at line %d", linenr);
@@ -2142,6 +2150,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
int len = linelen(patch, size);
int plen, added;
int added_blank_line = 0;
+ int is_blank_context = 0;
if (!len)
break;
@@ -2174,8 +2183,12 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
*new++ = '\n';
add_line_info(&preimage, "\n", 1, LINE_COMMON);
add_line_info(&postimage, "\n", 1, LINE_COMMON);
+ is_blank_context = 1;
break;
case ' ':
+ if (plen && (ws_rule & WS_BLANK_AT_EOF) &&
+ ws_blank_line(patch + 1, plen, ws_rule))
+ is_blank_context = 1;
case '-':
memcpy(old, patch + 1, plen);
add_line_info(&preimage, old, plen,
@@ -2202,7 +2215,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
(first == '+' ? 0 : LINE_COMMON));
new += added;
if (first == '+' &&
- added == 1 && new[-1] == '\n')
+ (ws_rule & WS_BLANK_AT_EOF) &&
+ ws_blank_line(patch + 1, plen, ws_rule))
added_blank_line = 1;
break;
case '@': case '\\':
@@ -2215,6 +2229,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
}
if (added_blank_line)
new_blank_lines_at_end++;
+ else if (is_blank_context)
+ ;
else
new_blank_lines_at_end = 0;
patch += len;
@@ -2296,17 +2312,24 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
}
if (applied_pos >= 0) {
- if (ws_error_action == correct_ws_error &&
- new_blank_lines_at_end &&
- postimage.nr + applied_pos == img->nr) {
+ if (new_blank_lines_at_end &&
+ preimage.nr + applied_pos == img->nr &&
+ (ws_rule & WS_BLANK_AT_EOF) &&
+ ws_error_action != nowarn_ws_error) {
+ record_ws_error(WS_BLANK_AT_EOF, "+", 1, frag->linenr);
+ if (ws_error_action == correct_ws_error) {
+ while (new_blank_lines_at_end--)
+ remove_last_line(&postimage);
+ }
/*
- * If the patch application adds blank lines
- * at the end, and if the patch applies at the
- * end of the image, remove those added blank
- * lines.
+ * We would want to prevent write_out_results()
+ * from taking place in apply_patch() that follows
+ * the callchain led us here, which is:
+ * apply_patch->check_patch_list->check_patch->
+ * apply_data->apply_fragments->apply_one_fragment
*/
- while (new_blank_lines_at_end--)
- remove_last_line(&postimage);
+ if (ws_error_action == die_on_ws_error)
+ apply = 0;
}
/*
diff --git a/builtin-clone.c b/builtin-clone.c
index 4992c2597c..5762a6f9d8 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -641,7 +641,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
die("unable to write new index file");
err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
- sha1_to_hex(remote_head->old_sha1), "1", NULL);
+ sha1_to_hex(our_head_points_at->old_sha1), "1",
+ NULL);
if (!err && option_recursive)
err = run_command_v_opt(argv_submodule, RUN_GIT_CMD);
diff --git a/builtin-describe.c b/builtin-describe.c
index df67a733ae..2dcfd3dfeb 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -180,7 +180,6 @@ static void describe(const char *arg, int last_one)
unsigned char sha1[20];
struct commit *cmit, *gave_up_on = NULL;
struct commit_list *list;
- static int initialized = 0;
struct commit_name *n;
struct possible_tag all_matches[MAX_TAGS];
unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
@@ -192,14 +191,6 @@ static void describe(const char *arg, int last_one)
if (!cmit)
die("%s is not a valid '%s' object", arg, commit_type);
- if (!initialized) {
- initialized = 1;
- for_each_ref(get_name, NULL);
- }
-
- if (!found_names)
- die("cannot describe '%s'", sha1_to_hex(sha1));
-
n = cmit->util;
if (n) {
/*
@@ -359,6 +350,10 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
return cmd_name_rev(i + argc, args, prefix);
}
+ for_each_ref(get_name, NULL);
+ if (!found_names)
+ die("No names found, cannot describe anything.");
+
if (argc == 0) {
describe("HEAD", 1);
} else {
diff --git a/builtin-fetch.c b/builtin-fetch.c
index cb48c57ca3..a35a6f8cb8 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -504,57 +504,98 @@ static int will_fetch(struct ref **head, const unsigned char *sha1)
return 0;
}
+struct tag_data {
+ struct ref **head;
+ struct ref ***tail;
+};
+
+static int add_to_tail(struct string_list_item *item, void *cb_data)
+{
+ struct tag_data *data = (struct tag_data *)cb_data;
+ struct ref *rm = NULL;
+
+ /* We have already decided to ignore this item */
+ if (!item->util)
+ return 0;
+
+ rm = alloc_ref(item->string);
+ rm->peer_ref = alloc_ref(item->string);
+ hashcpy(rm->old_sha1, item->util);
+
+ **data->tail = rm;
+ *data->tail = &rm->next;
+
+ return 0;
+}
+
static void find_non_local_tags(struct transport *transport,
struct ref **head,
struct ref ***tail)
{
struct string_list existing_refs = { NULL, 0, 0, 0 };
- struct string_list new_refs = { NULL, 0, 0, 1 };
- char *ref_name;
- int ref_name_len;
- const unsigned char *ref_sha1;
- const struct ref *tag_ref;
- struct ref *rm = NULL;
+ struct string_list remote_refs = { NULL, 0, 0, 0 };
+ struct tag_data data = {head, tail};
const struct ref *ref;
+ struct string_list_item *item = NULL;
for_each_ref(add_existing, &existing_refs);
for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
if (prefixcmp(ref->name, "refs/tags"))
continue;
- ref_name = xstrdup(ref->name);
- ref_name_len = strlen(ref_name);
- ref_sha1 = ref->old_sha1;
-
- if (!strcmp(ref_name + ref_name_len - 3, "^{}")) {
- ref_name[ref_name_len - 3] = 0;
- tag_ref = transport_get_remote_refs(transport);
- while (tag_ref) {
- if (!strcmp(tag_ref->name, ref_name)) {
- ref_sha1 = tag_ref->old_sha1;
- break;
- }
- tag_ref = tag_ref->next;
- }
+ /*
+ * The peeled ref always follows the matching base
+ * ref, so if we see a peeled ref that we don't want
+ * to fetch then we can mark the ref entry in the list
+ * as one to ignore by setting util to NULL.
+ */
+ if (!strcmp(ref->name + strlen(ref->name) - 3, "^{}")) {
+ if (item && !has_sha1_file(ref->old_sha1) &&
+ !will_fetch(head, ref->old_sha1) &&
+ !has_sha1_file(item->util) &&
+ !will_fetch(head, item->util))
+ item->util = NULL;
+ item = NULL;
+ continue;
}
- if (!string_list_has_string(&existing_refs, ref_name) &&
- !string_list_has_string(&new_refs, ref_name) &&
- (has_sha1_file(ref->old_sha1) ||
- will_fetch(head, ref->old_sha1))) {
- string_list_insert(ref_name, &new_refs);
+ /*
+ * If item is non-NULL here, then we previously saw a
+ * ref not followed by a peeled reference, so we need
+ * to check if it is a lightweight tag that we want to
+ * fetch.
+ */
+ if (item && !has_sha1_file(item->util) &&
+ !will_fetch(head, item->util))
+ item->util = NULL;
- rm = alloc_ref(ref_name);
- rm->peer_ref = alloc_ref(ref_name);
- hashcpy(rm->old_sha1, ref_sha1);
+ item = NULL;
- **tail = rm;
- *tail = &rm->next;
- }
- free(ref_name);
+ /* skip duplicates and refs that we already have */
+ if (string_list_has_string(&remote_refs, ref->name) ||
+ string_list_has_string(&existing_refs, ref->name))
+ continue;
+
+ item = string_list_insert(ref->name, &remote_refs);
+ item->util = (void *)ref->old_sha1;
}
string_list_clear(&existing_refs, 0);
- string_list_clear(&new_refs, 0);
+
+ /*
+ * We may have a final lightweight tag that needs to be
+ * checked to see if it needs fetching.
+ */
+ if (item && !has_sha1_file(item->util) &&
+ !will_fetch(head, item->util))
+ item->util = NULL;
+
+ /*
+ * For all the tags in the remote_refs string list, call
+ * add_to_tail to add them to the list of refs to be fetched
+ */
+ for_each_string_list(add_to_tail, &remote_refs, &data);
+
+ string_list_clear(&remote_refs, 0);
}
static void check_not_current_branch(struct ref *ref_map)
diff --git a/builtin-grep.c b/builtin-grep.c
index 761799d7d0..1df25b07b5 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -631,7 +631,7 @@ static int file_callback(const struct option *opt, const char *arg, int unset)
struct grep_opt *grep_opt = opt->value;
FILE *patterns;
int lno = 0;
- struct strbuf sb;
+ struct strbuf sb = STRBUF_INIT;
patterns = fopen(arg, "r");
if (!patterns)
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index f473220502..c5c0407b0b 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -170,10 +170,6 @@ static void show_files(struct dir_struct *dir, const char *prefix)
if (show_cached | show_stage) {
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
- int dtype = ce_to_dtype(ce);
- if (excluded(dir, ce->name, &dtype) !=
- !!(dir->flags & DIR_SHOW_IGNORED))
- continue;
if (show_unmerged && !ce_stage(ce))
continue;
if (ce->ce_flags & CE_UPDATE)
@@ -186,10 +182,6 @@ static void show_files(struct dir_struct *dir, const char *prefix)
struct cache_entry *ce = active_cache[i];
struct stat st;
int err;
- int dtype = ce_to_dtype(ce);
- if (excluded(dir, ce->name, &dtype) !=
- !!(dir->flags & DIR_SHOW_IGNORED))
- continue;
if (ce->ce_flags & CE_UPDATE)
continue;
err = lstat(ce->name, &st);
@@ -524,11 +516,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
ps_matched = xcalloc(1, num);
}
- if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given) {
- fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
- argv[0]);
- exit(1);
- }
+ if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given)
+ die("ls-files --ignored needs some exclude pattern");
/* With no flags, we default to showing the cached files */
if (!(show_stage | show_deleted | show_others | show_unmerged |
diff --git a/builtin-push.c b/builtin-push.c
index 3cb1ee46d1..b5cd2cdad0 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -10,7 +10,7 @@
#include "parse-options.h"
static const char * const push_usage[] = {
- "git push [--all | --mirror] [-n | --dry-run] [--porcelain] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
+ "git push [<options>] [<repository> <refspec>...]",
NULL,
};
@@ -181,7 +181,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
(TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
- OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
+ OPT_BOOLEAN( 0 , "tags", &tags, "push tags (can't be used with --all or --mirror"),
OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
OPT_BIT( 0, "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
diff --git a/builtin-show-branch.c b/builtin-show-branch.c
index 3510a86e38..be95930b78 100644
--- a/builtin-show-branch.c
+++ b/builtin-show-branch.c
@@ -565,7 +565,15 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "showbranch.default")) {
if (!value)
return config_error_nonbool(var);
- if (default_alloc <= default_num + 1) {
+ /*
+ * default_arg is now passed to parse_options(), so we need to
+ * mimick the real argv a bit better.
+ */
+ if (!default_num) {
+ default_alloc = 20;
+ default_arg = xcalloc(default_alloc, sizeof(*default_arg));
+ default_arg[default_num++] = "show-branch";
+ } else if (default_alloc <= default_num + 1) {
default_alloc = default_alloc * 3 / 2 + 20;
default_arg = xrealloc(default_arg, sizeof *default_arg * default_alloc);
}
@@ -692,8 +700,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
/* If nothing is specified, try the default first */
if (ac == 1 && default_num) {
- ac = default_num + 1;
- av = default_arg - 1; /* ick; we would not address av[0] */
+ ac = default_num;
+ av = default_arg;
}
ac = parse_options(ac, av, prefix, builtin_show_branch_options,
diff --git a/cache.h b/cache.h
index a5eeead1e2..96840c7af7 100644
--- a/cache.h
+++ b/cache.h
@@ -986,10 +986,12 @@ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, i
* whitespace rules.
* used by both diff and apply
*/
-#define WS_TRAILING_SPACE 01
+#define WS_BLANK_AT_EOL 01
#define WS_SPACE_BEFORE_TAB 02
#define WS_INDENT_WITH_NON_TAB 04
#define WS_CR_AT_EOL 010
+#define WS_BLANK_AT_EOF 020
+#define WS_TRAILING_SPACE (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB)
extern unsigned whitespace_rule_cfg;
extern unsigned whitespace_rule(const char *);
diff --git a/command-list.txt b/command-list.txt
index fb03a2ebb5..59b0adc39b 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -92,6 +92,7 @@ git-reflog ancillarymanipulators
git-relink ancillarymanipulators
git-remote ancillarymanipulators
git-repack ancillarymanipulators
+git-replace ancillarymanipulators
git-repo-config ancillarymanipulators deprecated
git-request-pull foreignscminterface
git-rerere ancillaryinterrogators
diff --git a/commit.h b/commit.h
index f4fc5c5589..95f981a1a9 100644
--- a/commit.h
+++ b/commit.h
@@ -70,7 +70,7 @@ extern char *reencode_commit_message(const struct commit *commit,
const char **encoding_p);
extern void get_commit_format(const char *arg, struct rev_info *);
extern void format_commit_message(const struct commit *commit,
- const void *format, struct strbuf *sb,
+ const char *format, struct strbuf *sb,
enum date_mode dmode);
extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*,
struct strbuf *,
diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl
index 0ffd59f9fb..f9528c0ea1 100644
--- a/compat/vcbuild/scripts/clink.pl
+++ b/compat/vcbuild/scripts/clink.pl
@@ -45,4 +45,4 @@ if ($is_linking) {
push(@args, @cflags);
}
#printf("**** @args\n");
-exit system(@args);
+exit (system(@args) != 0);
diff --git a/compat/vcbuild/scripts/lib.pl b/compat/vcbuild/scripts/lib.pl
index 68f66446ea..d8054e469f 100644
--- a/compat/vcbuild/scripts/lib.pl
+++ b/compat/vcbuild/scripts/lib.pl
@@ -23,4 +23,4 @@ while (@ARGV) {
}
unshift(@args, "lib.exe");
# printf("**** @args\n");
-exit system(@args);
+exit (system(@args) != 0);
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 2c2a0d4614..d3fec32997 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -496,7 +496,7 @@ __git_all_commands ()
return
fi
local i IFS=" "$'\n'
- for i in $(git help -a|egrep '^ ')
+ for i in $(git help -a|egrep '^ [a-zA-Z0-9]')
do
case $i in
*--*) : helper pattern;;
@@ -602,8 +602,12 @@ __git_aliases ()
{
local i IFS=$'\n'
for i in $(git --git-dir="$(__gitdir)" config --get-regexp "alias\..*" 2>/dev/null); do
- i="${i#alias.}"
- echo "${i/ */}"
+ case "$i" in
+ alias.*)
+ i="${i#alias.}"
+ echo "${i/ */}"
+ ;;
+ esac
done
}
@@ -668,7 +672,7 @@ _git_am ()
--3way --committer-date-is-author-date --ignore-date
--ignore-whitespace --ignore-space-change
--interactive --keep --no-utf8 --signoff --utf8
- --whitespace=
+ --whitespace= --scissors
"
return
esac
@@ -894,6 +898,7 @@ _git_commit ()
__gitcomp "
--all --author= --signoff --verify --no-verify
--edit --amend --include --only --interactive
+ --dry-run
"
return
esac
@@ -926,6 +931,8 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
--inter-hunk-context=
--patience
--raw
+ --dirstat --dirstat= --dirstat-by-file
+ --dirstat-by-file= --cumulative
"
_git_diff ()
@@ -1062,7 +1069,8 @@ _git_grep ()
return
;;
esac
- COMPREPLY=()
+
+ __gitcomp "$(__git_refs)"
}
_git_help ()
@@ -1179,6 +1187,10 @@ _git_log ()
__gitcomp "$__git_log_date_formats" "" "${cur##--date=}"
return
;;
+ --decorate=*)
+ __gitcomp "long short" "" "${cur##--decorate=}"
+ return
+ ;;
--*)
__gitcomp "
$__git_log_common_options
@@ -1191,7 +1203,7 @@ _git_log ()
--pretty= --format= --oneline
--cherry-pick
--graph
- --decorate
+ --decorate --decorate=
--walk-reflogs
--parents --children
$merge
@@ -1787,6 +1799,11 @@ _git_remote ()
esac
}
+_git_replace ()
+{
+ __gitcomp "$(__git_refs)"
+}
+
_git_reset ()
{
__git_has_doubledash && return
@@ -2155,6 +2172,7 @@ _git ()
push) _git_push ;;
rebase) _git_rebase ;;
remote) _git_remote ;;
+ replace) _git_replace ;;
reset) _git_reset ;;
revert) _git_revert ;;
rm) _git_rm ;;
diff --git a/contrib/emacs/git-blame.el b/contrib/emacs/git-blame.el
index 4fa70c5ad4..7f4c792978 100644
--- a/contrib/emacs/git-blame.el
+++ b/contrib/emacs/git-blame.el
@@ -80,6 +80,57 @@
(eval-when-compile (require 'cl)) ; to use `push', `pop'
+(defface git-blame-prefix-face
+ '((((background dark)) (:foreground "gray"
+ :background "black"))
+ (((background light)) (:foreground "gray"
+ :background "white"))
+ (t (:weight bold)))
+ "The face used for the hash prefix."
+ :group 'git-blame)
+
+(defgroup git-blame nil
+ "A minor mode showing Git blame information."
+ :group 'git
+ :link '(function-link git-blame-mode))
+
+
+(defcustom git-blame-use-colors t
+ "Use colors to indicate commits in `git-blame-mode'."
+ :type 'boolean
+ :group 'git-blame)
+
+(defcustom git-blame-prefix-format
+ "%h %20A:"
+ "The format of the prefix added to each line in `git-blame'
+mode. The format is passed to `format-spec' with the following format keys:
+
+ %h - the abbreviated hash
+ %H - the full hash
+ %a - the author name
+ %A - the author email
+ %c - the committer name
+ %C - the committer email
+ %s - the commit summary
+"
+ :group 'git-blame)
+
+(defcustom git-blame-mouseover-format
+ "%h %a %A: %s"
+ "The format of the description shown when pointing at a line in
+`git-blame' mode. The format string is passed to `format-spec'
+with the following format keys:
+
+ %h - the abbreviated hash
+ %H - the full hash
+ %a - the author name
+ %A - the author email
+ %c - the committer name
+ %C - the committer email
+ %s - the commit summary
+"
+ :group 'git-blame)
+
(defun git-blame-color-scale (&rest elements)
"Given a list, returns a list of triples formed with each
@@ -302,72 +353,69 @@ See also function `git-blame-mode'."
(src-line (string-to-number (match-string 2)))
(res-line (string-to-number (match-string 3)))
(num-lines (string-to-number (match-string 4))))
- (setq git-blame-current
- (if (string= hash "0000000000000000000000000000000000000000")
- nil
- (git-blame-new-commit
- hash src-line res-line num-lines))))
- (delete-region (point) (match-end 0))
- t)
- ((looking-at "filename \\(.+\\)\n")
- (let ((filename (match-string 1)))
- (git-blame-add-info "filename" filename))
- (delete-region (point) (match-end 0))
+ (delete-region (point) (match-end 0))
+ (setq git-blame-current (list (git-blame-new-commit hash)
+ src-line res-line num-lines)))
t)
((looking-at "\\([a-z-]+\\) \\(.+\\)\n")
(let ((key (match-string 1))
(value (match-string 2)))
- (git-blame-add-info key value))
- (delete-region (point) (match-end 0))
- t)
- ((looking-at "boundary\n")
- (setq git-blame-current nil)
- (delete-region (point) (match-end 0))
+ (delete-region (point) (match-end 0))
+ (git-blame-add-info (car git-blame-current) key value)
+ (when (string= key "filename")
+ (git-blame-create-overlay (car git-blame-current)
+ (caddr git-blame-current)
+ (cadddr git-blame-current))
+ (setq git-blame-current nil)))
t)
(t
nil)))
-(defun git-blame-new-commit (hash src-line res-line num-lines)
+(defun git-blame-new-commit (hash)
+ (with-current-buffer git-blame-file
+ (or (gethash hash git-blame-cache)
+ ;; Assign a random color to each new commit info
+ ;; Take care not to select the same color multiple times
+ (let* ((color (if git-blame-colors
+ (git-blame-random-pop git-blame-colors)
+ git-blame-ancient-color))
+ (info `(,hash (color . ,color))))
+ (puthash hash info git-blame-cache)
+ info))))
+
+(defun git-blame-create-overlay (info start-line num-lines)
(save-excursion
(set-buffer git-blame-file)
- (let ((info (gethash hash git-blame-cache))
- (inhibit-point-motion-hooks t)
+ (let ((inhibit-point-motion-hooks t)
(inhibit-modification-hooks t))
- (when (not info)
- ;; Assign a random color to each new commit info
- ;; Take care not to select the same color multiple times
- (let ((color (if git-blame-colors
- (git-blame-random-pop git-blame-colors)
- git-blame-ancient-color)))
- (setq info (list hash src-line res-line num-lines
- (git-describe-commit hash)
- (cons 'color color))))
- (puthash hash info git-blame-cache))
- (goto-line res-line)
- (while (> num-lines 0)
- (if (get-text-property (point) 'git-blame)
- (forward-line)
- (let* ((start (point))
- (end (progn (forward-line 1) (point)))
- (ovl (make-overlay start end)))
- (push ovl git-blame-overlays)
- (overlay-put ovl 'git-blame info)
- (overlay-put ovl 'help-echo hash)
+ (goto-line start-line)
+ (let* ((start (point))
+ (end (progn (forward-line num-lines) (point)))
+ (ovl (make-overlay start end))
+ (hash (car info))
+ (spec `((?h . ,(substring hash 0 6))
+ (?H . ,hash)
+ (?a . ,(git-blame-get-info info 'author))
+ (?A . ,(git-blame-get-info info 'author-mail))
+ (?c . ,(git-blame-get-info info 'committer))
+ (?C . ,(git-blame-get-info info 'committer-mail))
+ (?s . ,(git-blame-get-info info 'summary)))))
+ (push ovl git-blame-overlays)
+ (overlay-put ovl 'git-blame info)
+ (overlay-put ovl 'help-echo
+ (format-spec git-blame-mouseover-format spec))
+ (if git-blame-use-colors
(overlay-put ovl 'face (list :background
- (cdr (assq 'color (nthcdr 5 info)))))
- ;; the point-entered property doesn't seem to work in overlays
- ;;(overlay-put ovl 'point-entered
- ;; `(lambda (x y) (git-blame-identify ,hash)))
- (let ((modified (buffer-modified-p)))
- (put-text-property (if (= start 1) start (1- start)) (1- end)
- 'point-entered
- `(lambda (x y) (git-blame-identify ,hash)))
- (set-buffer-modified-p modified))))
- (setq num-lines (1- num-lines))))))
-
-(defun git-blame-add-info (key value)
- (if git-blame-current
- (nconc git-blame-current (list (cons (intern key) value)))))
+ (cdr (assq 'color (cdr info))))))
+ (overlay-put ovl 'line-prefix
+ (propertize (format-spec git-blame-prefix-format spec)
+ 'face 'git-blame-prefix-face))))))
+
+(defun git-blame-add-info (info key value)
+ (nconc info (list (cons (intern key) value))))
+
+(defun git-blame-get-info (info key)
+ (cdr (assq key (cdr info))))
(defun git-blame-current-commit ()
(let ((info (get-char-property (point) 'git-blame)))
diff --git a/contrib/fast-import/import-tars.perl b/contrib/fast-import/import-tars.perl
index a909716682..7001862bfd 100755
--- a/contrib/fast-import/import-tars.perl
+++ b/contrib/fast-import/import-tars.perl
@@ -140,7 +140,7 @@ foreach my $tar_file (@ARGV)
} elsif (!$header_done && /^Author:\s+([^<>]*)\s+<(.*)>\s*$/i) {
$this_author_name = $1;
$this_author_email = $2;
- } elsif (!$header_done && /^$/ { # empty line ends header.
+ } elsif (!$header_done && /^$/) { # empty line ends header.
$header_done = 1;
} else {
$commit_msg .= $_;
diff --git a/diff.c b/diff.c
index e1be189742..b0c7e616a6 100644
--- a/diff.c
+++ b/diff.c
@@ -174,6 +174,175 @@ static struct diff_tempfile {
char tmp_path[PATH_MAX];
} diff_temp[2];
+typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
+
+struct emit_callback {
+ int color_diff;
+ unsigned ws_rule;
+ int blank_at_eof_in_preimage;
+ int blank_at_eof_in_postimage;
+ int lno_in_preimage;
+ int lno_in_postimage;
+ sane_truncate_fn truncate;
+ const char **label_path;
+ struct diff_words_data *diff_words;
+ int *found_changesp;
+ FILE *file;
+};
+
+static int count_lines(const char *data, int size)
+{
+ int count, ch, completely_empty = 1, nl_just_seen = 0;
+ count = 0;
+ while (0 < size--) {
+ ch = *data++;
+ if (ch == '\n') {
+ count++;
+ nl_just_seen = 1;
+ completely_empty = 0;
+ }
+ else {
+ nl_just_seen = 0;
+ completely_empty = 0;
+ }
+ }
+ if (completely_empty)
+ return 0;
+ if (!nl_just_seen)
+ count++; /* no trailing newline */
+ return count;
+}
+
+static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
+{
+ if (!DIFF_FILE_VALID(one)) {
+ mf->ptr = (char *)""; /* does not matter */
+ mf->size = 0;
+ return 0;
+ }
+ else if (diff_populate_filespec(one, 0))
+ return -1;
+
+ mf->ptr = one->data;
+ mf->size = one->size;
+ return 0;
+}
+
+static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule)
+{
+ char *ptr = mf->ptr;
+ long size = mf->size;
+ int cnt = 0;
+
+ if (!size)
+ return cnt;
+ ptr += size - 1; /* pointing at the very end */
+ if (*ptr != '\n')
+ ; /* incomplete line */
+ else
+ ptr--; /* skip the last LF */
+ while (mf->ptr < ptr) {
+ char *prev_eol;
+ for (prev_eol = ptr; mf->ptr <= prev_eol; prev_eol--)
+ if (*prev_eol == '\n')
+ break;
+ if (!ws_blank_line(prev_eol + 1, ptr - prev_eol, ws_rule))
+ break;
+ cnt++;
+ ptr = prev_eol - 1;
+ }
+ return cnt;
+}
+
+static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,
+ struct emit_callback *ecbdata)
+{
+ int l1, l2, at;
+ unsigned ws_rule = ecbdata->ws_rule;
+ l1 = count_trailing_blank(mf1, ws_rule);
+ l2 = count_trailing_blank(mf2, ws_rule);
+ if (l2 <= l1) {
+ ecbdata->blank_at_eof_in_preimage = 0;
+ ecbdata->blank_at_eof_in_postimage = 0;
+ return;
+ }
+ at = count_lines(mf1->ptr, mf1->size);
+ ecbdata->blank_at_eof_in_preimage = (at - l1) + 1;
+
+ at = count_lines(mf2->ptr, mf2->size);
+ ecbdata->blank_at_eof_in_postimage = (at - l2) + 1;
+}
+
+static void emit_line_0(FILE *file, const char *set, const char *reset,
+ int first, const char *line, int len)
+{
+ int has_trailing_newline, has_trailing_carriage_return;
+ int nofirst;
+
+ if (len == 0) {
+ has_trailing_newline = (first == '\n');
+ has_trailing_carriage_return = (!has_trailing_newline &&
+ (first == '\r'));
+ nofirst = has_trailing_newline || has_trailing_carriage_return;
+ } else {
+ has_trailing_newline = (len > 0 && line[len-1] == '\n');
+ if (has_trailing_newline)
+ len--;
+ has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
+ if (has_trailing_carriage_return)
+ len--;
+ nofirst = 0;
+ }
+
+ fputs(set, file);
+
+ if (!nofirst)
+ fputc(first, file);
+ fwrite(line, len, 1, file);
+ fputs(reset, file);
+ if (has_trailing_carriage_return)
+ fputc('\r', file);
+ if (has_trailing_newline)
+ fputc('\n', file);
+}
+
+static void emit_line(FILE *file, const char *set, const char *reset,
+ const char *line, int len)
+{
+ emit_line_0(file, set, reset, line[0], line+1, len-1);
+}
+
+static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line, int len)
+{
+ if (!((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&
+ ecbdata->blank_at_eof_in_preimage &&
+ ecbdata->blank_at_eof_in_postimage &&
+ ecbdata->blank_at_eof_in_preimage <= ecbdata->lno_in_preimage &&
+ ecbdata->blank_at_eof_in_postimage <= ecbdata->lno_in_postimage))
+ return 0;
+ return ws_blank_line(line, len, ecbdata->ws_rule);
+}
+
+static void emit_add_line(const char *reset,
+ struct emit_callback *ecbdata,
+ const char *line, int len)
+{
+ const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
+ const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
+
+ if (!*ws)
+ emit_line_0(ecbdata->file, set, reset, '+', line, len);
+ else if (new_blank_line_at_eof(ecbdata, line, len))
+ /* Blank line at EOF - paint '+' as well */
+ emit_line_0(ecbdata->file, ws, reset, '+', line, len);
+ else {
+ /* Emit just the prefix, then the rest. */
+ emit_line_0(ecbdata->file, set, reset, '+', "", 0);
+ ws_check_emit(line, len, ecbdata->ws_rule,
+ ecbdata->file, set, reset, ws);
+ }
+}
+
static struct diff_tempfile *claim_diff_tempfile(void) {
int i;
for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
@@ -201,29 +370,6 @@ static void remove_tempfile_on_signal(int signo)
raise(signo);
}
-static int count_lines(const char *data, int size)
-{
- int count, ch, completely_empty = 1, nl_just_seen = 0;
- count = 0;
- while (0 < size--) {
- ch = *data++;
- if (ch == '\n') {
- count++;
- nl_just_seen = 1;
- completely_empty = 0;
- }
- else {
- nl_just_seen = 0;
- completely_empty = 0;
- }
- }
- if (completely_empty)
- return 0;
- if (!nl_just_seen)
- count++; /* no trailing newline */
- return count;
-}
-
static void print_line_count(FILE *file, int count)
{
switch (count) {
@@ -239,26 +385,36 @@ static void print_line_count(FILE *file, int count)
}
}
-static void copy_file_with_prefix(FILE *file,
- int prefix, const char *data, int size,
- const char *set, const char *reset)
+static void emit_rewrite_lines(struct emit_callback *ecb,
+ int prefix, const char *data, int size)
{
- int ch, nl_just_seen = 1;
- while (0 < size--) {
- ch = *data++;
- if (nl_just_seen) {
- fputs(set, file);
- putc(prefix, file);
+ const char *endp = NULL;
+ static const char *nneof = " No newline at end of file\n";
+ const char *old = diff_get_color(ecb->color_diff, DIFF_FILE_OLD);
+ const char *reset = diff_get_color(ecb->color_diff, DIFF_RESET);
+
+ while (0 < size) {
+ int len;
+
+ endp = memchr(data, '\n', size);
+ len = endp ? (endp - data + 1) : size;
+ if (prefix != '+') {
+ ecb->lno_in_preimage++;
+ emit_line_0(ecb->file, old, reset, '-',
+ data, len);
+ } else {
+ ecb->lno_in_postimage++;
+ emit_add_line(reset, ecb, data, len);
}
- if (ch == '\n') {
- nl_just_seen = 1;
- fputs(reset, file);
- } else
- nl_just_seen = 0;
- putc(ch, file);
+ size -= len;
+ data += len;
+ }
+ if (!endp) {
+ const char *plain = diff_get_color(ecb->color_diff,
+ DIFF_PLAIN);
+ emit_line_0(ecb->file, plain, reset, '\\',
+ nneof, strlen(nneof));
}
- if (!nl_just_seen)
- fprintf(file, "%s\n\\ No newline at end of file\n", reset);
}
static void emit_rewrite_diff(const char *name_a,
@@ -274,13 +430,12 @@ static void emit_rewrite_diff(const char *name_a,
const char *name_a_tab, *name_b_tab;
const char *metainfo = diff_get_color(color_diff, DIFF_METAINFO);
const char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO);
- const char *old = diff_get_color(color_diff, DIFF_FILE_OLD);
- const char *new = diff_get_color(color_diff, DIFF_FILE_NEW);
const char *reset = diff_get_color(color_diff, DIFF_RESET);
static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT;
const char *a_prefix, *b_prefix;
const char *data_one, *data_two;
size_t size_one, size_two;
+ struct emit_callback ecbdata;
if (diff_mnemonic_prefix && DIFF_OPT_TST(o, REVERSE_DIFF)) {
a_prefix = o->b_prefix;
@@ -321,6 +476,22 @@ static void emit_rewrite_diff(const char *name_a,
size_two = two->size;
}
+ memset(&ecbdata, 0, sizeof(ecbdata));
+ ecbdata.color_diff = color_diff;
+ ecbdata.found_changesp = &o->found_changes;
+ ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
+ ecbdata.file = o->file;
+ if (ecbdata.ws_rule & WS_BLANK_AT_EOF) {
+ mmfile_t mf1, mf2;
+ mf1.ptr = (char *)data_one;
+ mf2.ptr = (char *)data_two;
+ mf1.size = size_one;
+ mf2.size = size_two;
+ check_blank_at_eof(&mf1, &mf2, &ecbdata);
+ }
+ ecbdata.lno_in_preimage = 1;
+ ecbdata.lno_in_postimage = 1;
+
lc_a = count_lines(data_one, size_one);
lc_b = count_lines(data_two, size_two);
fprintf(o->file,
@@ -332,24 +503,9 @@ static void emit_rewrite_diff(const char *name_a,
print_line_count(o->file, lc_b);
fprintf(o->file, " @@%s\n", reset);
if (lc_a)
- copy_file_with_prefix(o->file, '-', data_one, size_one, old, reset);
+ emit_rewrite_lines(&ecbdata, '-', data_one, size_one);
if (lc_b)
- copy_file_with_prefix(o->file, '+', data_two, size_two, new, reset);
-}
-
-static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
-{
- if (!DIFF_FILE_VALID(one)) {
- mf->ptr = (char *)""; /* does not matter */
- mf->size = 0;
- return 0;
- }
- else if (diff_populate_filespec(one, 0))
- return -1;
-
- mf->ptr = one->data;
- mf->size = one->size;
- return 0;
+ emit_rewrite_lines(&ecbdata, '+', data_two, size_two);
}
struct diff_words_buffer {
@@ -529,18 +685,6 @@ static void diff_words_show(struct diff_words_data *diff_words)
diff_words->minus.text.size = diff_words->plus.text.size = 0;
}
-typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
-
-struct emit_callback {
- int nparents, color_diff;
- unsigned ws_rule;
- sane_truncate_fn truncate;
- const char **label_path;
- struct diff_words_data *diff_words;
- int *found_changesp;
- FILE *file;
-};
-
static void free_diff_words_data(struct emit_callback *ecbdata)
{
if (ecbdata->diff_words) {
@@ -566,42 +710,6 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix)
return "";
}
-static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len)
-{
- int has_trailing_newline, has_trailing_carriage_return;
-
- has_trailing_newline = (len > 0 && line[len-1] == '\n');
- if (has_trailing_newline)
- len--;
- has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
- if (has_trailing_carriage_return)
- len--;
-
- fputs(set, file);
- fwrite(line, len, 1, file);
- fputs(reset, file);
- if (has_trailing_carriage_return)
- fputc('\r', file);
- if (has_trailing_newline)
- fputc('\n', file);
-}
-
-static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
-{
- const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
- const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
-
- if (!*ws)
- emit_line(ecbdata->file, set, reset, line, len);
- else {
- /* Emit just the prefix, then the rest. */
- emit_line(ecbdata->file, set, reset, line, ecbdata->nparents);
- ws_check_emit(line + ecbdata->nparents,
- len - ecbdata->nparents, ecbdata->ws_rule,
- ecbdata->file, set, reset, ws);
- }
-}
-
static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len)
{
const char *cp;
@@ -620,10 +728,23 @@ static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, u
return allot - l;
}
+static void find_lno(const char *line, struct emit_callback *ecbdata)
+{
+ const char *p;
+ ecbdata->lno_in_preimage = 0;
+ ecbdata->lno_in_postimage = 0;
+ p = strchr(line, '-');
+ if (!p)
+ return; /* cannot happen */
+ ecbdata->lno_in_preimage = strtol(p + 1, NULL, 10);
+ p = strchr(p, '+');
+ if (!p)
+ return; /* cannot happen */
+ ecbdata->lno_in_postimage = strtol(p + 1, NULL, 10);
+}
+
static void fn_out_consume(void *priv, char *line, unsigned long len)
{
- int i;
- int color;
struct emit_callback *ecbdata = priv;
const char *meta = diff_get_color(ecbdata->color_diff, DIFF_METAINFO);
const char *plain = diff_get_color(ecbdata->color_diff, DIFF_PLAIN);
@@ -650,14 +771,9 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
len = 1;
}
- /* This is not really necessary for now because
- * this codepath only deals with two-way diffs.
- */
- for (i = 0; i < len && line[i] == '@'; i++)
- ;
- if (2 <= i && i < len && line[i] == ' ') {
- ecbdata->nparents = i - 1;
+ if (line[0] == '@') {
len = sane_truncate_line(ecbdata, line, len);
+ find_lno(line, ecbdata);
emit_line(ecbdata->file,
diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO),
reset, line, len);
@@ -666,15 +782,11 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
return;
}
- if (len < ecbdata->nparents) {
+ if (len < 1) {
emit_line(ecbdata->file, reset, reset, line, len);
return;
}
- color = DIFF_PLAIN;
- if (ecbdata->diff_words && ecbdata->nparents != 1)
- /* fall back to normal diff */
- free_diff_words_data(ecbdata);
if (ecbdata->diff_words) {
if (line[0] == '-') {
diff_words_append(line, len,
@@ -693,20 +805,19 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
emit_line(ecbdata->file, plain, reset, line, len);
return;
}
- for (i = 0; i < ecbdata->nparents && len; i++) {
- if (line[i] == '-')
- color = DIFF_FILE_OLD;
- else if (line[i] == '+')
- color = DIFF_FILE_NEW;
- }
- if (color != DIFF_FILE_NEW) {
- emit_line(ecbdata->file,
- diff_get_color(ecbdata->color_diff, color),
- reset, line, len);
- return;
+ if (line[0] != '+') {
+ const char *color =
+ diff_get_color(ecbdata->color_diff,
+ line[0] == '-' ? DIFF_FILE_OLD : DIFF_PLAIN);
+ ecbdata->lno_in_preimage++;
+ if (line[0] == ' ')
+ ecbdata->lno_in_postimage++;
+ emit_line(ecbdata->file, color, reset, line, len);
+ } else {
+ ecbdata->lno_in_postimage++;
+ emit_add_line(reset, ecbdata, line + 1, len - 1);
}
- emit_add_line(reset, ecbdata, line, len);
}
static char *pprint_rename(const char *a, const char *b)
@@ -999,7 +1110,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
total_files, adds, dels);
}
-static void show_shortstats(struct diffstat_t* data, struct diff_options *options)
+static void show_shortstats(struct diffstat_t *data, struct diff_options *options)
{
int i, adds = 0, dels = 0, total_files = data->nr;
@@ -1211,7 +1322,6 @@ struct checkdiff_t {
struct diff_options *o;
unsigned ws_rule;
unsigned status;
- int trailing_blanks_start;
};
static int is_conflict_marker(const char *line, unsigned long len)
@@ -1255,10 +1365,6 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len)
if (line[0] == '+') {
unsigned bad;
data->lineno++;
- if (!ws_blank_line(line + 1, len - 1, data->ws_rule))
- data->trailing_blanks_start = 0;
- else if (!data->trailing_blanks_start)
- data->trailing_blanks_start = data->lineno;
if (is_conflict_marker(line + 1, len - 1)) {
data->status |= 1;
fprintf(data->o->file,
@@ -1278,14 +1384,12 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len)
data->o->file, set, reset, ws);
} else if (line[0] == ' ') {
data->lineno++;
- data->trailing_blanks_start = 0;
} else if (line[0] == '@') {
char *plus = strchr(line, '+');
if (plus)
data->lineno = strtol(plus, NULL, 10) - 1;
else
die("invalid diff");
- data->trailing_blanks_start = 0;
}
}
@@ -1562,6 +1666,8 @@ static void builtin_diff(const char *name_a,
ecbdata.color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
ecbdata.found_changesp = &o->found_changes;
ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
+ if (ecbdata.ws_rule & WS_BLANK_AT_EOF)
+ check_blank_at_eof(&mf1, &mf2, &ecbdata);
ecbdata.file = o->file;
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
xecfg.ctxlen = o->context;
@@ -1704,11 +1810,22 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
&xpp, &xecfg, &ecb);
- if ((data.ws_rule & WS_TRAILING_SPACE) &&
- data.trailing_blanks_start) {
- fprintf(o->file, "%s:%d: ends with blank lines.\n",
- data.filename, data.trailing_blanks_start);
- data.status = 1; /* report errors */
+ if (data.ws_rule & WS_BLANK_AT_EOF) {
+ struct emit_callback ecbdata;
+ int blank_at_eof;
+
+ ecbdata.ws_rule = data.ws_rule;
+ check_blank_at_eof(&mf1, &mf2, &ecbdata);
+ blank_at_eof = ecbdata.blank_at_eof_in_preimage;
+
+ if (blank_at_eof) {
+ static char *err;
+ if (!err)
+ err = whitespace_error_string(WS_BLANK_AT_EOF);
+ fprintf(o->file, "%s:%d: %s.\n",
+ data.filename, blank_at_eof, err);
+ data.status = 1; /* report errors */
+ }
}
}
free_and_return:
diff --git a/fast-import.c b/fast-import.c
index 7ef9865aa6..6faaaacb68 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1744,10 +1744,12 @@ static int validate_raw_date(const char *src, char *result, int maxlen)
{
const char *orig_src = src;
char *endp;
+ unsigned long num;
errno = 0;
- strtoul(src, &endp, 10);
+ num = strtoul(src, &endp, 10);
+ /* NEEDSWORK: perhaps check for reasonable values? */
if (errno || endp == src || *endp != ' ')
return -1;
@@ -1755,8 +1757,9 @@ static int validate_raw_date(const char *src, char *result, int maxlen)
if (*src != '-' && *src != '+')
return -1;
- strtoul(src + 1, &endp, 10);
- if (errno || endp == src || *endp || (endp - orig_src) >= maxlen)
+ num = strtoul(src + 1, &endp, 10);
+ if (errno || endp == src + 1 || *endp || (endp - orig_src) >= maxlen ||
+ 1400 < num)
return -1;
strcpy(result, orig_src);
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 392efb913f..69aeaf03ec 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -259,7 +259,7 @@ sub list_modified {
@tracked = map {
chomp $_;
unquote_path($_);
- } run_cmd_pipe(qw(git ls-files --exclude-standard --), @ARGV);
+ } run_cmd_pipe(qw(git ls-files --), @ARGV);
return if (!@tracked);
}
diff --git a/git-am.sh b/git-am.sh
index 26ffe702e0..c132f50da5 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -205,7 +205,7 @@ check_patch_format () {
# and see if it looks like that they all begin with the
# header field names...
sed -n -e '/^$/q' -e '/^[ ]/d' -e p "$1" |
- egrep -v '^[A-Za-z]+(-[A-Za-z]+)*:' >/dev/null ||
+ LC_ALL=C egrep -v '^[!-9;-~]+:' >/dev/null ||
patch_format=mbox
fi
} < "$1" || clean_abort
diff --git a/git-compat-util.h b/git-compat-util.h
index 8d6e29cdea..ef60803384 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -176,8 +176,10 @@ extern char *gitbasename(char *);
#ifdef __GNUC__
#define NORETURN __attribute__((__noreturn__))
+#define NORETURN_PTR __attribute__((__noreturn__))
#else
#define NORETURN
+#define NORETURN_PTR
#ifndef __attribute__
#define __attribute__(x)
#endif
@@ -186,13 +188,13 @@ extern char *gitbasename(char *);
#include "compat/bswap.h"
/* General helper functions */
-extern void usage(const char *err) NORETURN;
-extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
-extern void die_errno(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
+extern NORETURN void usage(const char *err);
+extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
+extern NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
-extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
+extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
extern int prefixcmp(const char *str, const char *prefix);
extern time_t tm_to_time_t(const struct tm *tm);
diff --git a/git-instaweb.sh b/git-instaweb.sh
index d96eddbe56..622a5f0eb2 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -317,7 +317,21 @@ EOF
resolve_full_httpd
list_mods=$(echo "$full_httpd" | sed "s/-f$/-l/")
$list_mods | grep 'mod_cgi\.c' >/dev/null 2>&1 || \
- echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf"
+ if test -f "$module_path/mod_cgi.so"
+ then
+ echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf"
+ else
+ $list_mods | grep 'mod_cgid\.c' >/dev/null 2>&1 || \
+ if test -f "$module_path/mod_cgid.so"
+ then
+ echo "LoadModule cgid_module $module_path/mod_cgid.so" \
+ >> "$conf"
+ else
+ echo "You have no CGI support!"
+ exit 2
+ fi
+ echo "ScriptSock logs/gitweb.sock" >> "$conf"
+ fi
cat >> "$conf" <<EOF
AddHandler cgi-script .cgi
<Location /gitweb.cgi>
diff --git a/git-pull.sh b/git-pull.sh
index edf3ce33bf..fc78592ae0 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -90,8 +90,17 @@ error_on_no_merge_candidates () {
curr_branch=${curr_branch#refs/heads/}
upstream=$(git config "branch.$curr_branch.merge")
+ remote=$(git config "branch.$curr_branch.remote")
- if [ -z "$curr_branch" ]; then
+ if [ $# -gt 1 ]; then
+ echo "There are no candidates for merging in the refs that you just fetched."
+ echo "Generally this means that you provided a wildcard refspec which had no"
+ echo "matches on the remote end."
+ elif [ $# -gt 0 ] && [ "$1" != "$remote" ]; then
+ echo "You asked to pull from the remote '$1', but did not specify"
+ echo "a branch to merge. Because this is not the default configured remote"
+ echo "for your current branch, you must specify a branch on the command line."
+ elif [ -z "$curr_branch" ]; then
echo "You are not currently on a branch, so I cannot use any"
echo "'branch.<branchname>.merge' in your configuration file."
echo "Please specify which branch you want to merge on the command"
@@ -116,9 +125,8 @@ error_on_no_merge_candidates () {
echo
echo "See git-config(1) for details."
else
- echo "Your configuration specifies to merge the ref"
- echo "'${upstream#refs/heads/}' from the remote, but no such ref"
- echo "was fetched."
+ echo "Your configuration specifies to merge the ref '${upstream#refs/heads/}' from the"
+ echo "remote, but no such ref was fetched."
fi
exit 1
}
@@ -182,14 +190,7 @@ merge_head=$(sed -e '/ not-for-merge /d' \
case "$merge_head" in
'')
- case $? in
- 0) error_on_no_merge_candidates "$@";;
- 1) echo >&2 "You are not currently on a branch; you must explicitly"
- echo >&2 "specify which branch you wish to merge:"
- echo >&2 " git pull <remote> <branch>"
- exit 1;;
- *) exit $?;;
- esac
+ error_on_no_merge_candidates "$@"
;;
?*' '?*)
if test -z "$orig_head"
diff --git a/git-send-email.perl b/git-send-email.perl
index dd821f70cd..a0279de687 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -401,7 +401,7 @@ my %aliases;
my %parse_alias = (
# multiline formats can be supported in the future
mutt => sub { my $fh = shift; while (<$fh>) {
- if (/^\s*alias\s+(\S+)\s+(.*)$/) {
+ if (/^\s*alias\s+(?:-group\s+\S+\s+)*(\S+)\s+(.*)$/) {
my ($alias, $addr) = ($1, $2);
$addr =~ s/#.*$//; # mutt allows # comments
# commas delimit multiple addresses
@@ -835,7 +835,7 @@ sub send_message
$gitversion = Git::version();
}
- my $cc = join(", ", unique_email_list(@cc));
+ my $cc = join(",\n\t", unique_email_list(@cc));
my $ccline = "";
if ($cc ne '') {
$ccline = "\nCc: $cc";
@@ -976,7 +976,9 @@ X-Mailer: git-send-email $gitversion
if ($smtp_server !~ m#^/#) {
print "Server: $smtp_server\n";
print "MAIL FROM:<$raw_from>\n";
- print "RCPT TO:".join(',',(map { "<$_>" } @recipients))."\n";
+ foreach my $entry (@recipients) {
+ print "RCPT TO:<$entry>\n";
+ }
} else {
print "Sendmail: $smtp_server ".join(' ',@sendmail_parameters)."\n";
}
diff --git a/git-svn.perl b/git-svn.perl
index e0ec258e33..eb4b75aff3 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -603,8 +603,15 @@ sub cmd_dcommit {
"\nBefore dcommitting";
}
if ($url_ ne $expect_url) {
- fatal "URL mismatch after rebase: ",
- "$url_ != $expect_url";
+ if ($url_ eq $gs->metadata_url) {
+ print
+ "Accepting rewritten URL:",
+ " $url_\n";
+ } else {
+ fatal
+ "URL mismatch after rebase:",
+ " $url_ != $expect_url";
+ }
}
if ($uuid_ ne $uuid) {
fatal "uuid mismatch after rebase: ",
@@ -2626,7 +2633,8 @@ sub find_parent_branch {
my $url = $self->ra->{url};
my $new_url = $url . $branch_from;
print STDERR "Found possible branch point: ",
- "$new_url => ", $self->full_url, ", $r\n";
+ "$new_url => ", $self->full_url, ", $r\n"
+ unless $::_q > 1;
$branch_from =~ s#^/##;
my $gs = $self->other_gs($new_url, $url,
$branch_from, $r, $self->{ref_id});
@@ -2647,11 +2655,13 @@ sub find_parent_branch {
($r0, $parent) = $gs->find_rev_before($r, 1);
}
if (defined $r0 && defined $parent) {
- print STDERR "Found branch parent: ($self->{ref_id}) $parent\n";
+ print STDERR "Found branch parent: ($self->{ref_id}) $parent\n"
+ unless $::_q > 1;
my $ed;
if ($self->ra->can_do_switch) {
$self->assert_index_clean($parent);
- print STDERR "Following parent with do_switch\n";
+ print STDERR "Following parent with do_switch\n"
+ unless $::_q > 1;
# do_switch works with svn/trunk >= r22312, but that
# is not included with SVN 1.4.3 (the latest version
# at the moment), so we can't rely on it
@@ -2666,18 +2676,20 @@ sub find_parent_branch {
print STDERR "Trees match:\n",
" $new_url\@$r0\n",
" ${\$self->full_url}\@$rev\n",
- "Following parent with no changes\n";
+ "Following parent with no changes\n"
+ unless $::_q > 1;
$self->tmp_index_do(sub {
command_noisy('read-tree', $parent);
});
$self->{last_commit} = $parent;
} else {
- print STDERR "Following parent with do_update\n";
+ print STDERR "Following parent with do_update\n"
+ unless $::_q > 1;
$ed = SVN::Git::Fetcher->new($self);
$self->ra->gs_do_update($rev, $rev, $self, $ed)
or die "SVN connection failed somewhere...\n";
}
- print STDERR "Successfully followed parent\n";
+ print STDERR "Successfully followed parent\n" unless $::_q > 1;
return $self->make_log_entry($rev, [$parent], $ed);
}
return undef;
@@ -2822,7 +2834,7 @@ sub other_gs {
$ref_id .= "\@$r";
# just grow a tail if we're not unique enough :x
$ref_id .= '-' while find_ref($ref_id);
- print STDERR "Initializing parent: $ref_id\n";
+ print STDERR "Initializing parent: $ref_id\n" unless $::_q > 1;
my ($u, $p, $repo_id) = ($new_url, '', $ref_id);
if ($u =~ s#^\Q$url\E(/|$)##) {
$p = $u;
diff --git a/git.c b/git.c
index 9883009b5d..bd2c5fe77b 100644
--- a/git.c
+++ b/git.c
@@ -6,7 +6,7 @@
const char git_usage_string[] =
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n"
- " [-p|--paginate|--no-pager]\n"
+ " [-p|--paginate|--no-pager] [--no-replace-objects]\n"
" [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n"
" [--help] COMMAND [ARGS]";
@@ -87,6 +87,8 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
use_pager = 0;
if (envchanged)
*envchanged = 1;
+ } else if (!strcmp(cmd, "--no-replace-objects")) {
+ read_replace_refs = 0;
} else if (!strcmp(cmd, "--git-dir")) {
if (*argc < 2) {
fprintf(stderr, "No directory given for --git-dir.\n" );
diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index 8f68fe3091..d60bfc1f64 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -341,6 +341,12 @@ td.mode {
font-family: monospace;
}
+/* format of (optional) objects size in 'tree' view */
+td.size {
+ font-family: monospace;
+ text-align: right;
+}
+
/* styling of diffs (patchsets): commitdiff and blobdiff views */
div.diff.header,
div.diff.extended_header {
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 24b219310a..d6eb7291d6 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -297,6 +297,19 @@ our %feature = (
'override' => 0,
'default' => [1]},
+ # Enable showing size of blobs in a 'tree' view, in a separate
+ # column, similar to what 'ls -l' does. This cost a bit of IO.
+
+ # To disable system wide have in $GITWEB_CONFIG
+ # $feature{'show-sizes'}{'default'} = [0];
+ # To have project specific config enable override in $GITWEB_CONFIG
+ # $feature{'show-sizes'}{'override'} = 1;
+ # and in project config gitweb.showsizes = 0|1;
+ 'show-sizes' => {
+ 'sub' => sub { feature_bool('showsizes', @_) },
+ 'override' => 0,
+ 'default' => [1]},
+
# Make gitweb use an alternative format of the URLs which can be
# more readable and natural-looking: project name is embedded
# directly in the path and the query string contains other
@@ -2764,16 +2777,31 @@ sub parse_ls_tree_line {
my %opts = @_;
my %res;
- #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
- $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/s;
+ if ($opts{'-l'}) {
+ #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa 16717 panic.c'
+ $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40}) +(-|[0-9]+)\t(.+)$/s;
- $res{'mode'} = $1;
- $res{'type'} = $2;
- $res{'hash'} = $3;
- if ($opts{'-z'}) {
- $res{'name'} = $4;
+ $res{'mode'} = $1;
+ $res{'type'} = $2;
+ $res{'hash'} = $3;
+ $res{'size'} = $4;
+ if ($opts{'-z'}) {
+ $res{'name'} = $5;
+ } else {
+ $res{'name'} = unquote($5);
+ }
} else {
- $res{'name'} = unquote($4);
+ #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
+ $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/s;
+
+ $res{'mode'} = $1;
+ $res{'type'} = $2;
+ $res{'hash'} = $3;
+ if ($opts{'-z'}) {
+ $res{'name'} = $4;
+ } else {
+ $res{'name'} = unquote($4);
+ }
}
return wantarray ? %res : \%res;
@@ -3564,6 +3592,9 @@ sub git_print_tree_entry {
# and link is the action links of the entry.
print "<td class=\"mode\">" . mode_str($t->{'mode'}) . "</td>\n";
+ if (exists $t->{'size'}) {
+ print "<td class=\"size\">$t->{'size'}</td>\n";
+ }
if ($t->{'type'} eq "blob") {
print "<td class=\"list\">" .
$cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
@@ -3609,12 +3640,14 @@ sub git_print_tree_entry {
} elsif ($t->{'type'} eq "tree") {
print "<td class=\"list\">";
print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key)},
+ file_name=>"$basedir$t->{'name'}",
+ %base_key)},
esc_path($t->{'name'}));
print "</td>\n";
print "<td class=\"link\">";
print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key)},
+ file_name=>"$basedir$t->{'name'}",
+ %base_key)},
"tree");
if (defined $hash_base) {
print " | " .
@@ -5088,10 +5121,14 @@ sub git_tree {
}
die_error(404, "No such tree") unless defined($hash);
+ my $show_sizes = gitweb_check_feature('show-sizes');
+ my $have_blame = gitweb_check_feature('blame');
+
my @entries = ();
{
local $/ = "\0";
- open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash
+ open my $fd, "-|", git_cmd(), "ls-tree", '-z',
+ ($show_sizes ? '-l' : ()), @extra_options, $hash
or die_error(500, "Open git-ls-tree failed");
@entries = map { chomp; $_ } <$fd>;
close $fd
@@ -5102,7 +5139,6 @@ sub git_tree {
my $ref = format_ref_marker($refs, $hash_base);
git_header_html();
my $basedir = '';
- my $have_blame = gitweb_check_feature('blame');
if (defined $hash_base && (my %co = parse_commit($hash_base))) {
my @views_nav = ();
if (defined $file_name) {
@@ -5118,7 +5154,8 @@ sub git_tree {
# FIXME: Should be available when we have no hash base as well.
push @views_nav, $snapshot_links;
}
- git_print_page_nav('tree','', $hash_base, undef, undef, join(' | ', @views_nav));
+ git_print_page_nav('tree','', $hash_base, undef, undef,
+ join(' | ', @views_nav));
git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);
} else {
undef $hash_base;
@@ -5151,8 +5188,10 @@ sub git_tree {
undef $up unless $up;
# based on git_print_tree_entry
print '<td class="mode">' . mode_str('040000') . "</td>\n";
+ print '<td class="size">&nbsp;</td>'."\n" if $show_sizes;
print '<td class="list">';
- print $cgi->a({-href => href(action=>"tree", hash_base=>$hash_base,
+ print $cgi->a({-href => href(action=>"tree",
+ hash_base=>$hash_base,
file_name=>$up)},
"..");
print "</td>\n";
@@ -5161,7 +5200,7 @@ sub git_tree {
print "</tr>\n";
}
foreach my $line (@entries) {
- my %t = parse_ls_tree_line($line, -z => 1);
+ my %t = parse_ls_tree_line($line, -z => 1, -l => $show_sizes);
if ($alternate) {
print "<tr class=\"dark\">\n";
@@ -5328,7 +5367,7 @@ sub git_commit {
} @$parents ) .
')';
}
- if (gitweb_check_feature('patches')) {
+ if (gitweb_check_feature('patches') && @$parents <= 1) {
$formats_nav .= " | " .
$cgi->a({-href => href(action=>"patch", -replay=>1)},
"patch");
@@ -5616,7 +5655,7 @@ sub git_commitdiff {
$formats_nav =
$cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)},
"raw");
- if ($patch_max) {
+ if ($patch_max && @{$co{'parents'}} <= 1) {
$formats_nav .= " | " .
$cgi->a({-href => href(action=>"patch", -replay=>1)},
"patch");
@@ -5824,7 +5863,7 @@ sub git_commitdiff_plain {
# format-patch-style patches
sub git_patch {
- git_commitdiff(-format => 'patch', -single=> 1);
+ git_commitdiff(-format => 'patch', -single => 1);
}
sub git_patches {
diff --git a/index-pack.c b/index-pack.c
index 340074fc79..b4f8278659 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -206,8 +206,8 @@ static void parse_pack_header(void)
use(sizeof(struct pack_header));
}
-static void bad_object(unsigned long offset, const char *format,
- ...) NORETURN __attribute__((format (printf, 2, 3)));
+static NORETURN void bad_object(unsigned long offset, const char *format,
+ ...) __attribute__((format (printf, 2, 3)));
static void bad_object(unsigned long offset, const char *format, ...)
{
diff --git a/log-tree.c b/log-tree.c
index 1c9eefee33..f7d54f2f1b 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -43,6 +43,7 @@ void load_ref_decorations(int flags)
if (!loaded) {
loaded = 1;
for_each_ref(add_ref_decoration, &flags);
+ head_ref(add_ref_decoration, &flags);
}
}
@@ -390,7 +391,9 @@ void show_log(struct rev_info *opt)
*/
show_reflog_message(opt->reflog_info,
opt->commit_format == CMIT_FMT_ONELINE,
- opt->date_mode);
+ opt->date_mode_explicit ?
+ opt->date_mode :
+ DATE_NORMAL);
if (opt->commit_format == CMIT_FMT_ONELINE)
return;
}
diff --git a/pretty.c b/pretty.c
index f5983f8baa..587101f846 100644
--- a/pretty.c
+++ b/pretty.c
@@ -740,7 +740,7 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
}
void format_commit_message(const struct commit *commit,
- const void *format, struct strbuf *sb,
+ const char *format, struct strbuf *sb,
enum date_mode dmode)
{
struct format_commit_context context;
diff --git a/progress.c b/progress.c
index 132ed95a3d..3971f49f4d 100644
--- a/progress.c
+++ b/progress.c
@@ -131,7 +131,13 @@ static void throughput_string(struct throughput *tp, off_t total,
} else {
l -= snprintf(tp->display, l, ", %u bytes", (int)total);
}
- if (rate)
+
+ if (rate > 1 << 10) {
+ int x = rate + 5; /* for rounding */
+ snprintf(tp->display + sizeof(tp->display) - l, l,
+ " | %u.%2.2u MiB/s",
+ x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10);
+ } else if (rate)
snprintf(tp->display + sizeof(tp->display) - l, l,
" | %u KiB/s", rate);
}
diff --git a/remote-curl.c b/remote-curl.c
index ad6a1637b5..2faf1c6344 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -3,6 +3,7 @@
#include "strbuf.h"
#include "walker.h"
#include "http.h"
+#include "exec_cmd.h"
static struct ref *get_refs(struct walker *walker, const char *url)
{
@@ -82,6 +83,7 @@ int main(int argc, const char **argv)
const char *url;
struct walker *walker = NULL;
+ git_extract_argv0_path(argv[0]);
setup_git_directory();
if (argc < 2) {
fprintf(stderr, "Remote needed\n");
diff --git a/revision.c b/revision.c
index 35eca4a361..9fc4e8d381 100644
--- a/revision.c
+++ b/revision.c
@@ -1159,8 +1159,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->simplify_history = 0;
} else if (!strcmp(arg, "--relative-date")) {
revs->date_mode = DATE_RELATIVE;
+ revs->date_mode_explicit = 1;
} else if (!strncmp(arg, "--date=", 7)) {
revs->date_mode = parse_date_format(arg + 7);
+ revs->date_mode_explicit = 1;
} else if (!strcmp(arg, "--log-size")) {
revs->show_log_size = 1;
}
diff --git a/revision.h b/revision.h
index 9d0dddbcbc..b6421a6432 100644
--- a/revision.h
+++ b/revision.h
@@ -81,7 +81,8 @@ struct rev_info {
show_merge:1,
abbrev_commit:1,
use_terminator:1,
- missing_newline:1;
+ missing_newline:1,
+ date_mode_explicit:1;
enum date_mode date_mode;
unsigned int abbrev;
diff --git a/sha1_file.c b/sha1_file.c
index 4ea0b18d0a..4cc8939e4b 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1357,6 +1357,8 @@ unsigned long get_size_from_delta(struct packed_git *p,
in = use_pack(p, w_curs, curpos, &stream.avail_in);
stream.next_in = in;
st = git_inflate(&stream, Z_FINISH);
+ if (st == Z_BUF_ERROR && (stream.avail_in || !stream.avail_out))
+ break;
curpos += stream.next_in - in;
} while ((st == Z_OK || st == Z_BUF_ERROR) &&
stream.total_out < sizeof(delta_head));
@@ -1594,6 +1596,8 @@ static void *unpack_compressed_entry(struct packed_git *p,
in = use_pack(p, w_curs, curpos, &stream.avail_in);
stream.next_in = in;
st = git_inflate(&stream, Z_FINISH);
+ if (st == Z_BUF_ERROR && (stream.avail_in || !stream.avail_out))
+ break;
curpos += stream.next_in - in;
} while (st == Z_OK || st == Z_BUF_ERROR);
git_inflate_end(&stream);
diff --git a/t/t3003-ls-files-exclude.sh b/t/t3003-ls-files-exclude.sh
new file mode 100755
index 0000000000..fc1e379321
--- /dev/null
+++ b/t/t3003-ls-files-exclude.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+test_description='ls-files --exclude does not affect index files'
+. ./test-lib.sh
+
+test_expect_success 'create repo with file' '
+ echo content >file &&
+ git add file &&
+ git commit -m file &&
+ echo modification >file
+'
+
+check_output() {
+test_expect_success "ls-files output contains file ($1)" "
+ echo '$2' >expect &&
+ git ls-files --exclude-standard --$1 >output &&
+ test_cmp expect output
+"
+}
+
+check_all_output() {
+ check_output 'cached' 'file'
+ check_output 'modified' 'file'
+}
+
+check_all_output
+test_expect_success 'add file to gitignore' '
+ echo file >.gitignore
+'
+check_all_output
+
+test_done
diff --git a/t/t3202-show-branch-octopus.sh b/t/t3202-show-branch-octopus.sh
index 7fe4a6ecb0..0a5d5e669f 100755
--- a/t/t3202-show-branch-octopus.sh
+++ b/t/t3202-show-branch-octopus.sh
@@ -56,4 +56,12 @@ test_expect_success 'show-branch with more than 8 branches' '
'
+test_expect_success 'show-branch with showbranch.default' '
+ for i in $numbers; do
+ git config --add showbranch.default branch$i
+ done &&
+ git show-branch >out &&
+ test_cmp expect out
+'
+
test_done
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 62fd65e18d..687bd7ab53 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -138,6 +138,20 @@ test_expect_success 'real edit works' '
test_cmp expected output
'
+test_expect_success 'skip files similarly as commit -a' '
+ git reset &&
+ echo file >.gitignore &&
+ echo changed >file &&
+ echo y | git add -p file &&
+ git diff >output &&
+ git reset &&
+ git commit -am commit &&
+ git diff >expected &&
+ test_cmp expected output &&
+ git reset --hard HEAD^
+'
+rm -f .gitignore
+
if test "$(git config --bool core.filemode)" = false
then
say 'skipping filemode tests (filesystem does not properly support modes)'
diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all
index 903d9d9659..d155e0bab2 100644
--- a/t/t4013/diff.log_--decorate=full_--all
+++ b/t/t4013/diff.log_--decorate=full_--all
@@ -1,5 +1,5 @@
$ git log --decorate=full --all
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (refs/heads/master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD, refs/heads/master)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all
index 954210ea90..fd7c3e6439 100644
--- a/t/t4013/diff.log_--decorate_--all
+++ b/t/t4013/diff.log_--decorate_--all
@@ -1,5 +1,5 @@
$ git log --decorate --all
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD, master)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index 6d13da30da..8dd147d78f 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -362,10 +362,17 @@ test_expect_success 'line numbers in --check output are correct' '
'
-test_expect_success 'checkdiff detects trailing blank lines' '
+test_expect_success 'checkdiff detects new trailing blank lines (1)' '
echo "foo();" >x &&
echo "" >>x &&
- git diff --check | grep "ends with blank"
+ git diff --check | grep "new blank line"
+'
+
+test_expect_success 'checkdiff detects new trailing blank lines (2)' '
+ { echo a; echo b; echo; echo; } >x &&
+ git add x &&
+ { echo a; echo; echo; echo; echo; } >x &&
+ git diff --check | grep "new blank line"
'
test_expect_success 'checkdiff allows new blank lines' '
diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh
index 84a1fe3115..3a3663fbcb 100755
--- a/t/t4019-diff-wserror.sh
+++ b/t/t4019-diff-wserror.sh
@@ -165,7 +165,7 @@ test_expect_success 'trailing empty lines (1)' '
rm -f .gitattributes &&
test_must_fail git diff --check >output &&
- grep "ends with blank lines." output &&
+ grep "new blank line at" output &&
grep "trailing whitespace" output
'
@@ -190,4 +190,13 @@ test_expect_success 'do not color trailing cr in context' '
'
+test_expect_success 'color new trailing blank lines' '
+ { echo a; echo b; echo; echo; } >x &&
+ git add x &&
+ { echo a; echo; echo; echo; echo c; echo; echo; echo; echo; } >x &&
+ git diff --color x >output &&
+ cnt=$(grep "${blue_grep}" output | wc -l) &&
+ test $cnt = 2
+'
+
test_done
diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh
index fac2093d7f..ca26397590 100755
--- a/t/t4124-apply-ws-rule.sh
+++ b/t/t4124-apply-ws-rule.sh
@@ -170,4 +170,95 @@ test_expect_success 'trailing whitespace & no newline at the end of file' '
grep "^$" target
'
+test_expect_success 'blank at EOF with --whitespace=fix (1)' '
+ : these can fail depending on what we did before
+ git config --unset core.whitespace
+ rm -f .gitattributes
+
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+ { echo a; echo b; echo c; } >expect &&
+ { cat expect; echo; } >one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=fix patch &&
+ test_cmp expect one
+'
+
+test_expect_success 'blank at EOF with --whitespace=fix (2)' '
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+ { echo a; echo c; } >expect &&
+ { cat expect; echo; echo; } >one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=fix patch &&
+ test_cmp expect one
+'
+
+test_expect_success 'blank at EOF with --whitespace=fix (3)' '
+ { echo a; echo b; echo; } >one &&
+ git add one &&
+ { echo a; echo c; echo; } >expect &&
+ { cat expect; echo; echo; } >one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=fix patch &&
+ test_cmp expect one
+'
+
+test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' '
+ { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one &&
+ git add one &&
+ { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect &&
+ cp expect one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=fix patch &&
+ test_cmp expect one
+'
+
+test_expect_success 'blank at EOF with --whitespace=warn' '
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+ echo >>one &&
+ cat one >expect &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=warn patch 2>error &&
+ test_cmp expect one &&
+ grep "new blank line at EOF" error
+'
+
+test_expect_success 'blank at EOF with --whitespace=error' '
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+ cat one >expect &&
+ echo >>one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ test_must_fail git apply --whitespace=error patch 2>error &&
+ test_cmp expect one &&
+ grep "new blank line at EOF" error
+'
+
+test_expect_success 'blank but not empty at EOF' '
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+ echo " " >>one &&
+ cat one >expect &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=warn patch 2>error &&
+ test_cmp expect one &&
+ grep "new blank line at EOF" error
+'
+
test_done
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index 5f84b18fa5..0037f63d91 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -230,4 +230,16 @@ test_expect_success \
'git archive --list outside of a git repo' \
'GIT_DIR=some/non-existing/directory git archive --list'
+test_expect_success 'git-archive --prefix=olde-' '
+ git archive --prefix=olde- >h.tar HEAD &&
+ (
+ mkdir h &&
+ cd h &&
+ "$TAR" xf - <../h.tar
+ ) &&
+ test -d h/olde-a &&
+ test -d h/olde-a/bin &&
+ test -f h/olde-a/bin/sh
+'
+
test_done
diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh
index 5132d41309..5f6cd4f333 100755
--- a/t/t5303-pack-corruption-resilience.sh
+++ b/t/t5303-pack-corruption-resilience.sh
@@ -275,4 +275,13 @@ test_expect_success \
git cat-file blob $blob_2 > /dev/null &&
git cat-file blob $blob_3 > /dev/null'
+test_expect_success \
+ 'corrupting header to have too small output buffer fails unpack' \
+ 'create_new_pack &&
+ git prune-packed &&
+ printf "\262\001" | do_corrupt_object $blob_1 0 &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null'
+
test_done
diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh
index 8b8bd81c09..d4818b430a 100755
--- a/t/t6050-replace.sh
+++ b/t/t6050-replace.sh
@@ -70,6 +70,13 @@ test_expect_success 'replace the author' '
git show $HASH2 | grep "O Thor"
'
+test_expect_success 'test --no-replace-objects option' '
+ git cat-file commit $HASH2 | grep "author O Thor" &&
+ git --no-replace-objects cat-file commit $HASH2 | grep "author A U Thor" &&
+ git show $HASH2 | grep "O Thor" &&
+ git --no-replace-objects show $HASH2 | grep "A U Thor"
+'
+
cat >tag.sig <<EOF
object $HASH2
type commit
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index ae56a36eac..ae5290ab43 100755
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
@@ -213,6 +213,72 @@ test_expect_success 'grep -e A --and --not -e B' '
test_cmp expected actual
'
+test_expect_success 'grep -f, non-existent file' '
+ test_must_fail git grep -f patterns
+'
+
+cat >expected <<EOF
+file:foo mmap bar
+file:foo_mmap bar
+file:foo_mmap bar mmap
+file:foo mmap bar_mmap
+file:foo_mmap bar mmap baz
+EOF
+
+cat >pattern <<EOF
+mmap
+EOF
+
+test_expect_success 'grep -f, one pattern' '
+ git grep -f pattern >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+file:foo mmap bar
+file:foo_mmap bar
+file:foo_mmap bar mmap
+file:foo mmap bar_mmap
+file:foo_mmap bar mmap baz
+t/a/v:vvv
+t/v:vvv
+v:vvv
+EOF
+
+cat >patterns <<EOF
+mmap
+vvv
+EOF
+
+test_expect_success 'grep -f, multiple patterns' '
+ git grep -f patterns >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+file:foo mmap bar
+file:foo_mmap bar
+file:foo_mmap bar mmap
+file:foo mmap bar_mmap
+file:foo_mmap bar mmap baz
+t/a/v:vvv
+t/v:vvv
+v:vvv
+EOF
+
+cat >patterns <<EOF
+
+mmap
+
+vvv
+
+EOF
+
+test_expect_success 'grep -f, ignore empty lines' '
+ git grep -f patterns >actual &&
+ test_cmp expected actual
+'
+
cat >expected <<EOF
y:y yy
--
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index fb606a9f05..84a7f03d46 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -103,10 +103,18 @@ cat >expected-show-all-headers <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<bcc@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<cc@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<bcc@example.com>
From: Example <from@example.com>
To: to@example.com
-Cc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.com
+Cc: cc@example.com,
+ A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -164,7 +172,7 @@ test_expect_success 'cccmd works' '
--smtp-server="$(pwd)/fake.sendmail" \
cccmd.patch \
&&
- grep ^Cc:.*cccmd@example.com msgtxt1
+ grep "^ cccmd@example.com" msgtxt1
'
z8=zzzzzzzz
@@ -278,10 +286,17 @@ cat >expected-suppress-sob <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<cc@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
From: Example <from@example.com>
To: to@example.com
-Cc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.com
+Cc: cc@example.com,
+ A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -318,10 +333,15 @@ cat >expected-suppress-sob <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
From: Example <from@example.com>
To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -344,10 +364,17 @@ cat >expected-suppress-cccmd <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<committer@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<committer@example.com>
From: Example <from@example.com>
To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com, C O Mitter <committer@example.com>
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com,
+ C O Mitter <committer@example.com>
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -392,10 +419,17 @@ cat >expected-suppress-body <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<cc-cmd@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<cc-cmd@example.com>
From: Example <from@example.com>
To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com, cc-cmd@example.com
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com,
+ cc-cmd@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -416,10 +450,15 @@ cat >expected-suppress-body-cccmd <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
From: Example <from@example.com>
To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -440,10 +479,15 @@ cat >expected-suppress-sob <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
From: Example <from@example.com>
To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -466,10 +510,17 @@ cat >expected-suppress-bodycc <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<committer@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<committer@example.com>
From: Example <from@example.com>
To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com, C O Mitter <committer@example.com>
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com,
+ C O Mitter <committer@example.com>
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -489,10 +540,13 @@ cat >expected-suppress-cc <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<committer@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<committer@example.com>
From: Example <from@example.com>
To: to@example.com
-Cc: A <author@example.com>, C O Mitter <committer@example.com>
+Cc: A <author@example.com>,
+ C O Mitter <committer@example.com>
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -605,7 +659,7 @@ test_expect_success 'utf8 Cc is rfc2047 encoded' '
--to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
outdir/*.patch &&
- grep "^Cc:" msgtxt1 |
+ grep "^ " msgtxt1 |
grep "=?UTF-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>"
'
diff --git a/usage.c b/usage.c
index b6aea45280..c488f3afcd 100644
--- a/usage.c
+++ b/usage.c
@@ -36,12 +36,12 @@ static void warn_builtin(const char *warn, va_list params)
/* If we are in a dlopen()ed .so write to a global variable would segfault
* (ugh), so keep things static. */
-static void (*usage_routine)(const char *err) NORETURN = usage_builtin;
-static void (*die_routine)(const char *err, va_list params) NORETURN = die_builtin;
+static NORETURN_PTR void (*usage_routine)(const char *err) = usage_builtin;
+static NORETURN_PTR void (*die_routine)(const char *err, va_list params) = die_builtin;
static void (*error_routine)(const char *err, va_list params) = error_builtin;
static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
-void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN)
+void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params))
{
die_routine = routine;
}
diff --git a/ws.c b/ws.c
index 59d0883c1f..760b5743fa 100644
--- a/ws.c
+++ b/ws.c
@@ -16,6 +16,8 @@ static struct whitespace_rule {
{ "space-before-tab", WS_SPACE_BEFORE_TAB, 0 },
{ "indent-with-non-tab", WS_INDENT_WITH_NON_TAB, 0 },
{ "cr-at-eol", WS_CR_AT_EOL, 1 },
+ { "blank-at-eol", WS_BLANK_AT_EOL, 0 },
+ { "blank-at-eof", WS_BLANK_AT_EOF, 0 },
};
unsigned parse_whitespace_rule(const char *string)
@@ -102,8 +104,17 @@ unsigned whitespace_rule(const char *pathname)
char *whitespace_error_string(unsigned ws)
{
struct strbuf err = STRBUF_INIT;
- if (ws & WS_TRAILING_SPACE)
+ if ((ws & WS_TRAILING_SPACE) == WS_TRAILING_SPACE)
strbuf_addstr(&err, "trailing whitespace");
+ else {
+ if (ws & WS_BLANK_AT_EOL)
+ strbuf_addstr(&err, "trailing whitespace");
+ if (ws & WS_BLANK_AT_EOF) {
+ if (err.len)
+ strbuf_addstr(&err, ", ");
+ strbuf_addstr(&err, "new blank line at EOF");
+ }
+ }
if (ws & WS_SPACE_BEFORE_TAB) {
if (err.len)
strbuf_addstr(&err, ", ");
@@ -141,11 +152,11 @@ static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule,
}
/* Check for trailing whitespace. */
- if (ws_rule & WS_TRAILING_SPACE) {
+ if (ws_rule & WS_BLANK_AT_EOL) {
for (i = len - 1; i >= 0; i--) {
if (isspace(line[i])) {
trailing_whitespace = i;
- result |= WS_TRAILING_SPACE;
+ result |= WS_BLANK_AT_EOL;
}
else
break;
@@ -261,7 +272,7 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
/*
* Strip trailing whitespace
*/
- if (ws_rule & WS_TRAILING_SPACE) {
+ if (ws_rule & WS_BLANK_AT_EOL) {
if (0 < len && src[len - 1] == '\n') {
add_nl_to_tail = 1;
len--;