summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--Documentation/RelNotes/1.8.1.2.txt13
-rw-r--r--Documentation/RelNotes/1.8.2.txt261
-rw-r--r--Documentation/config.txt49
-rw-r--r--Documentation/git-commit-tree.txt4
-rw-r--r--Documentation/git-commit.txt4
-rw-r--r--Documentation/git-cvsimport.txt6
-rw-r--r--Documentation/git-for-each-ref.txt2
-rw-r--r--Documentation/git-format-patch.txt11
-rw-r--r--Documentation/git-log.txt7
-rw-r--r--Documentation/git-push.txt9
-rw-r--r--Documentation/git-remote-testgit.txt2
-rw-r--r--Documentation/git-submodule.txt25
-rw-r--r--Documentation/git-svn.txt10
-rw-r--r--Documentation/git.txt15
-rw-r--r--Documentation/gitignore.txt19
-rw-r--r--Documentation/gitmodules.txt5
-rw-r--r--Documentation/mailmap.txt3
-rw-r--r--Documentation/pretty-formats.txt6
-rw-r--r--Documentation/technical/api-directory-listing.txt21
-rw-r--r--Documentation/technical/api-string-list.txt8
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile578
l---------RelNotes2
-rw-r--r--abspath.c105
-rw-r--r--advice.c9
-rw-r--r--advice.h3
-rw-r--r--archive-zip.c7
-rw-r--r--attr.c4
-rw-r--r--builtin/add.c2
-rw-r--r--builtin/blame.c189
-rw-r--r--builtin/branch.c2
-rw-r--r--builtin/clean.c154
-rw-r--r--builtin/clone.c2
-rw-r--r--builtin/commit.c4
-rw-r--r--builtin/fast-export.c27
-rw-r--r--builtin/log.c85
-rw-r--r--builtin/ls-files.c4
-rw-r--r--builtin/ls-tree.c2
-rw-r--r--builtin/merge-index.c4
-rw-r--r--builtin/merge-tree.c92
-rw-r--r--builtin/push.c32
-rw-r--r--builtin/send-pack.c9
-rw-r--r--builtin/shortlog.c54
-rw-r--r--cache.h22
-rw-r--r--commit.h2
-rw-r--r--compat/fnmatch/fnmatch.c3
-rw-r--r--config.c3
-rw-r--r--config.mak.uname539
-rw-r--r--configure.ac14
-rwxr-xr-xcontrib/ciabot/ciabot.py8
-rw-r--r--contrib/completion/git-completion.bash2
-rw-r--r--contrib/completion/git-completion.tcsh33
-rwxr-xr-xcontrib/fast-import/import-zips.py7
-rwxr-xr-xcontrib/hg-to-git/hg-to-git.py5
-rw-r--r--contrib/p4import/git-p4import.py5
-rwxr-xr-xcontrib/remote-helpers/git-remote-bzr725
-rwxr-xr-xcontrib/remote-helpers/git-remote-hg13
-rwxr-xr-xcontrib/remote-helpers/test-bzr.sh143
-rwxr-xr-xcontrib/remote-helpers/test-hg-hg-git.sh68
-rwxr-xr-xcontrib/svn-fe/svnrdump_sim.py4
-rw-r--r--contrib/vim/README16
-rw-r--r--ctype.c15
-rw-r--r--diff.c2
-rw-r--r--dir.c314
-rw-r--r--dir.h54
-rw-r--r--fetch-pack.c3
-rw-r--r--fsck.c15
-rw-r--r--git-compat-util.h33
-rwxr-xr-xgit-p4.py8
-rw-r--r--git-rebase--am.sh49
-rw-r--r--git-rebase--interactive.sh7
-rwxr-xr-xgit-remote-testgit90
-rw-r--r--git-remote-testpy.py (renamed from git-remote-testgit.py)15
-rwxr-xr-xgit-send-email.perl10
-rwxr-xr-xgit-submodule.sh51
-rwxr-xr-xgit-svn.perl12
-rw-r--r--git.c8
-rw-r--r--git_remote_helpers/git/__init__.py5
-rw-r--r--git_remote_helpers/git/importer.py2
-rw-r--r--http-push.c23
-rw-r--r--imap-send.c157
-rw-r--r--log-tree.c54
-rw-r--r--log-tree.h4
-rw-r--r--mailmap.c246
-rw-r--r--mailmap.h4
-rw-r--r--merge-blobs.c (renamed from merge-file.c)4
-rw-r--r--merge-blobs.h8
-rw-r--r--merge-file.h7
-rw-r--r--merge-recursive.c6
-rw-r--r--mergetools/p4merge27
-rw-r--r--parse-options.c18
-rw-r--r--parse-options.h4
-rw-r--r--path.c46
-rw-r--r--perl/Git/SVN/Editor.pm7
-rw-r--r--perl/Git/SVN/Utils.pm2
-rw-r--r--po/de.po484
-rw-r--r--pretty.c133
-rw-r--r--remote.c83
-rw-r--r--revision.c54
-rw-r--r--revision.h2
-rw-r--r--send-pack.c1
-rw-r--r--sequencer.c20
-rw-r--r--setup.c34
-rw-r--r--strbuf.c26
-rw-r--r--strbuf.h6
-rw-r--r--string-list.c37
-rw-r--r--string-list.h13
-rw-r--r--t/Makefile8
-rwxr-xr-xt/check-non-portable-shell.pl27
-rwxr-xr-xt/t0000-basic.sh214
-rwxr-xr-xt/t0003-attributes.sh37
-rwxr-xr-xt/t0024-crlf-archive.sh16
-rwxr-xr-xt/t0060-path-utils.sh41
-rwxr-xr-xt/t0063-string-list.sh30
-rwxr-xr-xt/t1450-fsck.sh31
-rwxr-xr-xt/t1505-rev-parse-last.sh18
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh18
-rwxr-xr-xt/t3070-wildmatch.sh195
-rwxr-xr-xt/t3404-rebase-interactive.sh6
-rwxr-xr-xt/t3501-revert-cherry-pick.sh9
-rwxr-xr-xt/t3506-cherry-pick-ff.sh8
-rwxr-xr-xt/t3507-cherry-pick-conflict.sh6
-rwxr-xr-xt/t3508-cherry-pick-many-commits.sh8
-rwxr-xr-xt/t3510-cherry-pick-sequence.sh6
-rwxr-xr-xt/t4014-format-patch.sh58
-rwxr-xr-xt/t4203-mailmap.sh154
-rwxr-xr-xt/t4300-merge-tree.sh44
-rwxr-xr-xt/t5000-tar-tree.sh71
-rwxr-xr-xt/t5003-archive-zip.sh131
-rw-r--r--t/t5003/infozip-symlinks.zipbin0 -> 328 bytes
-rwxr-xr-xt/t5516-fetch-push.sh44
-rwxr-xr-xt/t5800-remote-testpy.sh (renamed from t/t5800-remote-helpers.sh)35
-rwxr-xr-xt/t5801-remote-helpers.sh169
-rwxr-xr-xt/t6006-rev-list-format.sh63
-rwxr-xr-xt/t6030-bisect-porcelain.sh4
-rwxr-xr-xt/t6130-pathspec-noglob.sh68
-rwxr-xr-xt/t7061-wtstatus-ignore.sh146
-rwxr-xr-xt/t7400-submodule-basic.sh1
-rwxr-xr-xt/t7406-submodule-update.sh31
-rwxr-xr-xt/t7500/add-content-and-comment5
-rwxr-xr-xt/t7502-commit.sh84
-rwxr-xr-xt/t9350-fast-export.sh65
-rw-r--r--t/test-lib-functions.sh7
-rw-r--r--t/test-lib.sh33
-rw-r--r--test-path-utils.c51
-rw-r--r--test-string-list.c20
-rw-r--r--test-wildmatch.c22
-rw-r--r--transport-helper.c6
-rw-r--r--transport.c25
-rw-r--r--transport.h10
-rw-r--r--tree-walk.c77
-rw-r--r--unpack-trees.c14
-rw-r--r--upload-pack.c2
-rw-r--r--usage.c1
-rw-r--r--wildmatch.c235
-rw-r--r--wildmatch.h9
-rw-r--r--wt-status.c4
158 files changed, 6089 insertions, 1950 deletions
diff --git a/.gitignore b/.gitignore
index 726db73450..aa258a6bcf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,6 @@
/GIT-BUILD-OPTIONS
/GIT-CFLAGS
/GIT-LDFLAGS
-/GIT-GUI-VARS
/GIT-PREFIX
/GIT-PYTHON-VARS
/GIT-SCRIPT-DEFINES
@@ -125,7 +124,7 @@
/git-remote-ftps
/git-remote-fd
/git-remote-ext
-/git-remote-testgit
+/git-remote-testpy
/git-remote-testsvn
/git-repack
/git-replace
@@ -172,7 +171,6 @@
/git-whatchanged
/git-write-tree
/git-core-*/?*
-/gitk-git/gitk-wish
/gitweb/GITWEB-BUILD-OPTIONS
/gitweb/gitweb.cgi
/gitweb/static/gitweb.js
@@ -199,6 +197,7 @@
/test-string-list
/test-subprocess
/test-svn-fe
+/test-wildmatch
/common-cmds.h
*.tar.gz
*.dsc
diff --git a/Documentation/RelNotes/1.8.1.2.txt b/Documentation/RelNotes/1.8.1.2.txt
new file mode 100644
index 0000000000..76ad0b3d01
--- /dev/null
+++ b/Documentation/RelNotes/1.8.1.2.txt
@@ -0,0 +1,13 @@
+Git 1.8.1.2 Release Notes
+=========================
+
+Fixes since v1.8.1.1
+--------------------
+
+ * "git archive" did not record uncompressed size in the header when
+ streaming a zip archive, which confused some implementations of unzip.
+
+ * When users spelled "cc:" in lowercase in the fake "header" in the
+ trailer part, "git send-email" failed to pick up the addresses from
+ there. As e-mail headers field names are case insensitive, this
+ script should follow suit and treat "cc:" and "Cc:" the same way.
diff --git a/Documentation/RelNotes/1.8.2.txt b/Documentation/RelNotes/1.8.2.txt
new file mode 100644
index 0000000000..f6d15059dc
--- /dev/null
+++ b/Documentation/RelNotes/1.8.2.txt
@@ -0,0 +1,261 @@
+Git v1.8.2 Release Notes
+========================
+
+Backward compatibility notes
+----------------------------
+
+In the upcoming major release (tentatively called 1.8.2), we will
+change the behavior of the "git push" command.
+
+When "git push [$there]" does not say what to push, we have used the
+traditional "matching" semantics so far (all your branches were sent
+to the remote as long as there already are branches of the same name
+over there). We will use the "simple" semantics that pushes the
+current branch to the branch with the same name, only when the current
+branch is set to integrate with that remote branch. There is a user
+preference configuration variable "push.default" to change this.
+
+
+Updates since v1.8.1
+--------------------
+
+UI, Workflows & Features
+
+ * Initial ports to QNX and z/OS UNIX System Services have started.
+
+ * Output from the tests is coloured using "green is okay, yellow is
+ questionable, red is bad and blue is informative" scheme.
+
+ * In bare repositories, "git shortlog" and other commands now read
+ mailmap files from the tip of the history, to help running these
+ tools in server settings.
+
+ * Color specifiers, e.g. "%C(blue)Hello%C(reset)", used in the
+ "--format=" option of "git log" and friends can be disabled when
+ the output is not sent to a terminal by prefixing them with
+ "auto,", e.g. "%C(auto,blue)Hello%C(auto,reset)".
+
+ * Scripts can ask Git that wildcard patterns in pathspecs they give do
+ not have any significance, i.e. take them as literal strings.
+
+ * The pathspec code learned to grok "foo/**/bar" as a pattern that
+ matches "bar" in 0-or-more levels of subdirectory in "foo".
+
+ * "git blame" (and "git diff") learned the "--no-follow" option.
+
+ * "git cherry-pick" can be used to replay a root commit to an unborn
+ branch.
+
+ * "git commit" can be told to use --cleanup=whitespace by setting the
+ configuration variable commit.cleanup to 'whitespace'.
+
+ * "git fetch --mirror" and fetch that uses other forms of refspec
+ with wildcard used to attempt to update a symbolic ref that match
+ the wildcard on the receiving end, which made little sense (the
+ real ref that is pointed at by the symbolic ref would be updated
+ anyway). Symbolic refs no longer are affected by such a fetch.
+
+ * "git format-patch" now detects more cases in which a whole branch
+ is being exported, and uses the description for the branch, when
+ asked to write a cover letter for the series.
+
+ * "git format-patch" learned "-v $count" option, and prepends a
+ string "v$count-" to the names of its output files, and also
+ automatically sets the subject prefix to "PATCH v$count". This
+ allows patches from rerolled series to be stored under different
+ names and makes it easier to reuse cover letter messsages.
+
+ * "git log" and friends can be told with --use-mailmap option to
+ rewrite the names and email addresses of people using the mailmap
+ mechanism.
+
+ * "git push" now requires "-f" to update a tag, even if it is a
+ fast-forward, as tags are meant to be fixed points.
+
+ * When "git rebase" fails to generate patches to be applied (e.g. due
+ to oom), it failed to detect the failure and instead behaved as if
+ there were nothing to do. A workaround to use a temporary file has
+ been applied, but we probably would want to revisit this later, as
+ it hurts the common case of not failing at all.
+
+ * "git submodule" started learning a new mode to integrate with the
+ tip of the remote branch (as opposed to integrating with the commit
+ recorded in the superproject's gitlink).
+
+
+Foreign Interface
+
+ * "git fast-export" has been updated for its use in the context of
+ the remote helper interface.
+
+ * A new remote helper to interact with bzr has been added to contrib/.
+
+
+Performance, Internal Implementation, etc.
+
+ * "git fsck" has been taught to be pickier about entries in tree
+ objects that should not be there, e.g. ".", ".git", and "..".
+
+ * Matching paths with common forms of pathspecs that contain wildcard
+ characters has been optimized further.
+
+ * The implementation of "imap-send" has been updated to reuse xml
+ quoting code from http-push codepath.
+
+ * There is a simple-minded checker for the test scripts in t/
+ directory to catch most common mistakes (it is not enabled by
+ default).
+
+
+Also contains minor documentation updates and code clean-ups.
+
+
+Fixes since v1.8.1
+------------------
+
+Unless otherwise noted, all the fixes since v1.8.1 in the maintenance
+track are contained in this release (see release notes to them for
+details).
+
+ * An element on GIT_CEILING_DIRECTORIES list that does not name the
+ real path to a directory (i.e. a symbolic link) could have caused
+ the GIT_DIR discovery logic to escape the ceiling.
+ (merge 059b379 mh/ceiling later to maint).
+
+ * When attempting to read the XDG-style $HOME/.config/git/config and
+ finding that $HOME/.config/git is a file, we gave a wrong error
+ message, instead of treating the case as "a custom config file does
+ not exist there" and moving on.
+ (merge 8f2bbe4 jn/warn-on-inaccessible-loosen later to maint).
+
+ * The behaviour visible to the end users was confusing, when they
+ attempt to kill a process spawned in the editor that was in turn
+ launched by Git with SIGINT (or SIGQUIT), as Git would catch that
+ signal and die. We ignore these signals now.
+ (merge 1250857 pf/editor-ignore-sigint later to maint).
+
+ * A child process that was killed by a signal (e.g. SIGINT) was
+ reported in an inconsistent way depending on how the process was
+ spawned by us, with or without a shell in between.
+ (merge 709ca73 jk/unify-exit-code-by-receiving-signal later to maint).
+
+ * After failing to create a temporary file using mkstemp(), failing
+ pathname was not reported correctly on some platforms.
+ (merge f7be59b jc/mkstemp-more-careful-error-reporting later to maint).
+
+ * The attribute mechanism didn't allow limiting attributes to be
+ applied to only a single directory itself with "path/" like the
+ exclude mechanism does.
+ (merge 94bc671 ja/directory-attrs later to maint).
+
+ * "git apply" misbehaved when fixing whitespace breakages by removing
+ excess trailing blank lines.
+ (merge 5de7166 jc/apply-trailing-blank-removal later to maint).
+
+ * A tar archive created by "git archive" recorded a directory in a
+ way that made NetBSD's implementation of "tar" sometimes unhappy.
+ (merge 22f0dcd rs/leave-base-name-in-name-field-of-tar later to maint).
+
+ * "git archive" did not record uncompressed size in the header when
+ streaming a zip archive, which confused some implementations of unzip.
+ (merge 5ea2c84 rs/zip-with-uncompressed-size-in-the-header later to maint).
+
+ * When "git clone --separate-git-dir=$over_there" is interrupted, it
+ failed to remove the real location of the $GIT_DIR it created.
+ This was most visible when interrupting a submodule update.
+ (merge 9be1980 jl/interrupt-clone-remove-separate-git-dir later to maint).
+
+ * The way "git svn" asked for password using SSH_ASKPASS and
+ GIT_ASKPASS was not in line with the rest of the system.
+ (merge e9263e4 ss/svn-prompt later to maint).
+
+ * The --graph code fell into infinite loop when asked to do what the
+ code did not expect.
+ (merge 656197a mk/maint-graph-infinity-loop later to maint).
+
+ * http transport was wrong to ask for the username when the
+ authentication is done by certificate identity.
+ (merge 75e9a40 rb/http-cert-cred-no-username-prompt later to maint).
+
+ * "git pack-refs" that ran in parallel to another process that
+ created new refs had a nasty race.
+ (merge b3f1280 jk/repack-ref-racefix later to maint).
+
+ * After "git add -N" and then writing a tree object out of the
+ index, the cache-tree data structure got corrupted.
+ (merge eec3e7e nd/invalidate-i-t-a-cache-tree later to maint).
+
+ * "git merge --no-edit" computed who were involved in the work done
+ on the side branch, even though that information is to be discarded
+ without getting seen in the editor.
+ (merge 9bcbb1c jc/maint-fmt-merge-msg-no-edit-lose-credit later to maint).
+
+ * "git merge" started calling prepare-commit-msg hook like "git
+ commit" does some time ago, but forgot to pay attention to the exit
+ status of the hook.
+ (merge 3e4141d ap/merge-stop-at-prepare-commit-msg-failure later to maint).
+
+ * When users spell "cc:" in lowercase in the fake "header" in the
+ trailer part, "git send-email" failed to pick up the addresses from
+ there. As e-mail headers field names are case insensitive, this
+ script should follow suit and treat "cc:" and "Cc:" the same way.
+ (merge 6310071 nz/send-email-headers-are-case-insensitive later to maint).
+
+ * Output from "git status --ignored" showed an unexpected interaction
+ with "--untracked".
+ (merge a45fb69 ap/status-ignored-in-ignored-directory later to maint).
+
+ * "gitweb", when sorting by age to show repositories with new
+ activities first, used to sort repositories with absolutely
+ nothing in it early, which was not very useful.
+ (merge 28dae18 md/gitweb-sort-by-age later to maint).
+
+ * "gitweb"'s code to sanitize control characters before passing it to
+ "highlight" filter lost known-to-be-safe control characters by
+ mistake.
+ (merge 0e901d2 os/gitweb-highlight-uncaptured later to maint).
+
+ * When a line to be wrapped has a solid run of non space characters
+ whose length exactly is the wrap width, "git shortlog -w" failed
+ to add a newline after such a line.
+ (merge e0db176 sp/shortlog-missing-lf later to maint).
+
+ * Command line completion leaked an unnecessary error message while
+ looking for possible matches with paths in <tree-ish>.
+ (merge ca87dd6 ds/completion-silence-in-tree-path-probe later to maint).
+
+ * Command line completion for "tcsh" emitted an unwanted space
+ after completing a single directory name.
+ (merge 92f1c04 mk/complete-tcsh later to maint).
+
+ * Some shells do not behave correctly when IFS is unset; work it
+ around by explicitly setting it to the default value.
+ (merge 393050c jc/maint-fbsd-sh-ifs-workaround later to maint).
+
+ * Some scripted programs written in Python did not get updated when
+ PYTHON_PATH changed.
+ (cherry-pick 96a4647fca54031974cd6ad1 later to maint).
+
+ * When autoconf is used, any build on a different commit always ran
+ "config.status --recheck" even when unnecessary.
+ (merge 1226504 jn/less-reconfigure later to maint).
+
+ * We have been carrying a translated and long-unmaintained copy of an
+ old version of the tutorial; removed.
+ (merge 0a85441 ta/remove-stale-translated-tut later to maint).
+
+ * t4014, t9502 and t0200 tests had various portability issues that
+ broke on OpenBSD.
+ (merge 27f6342 jc/maint-test-portability later to maint).
+
+ * t9020 and t3600 tests had various portability issues.
+ (merge 5a02966 jc/test-portability later to maint).
+
+ * t9200 runs "cvs init" on a directory that already exists, but a
+ platform can configure this fail for the current user (e.g. you
+ need to be in the cvsadmin group on NetBSD 6.0).
+ (merge 8666df0 jc/test-cvs-no-init-in-existing-dir later to maint).
+
+ * t9020 and t9810 had a few non-portable shell script construct.
+ (merge 2797914 tb/test-t9020-no-which later to maint).
+ (merge 6f4e505 tb/test-t9810-no-sed-i later to maint).
diff --git a/Documentation/config.txt b/Documentation/config.txt
index bf8f911e1f..b87f744643 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -140,10 +140,11 @@ advice.*::
can tell Git that you do not need help by setting these to 'false':
+
--
- pushNonFastForward::
+ pushUpdateRejected::
Set this variable to 'false' if you want to disable
- 'pushNonFFCurrent', 'pushNonFFDefault', and
- 'pushNonFFMatching' simultaneously.
+ 'pushNonFFCurrent', 'pushNonFFDefault',
+ 'pushNonFFMatching', and 'pushAlreadyExists'
+ simultaneously.
pushNonFFCurrent::
Advice shown when linkgit:git-push[1] fails due to a
non-fast-forward update to the current branch.
@@ -158,6 +159,9 @@ advice.*::
'matching refs' explicitly (i.e. you used ':', or
specified a refspec that isn't your current branch) and
it resulted in a non-fast-forward error.
+ pushAlreadyExists::
+ Shown when linkgit:git-push[1] rejects an update that
+ does not qualify for fast-forwarding (e.g., a tag.)
statusHints::
Show directions on how to proceed from the current
state in the output of linkgit:git-status[1], in
@@ -735,6 +739,12 @@ branch.<name>.rebase::
it unless you understand the implications (see linkgit:git-rebase[1]
for details).
+branch.<name>.description::
+ Branch description, can be edited with
+ `git branch --edit-description`. Branch description is
+ automatically added in the format-patch cover letter or
+ request-pull summary.
+
browser.<tool>.cmd::
Specify the command to invoke the specified browser. The
specified command is evaluated in shell with the URLs passed
@@ -913,6 +923,15 @@ column.tag::
Specify whether to output tag listing in `git tag` in columns.
See `column.ui` for details.
+commit.cleanup::
+ This setting overrides the default of the `--cleanup` option in
+ `git commit`. See linkgit:git-commit[1] for details. Changing the
+ default can be useful when you always want to keep lines that begin
+ with comment character `#` in your log message, in which case you
+ would do `git config commit.cleanup whitespace` (note that you will
+ have to remove the help lines that begin with `#` in the commit log
+ template yourself, if you do this).
+
commit.status::
A boolean to enable/disable inclusion of status information in the
commit message template when using an editor to prepare the commit
@@ -1351,6 +1370,12 @@ help.autocorrect::
value is 0 - the command will be just shown but not executed.
This is the default.
+help.htmlpath::
+ Specify the path where the HTML documentation resides. File system paths
+ and URLs are supported. HTML pages will be prefixed with this path when
+ help is displayed in the 'web' format. This defaults to the documentation
+ path of your Git installation.
+
http.proxy::
Override the HTTP proxy, normally configured using the 'http_proxy',
'https_proxy', and 'all_proxy' environment variables (see
@@ -1509,6 +1534,10 @@ log.showroot::
Tools like linkgit:git-log[1] or linkgit:git-whatchanged[1], which
normally hide the root commit will now show it. True by default.
+log.mailmap::
+ If true, makes linkgit:git-log[1], linkgit:git-show[1], and
+ linkgit:git-whatchanged[1] assume `--use-mailmap`.
+
mailmap.file::
The location of an augmenting mailmap file. The default
mailmap, located in the root of the repository, is loaded
@@ -1517,6 +1546,14 @@ mailmap.file::
subdirectory, or somewhere outside of the repository itself.
See linkgit:git-shortlog[1] and linkgit:git-blame[1].
+mailmap.blob::
+ Like `mailmap.file`, but consider the value as a reference to a
+ blob in the repository. If both `mailmap.file` and
+ `mailmap.blob` are given, both are parsed, with entries from
+ `mailmap.file` taking precedence. In a bare repository, this
+ defaults to `HEAD:.mailmap`. In a non-bare repository, it
+ defaults to empty.
+
man.viewer::
Specify the programs that may be used to display help in the
'man' format. See linkgit:git-help[1].
@@ -1995,6 +2032,12 @@ submodule.<name>.update::
URL and other values found in the `.gitmodules` file. See
linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
+submodule.<name>.branch::
+ The remote branch name for a submodule, used by `git submodule
+ update --remote`. Set this option to override the value found in
+ the `.gitmodules` file. See linkgit:git-submodule[1] and
+ linkgit:gitmodules[5] for details.
+
submodule.<name>.fetchRecurseSubmodules::
This option can be used to control recursive fetching of this
submodule. It can be overridden by using the --[no-]recurse-submodules
diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt
index 6d5a04c83b..a221169515 100644
--- a/Documentation/git-commit-tree.txt
+++ b/Documentation/git-commit-tree.txt
@@ -72,13 +72,13 @@ if set:
GIT_COMMITTER_NAME
GIT_COMMITTER_EMAIL
GIT_COMMITTER_DATE
- EMAIL
(nb "<", ">" and "\n"s are stripped)
In case (some of) these environment variables are not set, the information
is taken from the configuration items user.name and user.email, or, if not
-present, system user name and the hostname used for outgoing mail (taken
+present, the environment variable EMAIL, or, if that is not set,
+system user name and the hostname used for outgoing mail (taken
from `/etc/mailname` and falling back to the fully qualified hostname when
that file does not exist).
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 7bdb039d5e..41b27da325 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -179,7 +179,9 @@ OPTIONS
only if the message is to be edited. Otherwise only whitespace
removed. The 'verbatim' mode does not change message at all,
'whitespace' removes just leading/trailing whitespace lines
- and 'strip' removes both whitespace and commentary.
+ and 'strip' removes both whitespace and commentary. The default
+ can be changed by the 'commit.cleanup' configuration variable
+ (see linkgit:git-config[1]).
-e::
--edit::
diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt
index 98d9881d7e..9d5353e8be 100644
--- a/Documentation/git-cvsimport.txt
+++ b/Documentation/git-cvsimport.txt
@@ -213,11 +213,9 @@ Problems related to tags:
* Multiple tags on the same revision are not imported.
If you suspect that any of these issues may apply to the repository you
-want to import consider using these alternative tools which proved to be
-more stable in practice:
+want to imort, consider using cvs2git:
-* cvs2git (part of cvs2svn), `http://cvs2svn.tigris.org`
-* parsecvs, `http://cgit.freedesktop.org/~keithp/parsecvs`
+* cvs2git (part of cvs2svn), `http://subversion.apache.org/`
GIT
---
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index db55a4e0bb..f2e08d11c1 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -117,7 +117,7 @@ returns an empty string instead.
As a special case for the date-type fields, you may specify a format for
the date by adding one of `:default`, `:relative`, `:short`, `:local`,
-`:iso8601` or `:rfc2822` to the end of the fieldname; e.g.
+`:iso8601`, `:rfc2822` or `:raw` to the end of the fieldname; e.g.
`%(taggerdate:relative)`.
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 259dce4994..9a914d0159 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -18,7 +18,7 @@ SYNOPSIS
[--start-number <n>] [--numbered-files]
[--in-reply-to=Message-Id] [--suffix=.<sfx>]
[--ignore-if-in-upstream]
- [--subject-prefix=Subject-Prefix]
+ [--subject-prefix=Subject-Prefix] [(--reroll-count|-v) <n>]
[--to=<email>] [--cc=<email>]
[--cover-letter] [--quiet] [--notes[=<ref>]]
[<common diff options>]
@@ -166,6 +166,15 @@ will want to ensure that threading is disabled for `git send-email`.
allows for useful naming of a patch series, and can be
combined with the `--numbered` option.
+-v <n>::
+--reroll-count=<n>::
+ Mark the series as the <n>-th iteration of the topic. The
+ output filenames have `v<n>` pretended to them, and the
+ subject prefix ("PATCH" by default, but configurable via the
+ `--subject-prefix` option) has ` v<n>` appended to it. E.g.
+ `--reroll-count=4` may produce `v4-0001-add-makefile.patch`
+ file that has "Subject: [PATCH v4 1/20] Add makefile" in it.
+
--to=<email>::
Add a `To:` header to the email headers. This is in addition
to any configured headers, and may be used multiple times.
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 585dac40ba..22c0d6e4b1 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -47,6 +47,11 @@ OPTIONS
Print out the ref name given on the command line by which each
commit was reached.
+--use-mailmap::
+ Use mailmap file to map author and committer names and email
+ to canonical real names and email addresses. See
+ linkgit:git-shortlog[1].
+
--full-diff::
Without this flag, "git log -p <path>..." shows commits that
touch the specified paths, and diffs about the same specified
@@ -167,7 +172,7 @@ log.showroot::
`git log -p` output would be shown without a diff attached.
The default is `true`.
-mailmap.file::
+mailmap.*::
See linkgit:git-shortlog[1].
notes.displayRef::
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 8b637d339f..c964b796be 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -51,10 +51,11 @@ be named. If `:`<dst> is omitted, the same ref as <src> will be
updated.
+
The object referenced by <src> is used to update the <dst> reference
-on the remote side, but by default this is only allowed if the
-update can fast-forward <dst>. By having the optional leading `+`,
-you can tell git to update the <dst> ref even when the update is not a
-fast-forward. This does *not* attempt to merge <src> into <dst>. See
+on the remote side. By default this is only allowed if <dst> is not
+a tag (annotated or lightweight), and then only if it can fast-forward
+<dst>. By having the optional leading `+`, you can tell git to update
+the <dst> ref even if it is not allowed by default (e.g., it is not a
+fast-forward.) This does *not* attempt to merge <src> into <dst>. See
EXAMPLES below for details.
+
`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
diff --git a/Documentation/git-remote-testgit.txt b/Documentation/git-remote-testgit.txt
index 2a67d456a3..612a625ced 100644
--- a/Documentation/git-remote-testgit.txt
+++ b/Documentation/git-remote-testgit.txt
@@ -19,7 +19,7 @@ testcase for the remote-helper functionality, and as an example to
show remote-helper authors one possible implementation.
The best way to learn more is to read the comments and source code in
-'git-remote-testgit.py'.
+'git-remote-testgit'.
SEE ALSO
--------
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index b1de3bade7..b1996f1a63 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -13,7 +13,7 @@ SYNOPSIS
[--reference <repository>] [--] <repository> [<path>]
'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
'git submodule' [--quiet] init [--] [<path>...]
-'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
+'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch] [--rebase]
[--reference <repository>] [--merge] [--recursive] [--] [<path>...]
'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
[commit] [--] [<path>...]
@@ -208,6 +208,8 @@ OPTIONS
-b::
--branch::
Branch of repository to add as submodule.
+ The name of the branch is recorded as `submodule.<path>.branch` in
+ `.gitmodules` for `update --remote`.
-f::
--force::
@@ -236,6 +238,27 @@ OPTIONS
(the default). This limit only applies to modified submodules. The
size is always limited to 1 for added/deleted/typechanged submodules.
+--remote::
+ This option is only valid for the update command. Instead of using
+ the superproject's recorded SHA-1 to update the submodule, use the
+ status of the submodule's remote tracking branch. The remote used
+ is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
+ The remote branch used defaults to `master`, but the branch name may
+ be overridden by setting the `submodule.<name>.branch` option in
+ either `.gitmodules` or `.git/config` (with `.git/config` taking
+ precedence).
++
+This works for any of the supported update procedures (`--checkout`,
+`--rebase`, etc.). The only change is the source of the target SHA-1.
+For example, `submodule update --remote --merge` will merge upstream
+submodule changes into the submodules, while `submodule update
+--merge` will merge superproject gitlink changes into the submodules.
++
+In order to ensure a current tracking branch state, `update --remote`
+fetches the submodule's remote repository before calculating the
+SHA-1. If you don't want to fetch, you should use `submodule update
+--remote --no-fetch`.
+
-N::
--no-fetch::
This option is only valid for the update command.
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 69decb13b0..34d438b0ab 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -346,6 +346,16 @@ Any other arguments are passed directly to 'git log'
corresponding git commit hash (this can optionally be followed by a
tree-ish to specify which branch should be searched). When given a
tree-ish, returns the corresponding SVN revision number.
++
+--before;;
+ Don't require an exact match if given an SVN revision, instead find
+ the commit corresponding to the state of the SVN repository (on the
+ current branch) at the specified revision.
++
+--after;;
+ Don't require an exact match if given an SVN revision; if there is
+ not an exact match return the closest match searching forward in the
+ history.
'set-tree'::
You should consider using 'dcommit' instead of this command.
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 276491223a..555250dfa0 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -429,6 +429,11 @@ help ...`.
Do not use replacement refs to replace git objects. See
linkgit:git-replace[1] for more information.
+--literal-pathspecs::
+ Treat pathspecs literally, rather than as glob patterns. This is
+ equivalent to setting the `GIT_LITERAL_PATHSPECS` environment
+ variable to `1`.
+
GIT COMMANDS
------------
@@ -805,6 +810,16 @@ for further details.
as a file path and will try to write the trace messages
into it.
+GIT_LITERAL_PATHSPECS::
+ Setting this variable to `1` will cause git to treat all
+ pathspecs literally, rather than as glob patterns. For example,
+ running `GIT_LITERAL_PATHSPECS=1 git log -- '*.c'` will search
+ for commits that touch the path `*.c`, not any paths that the
+ glob `*.c` matches. You might want this if you are feeding
+ literal paths to git (e.g., paths previously given to you by
+ `git ls-tree`, `--raw` diff output, etc).
+
+
Discussion[[Discussion]]
------------------------
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index 1b82fe1969..91a6438031 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -108,6 +108,25 @@ PATTERN FORMAT
For example, "/{asterisk}.c" matches "cat-file.c" but not
"mozilla-sha1/sha1.c".
+Two consecutive asterisks ("`**`") in patterns matched against
+full pathname may have special meaning:
+
+ - A leading "`**`" followed by a slash means match in all
+ directories. For example, "`**/foo`" matches file or directory
+ "`foo`" anywhere, the same as pattern "`foo`". "**/foo/bar"
+ matches file or directory "`bar`" anywhere that is directly
+ under directory "`foo`".
+
+ - A trailing "/**" matches everything inside. For example,
+ "abc/**" matches all files inside directory "abc", relative
+ to the location of the `.gitignore` file, with infinite depth.
+
+ - A slash followed by two consecutive asterisks then a slash
+ matches zero or more directories. For example, "`a/**/b`"
+ matches "`a/b`", "`a/x/b`", "`a/x/y/b`" and so on.
+
+ - Other consecutive asterisks are considered invalid.
+
NOTES
-----
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index ab3e91c054..52d7ae4313 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -49,6 +49,11 @@ submodule.<name>.update::
This config option is overridden if 'git submodule update' is given
the '--merge', '--rebase' or '--checkout' options.
+submodule.<name>.branch::
+ A remote branch name for tracking updates in the upstream submodule.
+ If the option is not specified, it defaults to 'master'. See the
+ `--remote` documentation in linkgit:git-submodule[1] for details.
+
submodule.<name>.fetchRecurseSubmodules::
This option can be used to control recursive fetching of this
submodule. If this option is also present in the submodules entry in
diff --git a/Documentation/mailmap.txt b/Documentation/mailmap.txt
index dd89fca3f8..4a8c276529 100644
--- a/Documentation/mailmap.txt
+++ b/Documentation/mailmap.txt
@@ -1,5 +1,6 @@
If the file `.mailmap` exists at the toplevel of the repository, or at
-the location pointed to by the mailmap.file configuration option, it
+the location pointed to by the mailmap.file or mailmap.blob
+configuration options, it
is used to map author and committer names and email addresses to
canonical real names and email addresses.
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index d9eddedc72..105f18a6f9 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -144,7 +144,11 @@ The placeholders are:
- '%Cgreen': switch color to green
- '%Cblue': switch color to blue
- '%Creset': reset color
-- '%C(...)': color specification, as described in color.branch.* config option
+- '%C(...)': color specification, as described in color.branch.* config option;
+ adding `auto,` at the beginning will emit color only when colors are
+ enabled for log output (by `color.diff`, `color.ui`, or `--color`, and
+ respecting the `auto` settings of the former if we are going to a
+ terminal)
- '%m': left, right or boundary mark
- '%n': newline
- '%%': a raw '%'
diff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt
index add6f435b5..944fc39fac 100644
--- a/Documentation/technical/api-directory-listing.txt
+++ b/Documentation/technical/api-directory-listing.txt
@@ -9,37 +9,40 @@ Data structure
--------------
`struct dir_struct` structure is used to pass directory traversal
-options to the library and to record the paths discovered. The notable
-options are:
+options to the library and to record the paths discovered. A single
+`struct dir_struct` is used regardless of whether or not the traversal
+recursively descends into subdirectories.
+
+The notable options are:
`exclude_per_dir`::
The name of the file to be read in each directory for excluded
files (typically `.gitignore`).
-`collect_ignored`::
+`flags`::
- Include paths that are to be excluded in the result.
+ A bit-field of options:
-`show_ignored`::
+`DIR_SHOW_IGNORED`:::
The traversal is for finding just ignored files, not unignored
files.
-`show_other_directories`::
+`DIR_SHOW_OTHER_DIRECTORIES`:::
Include a directory that is not tracked.
-`hide_empty_directories`::
+`DIR_HIDE_EMPTY_DIRECTORIES`:::
Do not include a directory that is not tracked and is empty.
-`no_gitlinks`::
+`DIR_NO_GITLINKS`:::
If set, recurse into a directory that looks like a git
directory. Otherwise it is shown as a directory.
-The result of the enumeration is left in these fields::
+The result of the enumeration is left in these fields:
`entries[]`::
diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt
index 7386bcab3e..20be348834 100644
--- a/Documentation/technical/api-string-list.txt
+++ b/Documentation/technical/api-string-list.txt
@@ -82,14 +82,6 @@ Functions
call free() on the util members of any items that have to be
deleted. Preserve the order of the items that are retained.
-`string_list_longest_prefix`::
-
- Return the longest string within a string_list that is a
- prefix (in the sense of prefixcmp()) of the specified string,
- or NULL if no such prefix exists. This function does not
- require the string_list to be sorted (it does a linear
- search).
-
`print_string_list`::
Dump a string_list to stdout, useful mainly for debugging purposes. It
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index c572e8da13..e9f7abca91 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v1.8.1.1
+DEF_VER=v1.8.1.GIT
LF='
'
diff --git a/Makefile b/Makefile
index 05d241bc12..1b30d7bde3 100644
--- a/Makefile
+++ b/Makefile
@@ -74,10 +74,14 @@ all::
# Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
# d_type in struct dirent (Cygwin 1.5, fixed in Cygwin 1.7).
#
+# Define HAVE_STRINGS_H if you have strings.h and need it for strcasecmp.
+#
# Define NO_STRCASESTR if you don't have strcasestr.
#
# Define NO_MEMMEM if you don't have memmem.
#
+# Define NO_GETPAGESIZE if you don't have getpagesize.
+#
# Define NO_STRLCPY if you don't have strlcpy.
#
# Define NO_STRTOUMAX if you don't have both strtoimax and strtoumax in the
@@ -165,6 +169,10 @@ all::
# Define NO_POLL if you do not have or don't want to use poll().
# This also implies NO_SYS_POLL_H.
#
+# Define NEEDS_SYS_PARAM_H if you need to include sys/param.h to compile,
+# *PLEASE* REPORT to git@vger.kernel.org if your platform needs this;
+# we want to know more about the issue.
+#
# Define NO_PTHREADS if you do not have or do not want to use Pthreads.
#
# Define NO_PREAD if you have a problem with pread() system call (e.g.
@@ -330,19 +338,6 @@ GIT-VERSION-FILE: FORCE
@$(SHELL_PATH) ./GIT-VERSION-GEN
-include GIT-VERSION-FILE
-uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
-uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
-uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
-uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
-uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
-uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
-
-ifdef MSVC
- # avoid the MingW and Cygwin configuration sections
- uname_S := Windows
- uname_O := Windows
-endif
-
# CFLAGS and LDFLAGS are for the users to override from the command line.
CFLAGS = -g -O2 -Wall
@@ -474,7 +469,7 @@ SCRIPT_PERL += git-relink.perl
SCRIPT_PERL += git-send-email.perl
SCRIPT_PERL += git-svn.perl
-SCRIPT_PYTHON += git-remote-testgit.py
+SCRIPT_PYTHON += git-remote-testpy.py
SCRIPT_PYTHON += git-p4.py
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
@@ -528,6 +523,7 @@ TEST_PROGRAMS_NEED_X += test-sigchain
TEST_PROGRAMS_NEED_X += test-string-list
TEST_PROGRAMS_NEED_X += test-subprocess
TEST_PROGRAMS_NEED_X += test-svn-fe
+TEST_PROGRAMS_NEED_X += test-wildmatch
TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
@@ -700,6 +696,7 @@ LIB_H += userdiff.h
LIB_H += utf8.h
LIB_H += varint.h
LIB_H += walker.h
+LIB_H += wildmatch.h
LIB_H += wt-status.h
LIB_H += xdiff-interface.h
LIB_H += xdiff/xdiff.h
@@ -769,7 +766,7 @@ LIB_OBJS += log-tree.o
LIB_OBJS += mailmap.o
LIB_OBJS += match-trees.o
LIB_OBJS += merge.o
-LIB_OBJS += merge-file.o
+LIB_OBJS += merge-blobs.o
LIB_OBJS += merge-recursive.o
LIB_OBJS += mergesort.o
LIB_OBJS += name-hash.o
@@ -834,6 +831,7 @@ LIB_OBJS += utf8.o
LIB_OBJS += varint.o
LIB_OBJS += version.o
LIB_OBJS += walker.o
+LIB_OBJS += wildmatch.o
LIB_OBJS += wrapper.o
LIB_OBJS += write_or_die.o
LIB_OBJS += ws.o
@@ -941,518 +939,7 @@ EXTLIBS =
GIT_USER_AGENT = git/$(GIT_VERSION)
-#
-# Platform specific tweaks
-#
-
-# We choose to avoid "if .. else if .. else .. endif endif"
-# because maintaining the nesting to match is a pain. If
-# we had "elif" things would have been much nicer...
-
-ifeq ($(uname_M),x86_64)
- XDL_FAST_HASH = YesPlease
-endif
-ifeq ($(uname_S),OSF1)
- # Need this for u_short definitions et al
- BASIC_CFLAGS += -D_OSF_SOURCE
- SOCKLEN_T = int
- NO_STRTOULL = YesPlease
- NO_NSEC = YesPlease
-endif
-ifeq ($(uname_S),Linux)
- NO_STRLCPY = YesPlease
- NO_MKSTEMPS = YesPlease
- HAVE_PATHS_H = YesPlease
- LIBC_CONTAINS_LIBINTL = YesPlease
- HAVE_DEV_TTY = YesPlease
-endif
-ifeq ($(uname_S),GNU/kFreeBSD)
- NO_STRLCPY = YesPlease
- NO_MKSTEMPS = YesPlease
- HAVE_PATHS_H = YesPlease
- DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
- LIBC_CONTAINS_LIBINTL = YesPlease
-endif
-ifeq ($(uname_S),UnixWare)
- CC = cc
- NEEDS_SOCKET = YesPlease
- NEEDS_NSL = YesPlease
- NEEDS_SSL_WITH_CRYPTO = YesPlease
- NEEDS_LIBICONV = YesPlease
- SHELL_PATH = /usr/local/bin/bash
- NO_IPV6 = YesPlease
- NO_HSTRERROR = YesPlease
- NO_MKSTEMPS = YesPlease
- BASIC_CFLAGS += -Kthread
- BASIC_CFLAGS += -I/usr/local/include
- BASIC_LDFLAGS += -L/usr/local/lib
- INSTALL = ginstall
- TAR = gtar
- NO_STRCASESTR = YesPlease
- NO_MEMMEM = YesPlease
-endif
-ifeq ($(uname_S),SCO_SV)
- ifeq ($(uname_R),3.2)
- CFLAGS = -O2
- endif
- ifeq ($(uname_R),5)
- CC = cc
- BASIC_CFLAGS += -Kthread
- endif
- NEEDS_SOCKET = YesPlease
- NEEDS_NSL = YesPlease
- NEEDS_SSL_WITH_CRYPTO = YesPlease
- NEEDS_LIBICONV = YesPlease
- SHELL_PATH = /usr/bin/bash
- NO_IPV6 = YesPlease
- NO_HSTRERROR = YesPlease
- NO_MKSTEMPS = YesPlease
- BASIC_CFLAGS += -I/usr/local/include
- BASIC_LDFLAGS += -L/usr/local/lib
- NO_STRCASESTR = YesPlease
- NO_MEMMEM = YesPlease
- INSTALL = ginstall
- TAR = gtar
-endif
-ifeq ($(uname_S),Darwin)
- NEEDS_CRYPTO_WITH_SSL = YesPlease
- NEEDS_SSL_WITH_CRYPTO = YesPlease
- NEEDS_LIBICONV = YesPlease
- ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2)
- OLD_ICONV = UnfortunatelyYes
- endif
- ifeq ($(shell expr "$(uname_R)" : '[15]\.'),2)
- NO_STRLCPY = YesPlease
- endif
- NO_MEMMEM = YesPlease
- USE_ST_TIMESPEC = YesPlease
- HAVE_DEV_TTY = YesPlease
- COMPAT_OBJS += compat/precompose_utf8.o
- BASIC_CFLAGS += -DPRECOMPOSE_UNICODE
-endif
-ifeq ($(uname_S),SunOS)
- NEEDS_SOCKET = YesPlease
- NEEDS_NSL = YesPlease
- SHELL_PATH = /bin/bash
- SANE_TOOL_PATH = /usr/xpg6/bin:/usr/xpg4/bin
- NO_STRCASESTR = YesPlease
- NO_MEMMEM = YesPlease
- NO_MKDTEMP = YesPlease
- NO_MKSTEMPS = YesPlease
- NO_REGEX = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
- NO_MSGFMT_EXTENDED_OPTIONS = YesPlease
- HAVE_DEV_TTY = YesPlease
- ifeq ($(uname_R),5.6)
- SOCKLEN_T = int
- NO_HSTRERROR = YesPlease
- NO_IPV6 = YesPlease
- NO_SOCKADDR_STORAGE = YesPlease
- NO_UNSETENV = YesPlease
- NO_SETENV = YesPlease
- NO_STRLCPY = YesPlease
- NO_STRTOUMAX = YesPlease
- GIT_TEST_CMP = cmp
- endif
- ifeq ($(uname_R),5.7)
- NEEDS_RESOLV = YesPlease
- NO_IPV6 = YesPlease
- NO_SOCKADDR_STORAGE = YesPlease
- NO_UNSETENV = YesPlease
- NO_SETENV = YesPlease
- NO_STRLCPY = YesPlease
- NO_STRTOUMAX = YesPlease
- GIT_TEST_CMP = cmp
- endif
- ifeq ($(uname_R),5.8)
- NO_UNSETENV = YesPlease
- NO_SETENV = YesPlease
- NO_STRTOUMAX = YesPlease
- GIT_TEST_CMP = cmp
- endif
- ifeq ($(uname_R),5.9)
- NO_UNSETENV = YesPlease
- NO_SETENV = YesPlease
- NO_STRTOUMAX = YesPlease
- GIT_TEST_CMP = cmp
- endif
- INSTALL = /usr/ucb/install
- TAR = gtar
- BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H
-endif
-ifeq ($(uname_O),Cygwin)
- ifeq ($(shell expr "$(uname_R)" : '1\.[1-6]\.'),4)
- NO_D_TYPE_IN_DIRENT = YesPlease
- NO_D_INO_IN_DIRENT = YesPlease
- NO_STRCASESTR = YesPlease
- NO_MEMMEM = YesPlease
- NO_MKSTEMPS = YesPlease
- NO_SYMLINK_HEAD = YesPlease
- NO_IPV6 = YesPlease
- OLD_ICONV = UnfortunatelyYes
- CYGWIN_V15_WIN32API = YesPlease
- endif
- NO_THREAD_SAFE_PREAD = YesPlease
- NEEDS_LIBICONV = YesPlease
- NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
- NO_TRUSTABLE_FILEMODE = UnfortunatelyYes
- NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
- # There are conflicting reports about this.
- # On some boxes NO_MMAP is needed, and not so elsewhere.
- # Try commenting this out if you suspect MMAP is more efficient
- NO_MMAP = YesPlease
- X = .exe
- COMPAT_OBJS += compat/cygwin.o
- UNRELIABLE_FSTAT = UnfortunatelyYes
- SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield
-endif
-ifeq ($(uname_S),FreeBSD)
- NEEDS_LIBICONV = YesPlease
- OLD_ICONV = YesPlease
- NO_MEMMEM = YesPlease
- BASIC_CFLAGS += -I/usr/local/include
- BASIC_LDFLAGS += -L/usr/local/lib
- DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
- USE_ST_TIMESPEC = YesPlease
- ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
- PTHREAD_LIBS = -pthread
- NO_UINTMAX_T = YesPlease
- NO_STRTOUMAX = YesPlease
- endif
- PYTHON_PATH = /usr/local/bin/python
- HAVE_PATHS_H = YesPlease
-endif
-ifeq ($(uname_S),OpenBSD)
- NO_STRCASESTR = YesPlease
- NO_MEMMEM = YesPlease
- USE_ST_TIMESPEC = YesPlease
- NEEDS_LIBICONV = YesPlease
- BASIC_CFLAGS += -I/usr/local/include
- BASIC_LDFLAGS += -L/usr/local/lib
- HAVE_PATHS_H = YesPlease
-endif
-ifeq ($(uname_S),NetBSD)
- ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2)
- NEEDS_LIBICONV = YesPlease
- endif
- BASIC_CFLAGS += -I/usr/pkg/include
- BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
- USE_ST_TIMESPEC = YesPlease
- NO_MKSTEMPS = YesPlease
- HAVE_PATHS_H = YesPlease
-endif
-ifeq ($(uname_S),AIX)
- DEFAULT_PAGER = more
- NO_STRCASESTR = YesPlease
- NO_MEMMEM = YesPlease
- NO_MKDTEMP = YesPlease
- NO_MKSTEMPS = YesPlease
- NO_STRLCPY = YesPlease
- NO_NSEC = YesPlease
- FREAD_READS_DIRECTORIES = UnfortunatelyYes
- INTERNAL_QSORT = UnfortunatelyYes
- NEEDS_LIBICONV = YesPlease
- BASIC_CFLAGS += -D_LARGE_FILES
- ifeq ($(shell expr "$(uname_V)" : '[1234]'),1)
- NO_PTHREADS = YesPlease
- else
- PTHREAD_LIBS = -lpthread
- endif
- ifeq ($(shell expr "$(uname_V).$(uname_R)" : '5\.1'),3)
- INLINE = ''
- endif
- GIT_TEST_CMP = cmp
-endif
-ifeq ($(uname_S),GNU)
- # GNU/Hurd
- NO_STRLCPY = YesPlease
- NO_MKSTEMPS = YesPlease
- HAVE_PATHS_H = YesPlease
- LIBC_CONTAINS_LIBINTL = YesPlease
-endif
-ifeq ($(uname_S),IRIX)
- NO_SETENV = YesPlease
- NO_UNSETENV = YesPlease
- NO_STRCASESTR = YesPlease
- 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_REGEX = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
- SNPRINTF_RETURNS_BOGUS = YesPlease
- SHELL_PATH = /usr/gnu/bin/bash
- NEEDS_LIBGEN = YesPlease
-endif
-ifeq ($(uname_S),IRIX64)
- NO_SETENV = YesPlease
- NO_UNSETENV = YesPlease
- NO_STRCASESTR = YesPlease
- 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_REGEX = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
- SNPRINTF_RETURNS_BOGUS = YesPlease
- SHELL_PATH = /usr/gnu/bin/bash
- NEEDS_LIBGEN = YesPlease
-endif
-ifeq ($(uname_S),HP-UX)
- INLINE = __inline
- NO_IPV6 = YesPlease
- NO_SETENV = YesPlease
- NO_STRCASESTR = YesPlease
- NO_MEMMEM = YesPlease
- NO_MKSTEMPS = YesPlease
- NO_STRLCPY = YesPlease
- NO_MKDTEMP = YesPlease
- NO_UNSETENV = YesPlease
- NO_HSTRERROR = YesPlease
- NO_SYS_SELECT_H = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
- SNPRINTF_RETURNS_BOGUS = YesPlease
- NO_NSEC = YesPlease
- ifeq ($(uname_R),B.11.00)
- NO_INET_NTOP = YesPlease
- NO_INET_PTON = YesPlease
- endif
- ifeq ($(uname_R),B.10.20)
- # Override HP-UX 11.x setting:
- INLINE =
- SOCKLEN_T = size_t
- NO_PREAD = YesPlease
- NO_INET_NTOP = YesPlease
- NO_INET_PTON = YesPlease
- endif
- GIT_TEST_CMP = cmp
-endif
-ifeq ($(uname_S),Windows)
- GIT_VERSION := $(GIT_VERSION).MSVC
- pathsep = ;
- NO_PREAD = YesPlease
- NEEDS_CRYPTO_WITH_SSL = YesPlease
- NO_LIBGEN_H = YesPlease
- NO_POLL = YesPlease
- NO_SYMLINK_HEAD = YesPlease
- NO_IPV6 = YesPlease
- NO_UNIX_SOCKETS = YesPlease
- NO_SETENV = YesPlease
- NO_UNSETENV = YesPlease
- NO_STRCASESTR = YesPlease
- NO_STRLCPY = YesPlease
- NO_STRTOK_R = YesPlease
- NO_FNMATCH = YesPlease
- NO_MEMMEM = YesPlease
- # NEEDS_LIBICONV = YesPlease
- NO_ICONV = YesPlease
- NO_STRTOUMAX = YesPlease
- NO_STRTOULL = YesPlease
- NO_MKDTEMP = YesPlease
- NO_MKSTEMPS = YesPlease
- SNPRINTF_RETURNS_BOGUS = YesPlease
- NO_SVN_TESTS = YesPlease
- NO_PERL_MAKEMAKER = YesPlease
- RUNTIME_PREFIX = YesPlease
- NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
- NO_NSEC = YesPlease
- USE_WIN32_MMAP = YesPlease
- # USE_NED_ALLOCATOR = YesPlease
- UNRELIABLE_FSTAT = UnfortunatelyYes
- OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
- NO_REGEX = YesPlease
- NO_CURL = YesPlease
- NO_PYTHON = YesPlease
- BLK_SHA1 = YesPlease
- NO_POSIX_GOODIES = UnfortunatelyYes
- NATIVE_CRLF = YesPlease
- DEFAULT_HELP_FORMAT = html
-
- 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
- COMPAT_OBJS = compat/msvc.o compat/winansi.o \
- compat/win32/pthread.o compat/win32/syslog.o \
- compat/win32/dirent.o
- COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
- BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
- EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib
- PTHREAD_LIBS =
- lib =
-ifndef DEBUG
- BASIC_CFLAGS += -GL -Os -MT
- BASIC_LDFLAGS += -LTCG
- AR += -LTCG
-else
- BASIC_CFLAGS += -Zi -MTd
-endif
- X = .exe
-endif
-ifeq ($(uname_S),Interix)
- NO_INITGROUPS = YesPlease
- NO_IPV6 = YesPlease
- NO_MEMMEM = YesPlease
- NO_MKDTEMP = YesPlease
- NO_STRTOUMAX = YesPlease
- NO_NSEC = YesPlease
- NO_MKSTEMPS = YesPlease
- ifeq ($(uname_R),3.5)
- NO_INET_NTOP = YesPlease
- NO_INET_PTON = YesPlease
- NO_SOCKADDR_STORAGE = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
- endif
- ifeq ($(uname_R),5.2)
- NO_INET_NTOP = YesPlease
- NO_INET_PTON = YesPlease
- NO_SOCKADDR_STORAGE = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
- endif
-endif
-ifeq ($(uname_S),Minix)
- NO_IPV6 = YesPlease
- NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
- NO_NSEC = YesPlease
- NEEDS_LIBGEN =
- NEEDS_CRYPTO_WITH_SSL = YesPlease
- NEEDS_IDN_WITH_CURL = YesPlease
- NEEDS_SSL_WITH_CURL = YesPlease
- NEEDS_RESOLV =
- NO_HSTRERROR = YesPlease
- NO_MMAP = YesPlease
- NO_CURL =
- NO_EXPAT =
-endif
-ifeq ($(uname_S),NONSTOP_KERNEL)
- # Needs some C99 features, "inline" is just one of them.
- # INLINE='' would just replace one set of warnings with another and
- # still not compile in c89 mode, due to non-const array initializations.
- CC = cc -c99
- # Disable all optimization, seems to result in bad code, with -O or -O2
- # or even -O1 (default), /usr/local/libexec/git-core/git-pack-objects
- # abends on "git push". Needs more investigation.
- CFLAGS = -g -O0
- # We'd want it to be here.
- prefix = /usr/local
- # Our's are in ${prefix}/bin (perl might also be in /usr/bin/perl).
- PERL_PATH = ${prefix}/bin/perl
- PYTHON_PATH = ${prefix}/bin/python
-
- # As detected by './configure'.
- # Missdetected, hence commented out, see below.
- #NO_CURL = YesPlease
- # Added manually, see above.
- NEEDS_SSL_WITH_CURL = YesPlease
- HAVE_LIBCHARSET_H = YesPlease
- NEEDS_LIBICONV = YesPlease
- NEEDS_LIBINTL_BEFORE_LIBICONV = YesPlease
- NO_SYS_SELECT_H = UnfortunatelyYes
- NO_D_TYPE_IN_DIRENT = YesPlease
- NO_HSTRERROR = YesPlease
- NO_STRCASESTR = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
- NO_MEMMEM = YesPlease
- NO_STRLCPY = YesPlease
- NO_SETENV = YesPlease
- NO_UNSETENV = YesPlease
- NO_MKDTEMP = YesPlease
- NO_MKSTEMPS = YesPlease
- # Currently libiconv-1.9.1.
- OLD_ICONV = UnfortunatelyYes
- NO_REGEX = YesPlease
- NO_PTHREADS = UnfortunatelyYes
-
- # Not detected (nor checked for) by './configure'.
- # We don't have SA_RESTART on NonStop, unfortunalety.
- COMPAT_CFLAGS += -DSA_RESTART=0
- # Apparently needed in compat/fnmatch/fnmatch.c.
- COMPAT_CFLAGS += -DHAVE_STRING_H=1
- NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
- NO_NSEC = YesPlease
- NO_PREAD = YesPlease
- NO_MMAP = YesPlease
- NO_POLL = YesPlease
- NO_INTPTR_T = UnfortunatelyYes
- # Bug report 10-120822-4477 submitted to HP NonStop development.
- MKDIR_WO_TRAILING_SLASH = YesPlease
- # RFE 10-120912-4693 submitted to HP NonStop development.
- NO_SETITIMER = UnfortunatelyYes
- SANE_TOOL_PATH = /usr/coreutils/bin:/usr/local/bin
- SHELL_PATH = /usr/local/bin/bash
- # as of H06.25/J06.14, we might better use this
- #SHELL_PATH = /usr/coreutils/bin/bash
-endif
-ifneq (,$(findstring MINGW,$(uname_S)))
- pathsep = ;
- NO_PREAD = YesPlease
- NEEDS_CRYPTO_WITH_SSL = YesPlease
- NO_LIBGEN_H = YesPlease
- NO_POLL = YesPlease
- NO_SYMLINK_HEAD = YesPlease
- NO_UNIX_SOCKETS = YesPlease
- NO_SETENV = YesPlease
- NO_UNSETENV = YesPlease
- NO_STRCASESTR = YesPlease
- NO_STRLCPY = YesPlease
- NO_STRTOK_R = YesPlease
- NO_FNMATCH = YesPlease
- NO_MEMMEM = YesPlease
- NEEDS_LIBICONV = YesPlease
- OLD_ICONV = YesPlease
- NO_STRTOUMAX = YesPlease
- NO_MKDTEMP = YesPlease
- NO_MKSTEMPS = YesPlease
- NO_SVN_TESTS = YesPlease
- NO_PERL_MAKEMAKER = YesPlease
- RUNTIME_PREFIX = YesPlease
- NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
- NO_NSEC = YesPlease
- USE_WIN32_MMAP = YesPlease
- USE_NED_ALLOCATOR = YesPlease
- UNRELIABLE_FSTAT = UnfortunatelyYes
- OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
- NO_REGEX = YesPlease
- NO_PYTHON = YesPlease
- BLK_SHA1 = YesPlease
- ETAGS_TARGET = ETAGS
- NO_INET_PTON = YesPlease
- NO_INET_NTOP = YesPlease
- NO_POSIX_GOODIES = UnfortunatelyYes
- COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/win32
- COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
- COMPAT_OBJS += compat/mingw.o compat/winansi.o \
- compat/win32/pthread.o compat/win32/syslog.o \
- compat/win32/dirent.o
- EXTLIBS += -lws2_32
- PTHREAD_LIBS =
- X = .exe
- SPARSE_FLAGS = -Wno-one-bit-signed-bitfield
-ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
- htmldir = doc/git/html/
- prefix =
- INSTALL = /bin/install
- EXTLIBS += /mingw/lib/libz.a
- NO_R_TO_GCC_LINKER = YesPlease
- INTERNAL_QSORT = YesPlease
- HAVE_LIBCHARSET_H = YesPlease
-else
- NO_CURL = YesPlease
-endif
-endif
-
+include config.mak.uname
-include config.mak.autogen
-include config.mak
@@ -1659,6 +1146,9 @@ endif
ifdef NO_D_INO_IN_DIRENT
BASIC_CFLAGS += -DNO_D_INO_IN_DIRENT
endif
+ifdef NO_GECOS_IN_PWENT
+ BASIC_CFLAGS += -DNO_GECOS_IN_PWENT
+endif
ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
endif
@@ -1752,6 +1242,9 @@ endif
ifdef NO_SYS_POLL_H
BASIC_CFLAGS += -DNO_SYS_POLL_H
endif
+ifdef NEEDS_SYS_PARAM_H
+ BASIC_CFLAGS += -DNEEDS_SYS_PARAM_H
+endif
ifdef NO_INTTYPES_H
BASIC_CFLAGS += -DNO_INTTYPES_H
endif
@@ -1863,6 +1356,9 @@ ifdef NO_MEMMEM
COMPAT_CFLAGS += -DNO_MEMMEM
COMPAT_OBJS += compat/memmem.o
endif
+ifdef NO_GETPAGESIZE
+ COMPAT_CFLAGS += -DNO_GETPAGESIZE
+endif
ifdef INTERNAL_QSORT
COMPAT_CFLAGS += -DINTERNAL_QSORT
COMPAT_OBJS += compat/qsort.o
@@ -1888,6 +1384,10 @@ ifdef HAVE_LIBCHARSET_H
EXTLIBS += $(CHARSET_LIB)
endif
+ifdef HAVE_STRINGS_H
+ BASIC_CFLAGS += -DHAVE_STRINGS_H
+endif
+
ifdef HAVE_DEV_TTY
BASIC_CFLAGS += -DHAVE_DEV_TTY
endif
@@ -2187,7 +1687,7 @@ endef
GIT-SCRIPT-DEFINES: FORCE
@FLAGS='$(SCRIPT_DEFINES)'; \
if test x"$$FLAGS" != x"`cat $@ 2>/dev/null`" ; then \
- echo 1>&2 " * new script parameters"; \
+ echo >&2 " * new script parameters"; \
echo "$$FLAGS" >$@; \
fi
@@ -2574,7 +2074,7 @@ TRACK_PREFIX = $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):\
GIT-PREFIX: FORCE
@FLAGS='$(TRACK_PREFIX)'; \
if test x"$$FLAGS" != x"`cat GIT-PREFIX 2>/dev/null`" ; then \
- echo 1>&2 " * new prefix flags"; \
+ echo >&2 " * new prefix flags"; \
echo "$$FLAGS" >GIT-PREFIX; \
fi
@@ -2583,7 +2083,7 @@ TRACK_CFLAGS = $(CC):$(subst ','\'',$(ALL_CFLAGS)):$(USE_GETTEXT_SCHEME)
GIT-CFLAGS: FORCE
@FLAGS='$(TRACK_CFLAGS)'; \
if test x"$$FLAGS" != x"`cat GIT-CFLAGS 2>/dev/null`" ; then \
- echo 1>&2 " * new build flags"; \
+ echo >&2 " * new build flags"; \
echo "$$FLAGS" >GIT-CFLAGS; \
fi
@@ -2592,7 +2092,7 @@ TRACK_LDFLAGS = $(subst ','\'',$(ALL_LDFLAGS))
GIT-LDFLAGS: FORCE
@FLAGS='$(TRACK_LDFLAGS)'; \
if test x"$$FLAGS" != x"`cat GIT-LDFLAGS 2>/dev/null`" ; then \
- echo 1>&2 " * new link flags"; \
+ echo >&2 " * new link flags"; \
echo "$$FLAGS" >GIT-LDFLAGS; \
fi
@@ -2634,18 +2134,6 @@ ifdef GIT_PERF_MAKE_OPTS
@echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@
endif
-### Detect Tck/Tk interpreter path changes
-ifndef NO_TCLTK
-TRACK_VARS = $(subst ','\'',-DTCLTK_PATH='$(TCLTK_PATH_SQ)')
-
-GIT-GUI-VARS: FORCE
- @VARS='$(TRACK_VARS)'; \
- if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
- echo 1>&2 " * new Tcl/Tk interpreter location"; \
- echo "$$VARS" >$@; \
- fi
-endif
-
### Detect Python interpreter path changes
ifndef NO_PYTHON
TRACK_PYTHON = $(subst ','\'',-DPYTHON_PATH='$(PYTHON_PATH_SQ)')
@@ -2653,7 +2141,7 @@ TRACK_PYTHON = $(subst ','\'',-DPYTHON_PATH='$(PYTHON_PATH_SQ)')
GIT-PYTHON-VARS: FORCE
@VARS='$(TRACK_PYTHON)'; \
if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
- echo 1>&2 " * new Python interpreter location"; \
+ echo >&2 " * new Python interpreter location"; \
echo "$$VARS" >$@; \
fi
endif
@@ -2932,7 +2420,7 @@ ifndef NO_TCLTK
$(MAKE) -C gitk-git clean
$(MAKE) -C git-gui clean
endif
- $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS
+ $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-BUILD-OPTIONS
$(RM) GIT-USER-AGENT GIT-PREFIX GIT-SCRIPT-DEFINES GIT-PYTHON-VARS
.PHONY: all install profile-clean clean strip
diff --git a/RelNotes b/RelNotes
index 5964e1c4ca..bdce3136ea 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.8.1.1.txt \ No newline at end of file
+Documentation/RelNotes/1.8.2.txt \ No newline at end of file
diff --git a/abspath.c b/abspath.c
index 05f2d79348..40cdc46219 100644
--- a/abspath.c
+++ b/abspath.c
@@ -15,16 +15,34 @@ int is_directory(const char *path)
#define MAXDEPTH 5
/*
- * Use this to get the real path, i.e. resolve links. If you want an
- * absolute path but don't mind links, use absolute_path.
+ * Return the real path (i.e., absolute path, with symlinks resolved
+ * and extra slashes removed) equivalent to the specified path. (If
+ * you want an absolute path but don't mind links, use
+ * absolute_path().) The return value is a pointer to a static
+ * buffer.
+ *
+ * The input and all intermediate paths must be shorter than MAX_PATH.
+ * The directory part of path (i.e., everything up to the last
+ * dir_sep) must denote a valid, existing directory, but the last
+ * component need not exist. If die_on_error is set, then die with an
+ * informative error message if there is a problem. Otherwise, return
+ * NULL on errors (without generating any output).
*
* If path is our buffer, then return path, as it's already what the
* user wants.
*/
-const char *real_path(const char *path)
+static const char *real_path_internal(const char *path, int die_on_error)
{
static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
+ char *retval = NULL;
+
+ /*
+ * If we have to temporarily chdir(), store the original CWD
+ * here so that we can chdir() back to it at the end of the
+ * function:
+ */
char cwd[1024] = "";
+
int buf_index = 1;
int depth = MAXDEPTH;
@@ -35,11 +53,19 @@ const char *real_path(const char *path)
if (path == buf || path == next_buf)
return path;
- if (!*path)
- die("The empty string is not a valid path");
+ if (!*path) {
+ if (die_on_error)
+ die("The empty string is not a valid path");
+ else
+ goto error_out;
+ }
- if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
- die ("Too long path: %.*s", 60, path);
+ if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) {
+ if (die_on_error)
+ die("Too long path: %.*s", 60, path);
+ else
+ goto error_out;
+ }
while (depth--) {
if (!is_directory(buf)) {
@@ -54,20 +80,36 @@ const char *real_path(const char *path)
}
if (*buf) {
- if (!*cwd && !getcwd(cwd, sizeof(cwd)))
- die_errno ("Could not get current working directory");
+ if (!*cwd && !getcwd(cwd, sizeof(cwd))) {
+ if (die_on_error)
+ die_errno("Could not get current working directory");
+ else
+ goto error_out;
+ }
- if (chdir(buf))
- die_errno ("Could not switch to '%s'", buf);
+ if (chdir(buf)) {
+ if (die_on_error)
+ die_errno("Could not switch to '%s'", buf);
+ else
+ goto error_out;
+ }
+ }
+ if (!getcwd(buf, PATH_MAX)) {
+ if (die_on_error)
+ die_errno("Could not get current working directory");
+ else
+ goto error_out;
}
- if (!getcwd(buf, PATH_MAX))
- die_errno ("Could not get current working directory");
if (last_elem) {
size_t len = strlen(buf);
- if (len + strlen(last_elem) + 2 > PATH_MAX)
- die ("Too long path name: '%s/%s'",
- buf, last_elem);
+ if (len + strlen(last_elem) + 2 > PATH_MAX) {
+ if (die_on_error)
+ die("Too long path name: '%s/%s'",
+ buf, last_elem);
+ else
+ goto error_out;
+ }
if (len && !is_dir_sep(buf[len-1]))
buf[len++] = '/';
strcpy(buf + len, last_elem);
@@ -77,10 +119,18 @@ const char *real_path(const char *path)
if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
ssize_t len = readlink(buf, next_buf, PATH_MAX);
- if (len < 0)
- die_errno ("Invalid symlink '%s'", buf);
- if (PATH_MAX <= len)
- die("symbolic link too long: %s", buf);
+ if (len < 0) {
+ if (die_on_error)
+ die_errno("Invalid symlink '%s'", buf);
+ else
+ goto error_out;
+ }
+ if (PATH_MAX <= len) {
+ if (die_on_error)
+ die("symbolic link too long: %s", buf);
+ else
+ goto error_out;
+ }
next_buf[len] = '\0';
buf = next_buf;
buf_index = 1 - buf_index;
@@ -89,10 +139,23 @@ const char *real_path(const char *path)
break;
}
+ retval = buf;
+error_out:
+ free(last_elem);
if (*cwd && chdir(cwd))
die_errno ("Could not change back to '%s'", cwd);
- return buf;
+ return retval;
+}
+
+const char *real_path(const char *path)
+{
+ return real_path_internal(path, 1);
+}
+
+const char *real_path_if_valid(const char *path)
+{
+ return real_path_internal(path, 0);
}
static const char *get_pwd_cwd(void)
diff --git a/advice.c b/advice.c
index edfbd4a6fb..d287927280 100644
--- a/advice.c
+++ b/advice.c
@@ -1,9 +1,10 @@
#include "cache.h"
-int advice_push_nonfastforward = 1;
+int advice_push_update_rejected = 1;
int advice_push_non_ff_current = 1;
int advice_push_non_ff_default = 1;
int advice_push_non_ff_matching = 1;
+int advice_push_already_exists = 1;
int advice_status_hints = 1;
int advice_commit_before_merge = 1;
int advice_resolve_conflict = 1;
@@ -14,15 +15,19 @@ static struct {
const char *name;
int *preference;
} advice_config[] = {
- { "pushnonfastforward", &advice_push_nonfastforward },
+ { "pushupdaterejected", &advice_push_update_rejected },
{ "pushnonffcurrent", &advice_push_non_ff_current },
{ "pushnonffdefault", &advice_push_non_ff_default },
{ "pushnonffmatching", &advice_push_non_ff_matching },
+ { "pushalreadyexists", &advice_push_already_exists },
{ "statushints", &advice_status_hints },
{ "commitbeforemerge", &advice_commit_before_merge },
{ "resolveconflict", &advice_resolve_conflict },
{ "implicitidentity", &advice_implicit_identity },
{ "detachedhead", &advice_detached_head },
+
+ /* make this an alias for backward compatibility */
+ { "pushnonfastforward", &advice_push_update_rejected }
};
void advise(const char *advice, ...)
diff --git a/advice.h b/advice.h
index f3cdbbf29e..8bf63563a5 100644
--- a/advice.h
+++ b/advice.h
@@ -3,10 +3,11 @@
#include "git-compat-util.h"
-extern int advice_push_nonfastforward;
+extern int advice_push_update_rejected;
extern int advice_push_non_ff_current;
extern int advice_push_non_ff_default;
extern int advice_push_non_ff_matching;
+extern int advice_push_already_exists;
extern int advice_status_hints;
extern int advice_commit_before_merge;
extern int advice_resolve_conflict;
diff --git a/archive-zip.c b/archive-zip.c
index 55f66b4060..d3aef532b7 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -240,7 +240,7 @@ static int write_zip_entry(struct archiver_args *args,
(mode & 0111) ? ((mode) << 16) : 0;
if (S_ISREG(mode) && args->compression_level != 0 && size > 0)
method = 8;
- compressed_size = size;
+ compressed_size = (method == 0) ? size : 0;
if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
size > big_file_threshold) {
@@ -313,10 +313,7 @@ static int write_zip_entry(struct archiver_args *args,
copy_le16(header.compression_method, method);
copy_le16(header.mtime, zip_time);
copy_le16(header.mdate, zip_date);
- if (flags & ZIP_STREAM)
- set_zip_header_data_desc(&header, 0, 0, 0);
- else
- set_zip_header_data_desc(&header, size, compressed_size, crc);
+ set_zip_header_data_desc(&header, size, compressed_size, crc);
copy_le16(header.filename_length, pathlen);
copy_le16(header.extra_length, ZIP_EXTRA_MTIME_SIZE);
write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
diff --git a/attr.c b/attr.c
index 466c93fa50..233539969a 100644
--- a/attr.c
+++ b/attr.c
@@ -284,7 +284,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
* (reading the file from top to bottom), .gitattribute of the root
* directory (again, reading the file from top to bottom) down to the
* current directory, and then scan the list backwards to find the first match.
- * This is exactly the same as what excluded() does in dir.c to deal with
+ * This is exactly the same as what is_excluded() does in dir.c to deal with
* .gitignore
*/
@@ -704,7 +704,7 @@ static int fill_one(const char *what, struct match_attr *a, int rem)
if (*n == ATTR__UNKNOWN) {
debug_set(what,
- a->is_macro ? a->u.attr->name : a->u.pattern,
+ a->is_macro ? a->u.attr->name : a->u.pat.pattern,
attr, v);
*n = v;
rem--;
diff --git a/builtin/add.c b/builtin/add.c
index e664100c71..075312afcd 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -454,7 +454,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
&& !file_exists(pathspec[i])) {
if (ignore_missing) {
int dtype = DT_UNKNOWN;
- if (path_excluded(&check, pathspec[i], -1, &dtype))
+ if (is_path_excluded(&check, pathspec[i], -1, &dtype))
dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
} else
die(_("pathspec '%s' did not match any files"),
diff --git a/builtin/blame.c b/builtin/blame.c
index cfae569905..b431ba3209 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -42,6 +42,7 @@ static int blank_boundary;
static int incremental;
static int xdl_opts;
static int abbrev = -1;
+static int no_whole_file_rename;
static enum date_mode blame_date_mode = DATE_ISO8601;
static size_t blame_date_width;
@@ -1226,7 +1227,7 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
* The first pass looks for unrenamed path to optimize for
* common cases, then we look for renames in the second pass.
*/
- for (pass = 0; pass < 2; pass++) {
+ for (pass = 0; pass < 2 - no_whole_file_rename; pass++) {
struct origin *(*find)(struct scoreboard *,
struct commit *, struct origin *);
find = pass ? find_rename : find_origin;
@@ -1321,30 +1322,31 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
* Information on commits, used for output.
*/
struct commit_info {
- const char *author;
- const char *author_mail;
+ struct strbuf author;
+ struct strbuf author_mail;
unsigned long author_time;
- const char *author_tz;
+ struct strbuf author_tz;
/* filled only when asked for details */
- const char *committer;
- const char *committer_mail;
+ struct strbuf committer;
+ struct strbuf committer_mail;
unsigned long committer_time;
- const char *committer_tz;
+ struct strbuf committer_tz;
- const char *summary;
+ struct strbuf summary;
};
/*
* Parse author/committer line in the commit object buffer
*/
static void get_ac_line(const char *inbuf, const char *what,
- int person_len, char *person,
- int mail_len, char *mail,
- unsigned long *time, const char **tz)
+ struct strbuf *name, struct strbuf *mail,
+ unsigned long *time, struct strbuf *tz)
{
- int len, tzlen, maillen;
- char *tmp, *endp, *timepos, *mailpos;
+ struct ident_split ident;
+ size_t len, maillen, namelen;
+ char *tmp, *endp;
+ const char *namebuf, *mailbuf;
tmp = strstr(inbuf, what);
if (!tmp)
@@ -1355,69 +1357,61 @@ static void get_ac_line(const char *inbuf, const char *what,
len = strlen(tmp);
else
len = endp - tmp;
- if (person_len <= len) {
+
+ if (split_ident_line(&ident, tmp, len)) {
error_out:
/* Ugh */
- *tz = "(unknown)";
- strcpy(person, *tz);
- strcpy(mail, *tz);
+ tmp = "(unknown)";
+ strbuf_addstr(name, tmp);
+ strbuf_addstr(mail, tmp);
+ strbuf_addstr(tz, tmp);
*time = 0;
return;
}
- memcpy(person, tmp, len);
- tmp = person;
- tmp += len;
- *tmp = 0;
- while (person < tmp && *tmp != ' ')
- tmp--;
- if (tmp <= person)
- goto error_out;
- *tz = tmp+1;
- tzlen = (person+len)-(tmp+1);
+ namelen = ident.name_end - ident.name_begin;
+ namebuf = ident.name_begin;
- *tmp = 0;
- while (person < tmp && *tmp != ' ')
- tmp--;
- if (tmp <= person)
- goto error_out;
- *time = strtoul(tmp, NULL, 10);
- timepos = tmp;
+ maillen = ident.mail_end - ident.mail_begin;
+ mailbuf = ident.mail_begin;
- *tmp = 0;
- while (person < tmp && !(*tmp == ' ' && tmp[1] == '<'))
- tmp--;
- if (tmp <= person)
- return;
- mailpos = tmp + 1;
- *tmp = 0;
- maillen = timepos - tmp;
- memcpy(mail, mailpos, maillen);
+ *time = strtoul(ident.date_begin, NULL, 10);
- if (!mailmap.nr)
- return;
-
- /*
- * mailmap expansion may make the name longer.
- * make room by pushing stuff down.
- */
- tmp = person + person_len - (tzlen + 1);
- memmove(tmp, *tz, tzlen);
- tmp[tzlen] = 0;
- *tz = tmp;
+ len = ident.tz_end - ident.tz_begin;
+ strbuf_add(tz, ident.tz_begin, len);
/*
* Now, convert both name and e-mail using mailmap
*/
- if (map_user(&mailmap, mail+1, mail_len-1, person, tmp-person-1)) {
- /* Add a trailing '>' to email, since map_user returns plain emails
- Note: It already has '<', since we replace from mail+1 */
- mailpos = memchr(mail, '\0', mail_len);
- if (mailpos && mailpos-mail < mail_len - 1) {
- *mailpos = '>';
- *(mailpos+1) = '\0';
- }
- }
+ map_user(&mailmap, &mailbuf, &maillen,
+ &namebuf, &namelen);
+
+ strbuf_addf(mail, "<%.*s>", (int)maillen, mailbuf);
+ strbuf_add(name, namebuf, namelen);
+}
+
+static void commit_info_init(struct commit_info *ci)
+{
+
+ strbuf_init(&ci->author, 0);
+ strbuf_init(&ci->author_mail, 0);
+ strbuf_init(&ci->author_tz, 0);
+ strbuf_init(&ci->committer, 0);
+ strbuf_init(&ci->committer_mail, 0);
+ strbuf_init(&ci->committer_tz, 0);
+ strbuf_init(&ci->summary, 0);
+}
+
+static void commit_info_destroy(struct commit_info *ci)
+{
+
+ strbuf_release(&ci->author);
+ strbuf_release(&ci->author_mail);
+ strbuf_release(&ci->author_tz);
+ strbuf_release(&ci->committer);
+ strbuf_release(&ci->committer_mail);
+ strbuf_release(&ci->committer_tz);
+ strbuf_release(&ci->summary);
}
static void get_commit_info(struct commit *commit,
@@ -1427,11 +1421,8 @@ static void get_commit_info(struct commit *commit,
int len;
const char *subject, *encoding;
char *reencoded, *message;
- static char author_name[1024];
- static char author_mail[1024];
- static char committer_name[1024];
- static char committer_mail[1024];
- static char summary_buf[1024];
+
+ commit_info_init(ret);
/*
* We've operated without save_commit_buffer, so
@@ -1449,11 +1440,8 @@ static void get_commit_info(struct commit *commit,
encoding = get_log_output_encoding();
reencoded = logmsg_reencode(commit, encoding);
message = reencoded ? reencoded : commit->buffer;
- ret->author = author_name;
- ret->author_mail = author_mail;
get_ac_line(message, "\nauthor ",
- sizeof(author_name), author_name,
- sizeof(author_mail), author_mail,
+ &ret->author, &ret->author_mail,
&ret->author_time, &ret->author_tz);
if (!detailed) {
@@ -1461,21 +1449,16 @@ static void get_commit_info(struct commit *commit,
return;
}
- ret->committer = committer_name;
- ret->committer_mail = committer_mail;
get_ac_line(message, "\ncommitter ",
- sizeof(committer_name), committer_name,
- sizeof(committer_mail), committer_mail,
+ &ret->committer, &ret->committer_mail,
&ret->committer_time, &ret->committer_tz);
- ret->summary = summary_buf;
len = find_commit_subject(message, &subject);
- if (len && len < sizeof(summary_buf)) {
- memcpy(summary_buf, subject, len);
- summary_buf[len] = 0;
- } else {
- sprintf(summary_buf, "(%s)", sha1_to_hex(commit->object.sha1));
- }
+ if (len)
+ strbuf_add(&ret->summary, subject, len);
+ else
+ strbuf_addf(&ret->summary, "(%s)", sha1_to_hex(commit->object.sha1));
+
free(reencoded);
}
@@ -1504,15 +1487,15 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat)
suspect->commit->object.flags |= METAINFO_SHOWN;
get_commit_info(suspect->commit, &ci, 1);
- printf("author %s\n", ci.author);
- printf("author-mail %s\n", ci.author_mail);
+ printf("author %s\n", ci.author.buf);
+ printf("author-mail %s\n", ci.author_mail.buf);
printf("author-time %lu\n", ci.author_time);
- printf("author-tz %s\n", ci.author_tz);
- printf("committer %s\n", ci.committer);
- printf("committer-mail %s\n", ci.committer_mail);
+ printf("author-tz %s\n", ci.author_tz.buf);
+ printf("committer %s\n", ci.committer.buf);
+ printf("committer-mail %s\n", ci.committer_mail.buf);
printf("committer-time %lu\n", ci.committer_time);
- printf("committer-tz %s\n", ci.committer_tz);
- printf("summary %s\n", ci.summary);
+ printf("committer-tz %s\n", ci.committer_tz.buf);
+ printf("summary %s\n", ci.summary.buf);
if (suspect->commit->object.flags & UNINTERESTING)
printf("boundary\n");
if (suspect->previous) {
@@ -1520,6 +1503,9 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat)
printf("previous %s ", sha1_to_hex(prev->commit->object.sha1));
write_name_quoted(prev->path, stdout, '\n');
}
+
+ commit_info_destroy(&ci);
+
return 1;
}
@@ -1706,11 +1692,11 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt)
if (opt & OUTPUT_ANNOTATE_COMPAT) {
const char *name;
if (opt & OUTPUT_SHOW_EMAIL)
- name = ci.author_mail;
+ name = ci.author_mail.buf;
else
- name = ci.author;
+ name = ci.author.buf;
printf("\t(%10s\t%10s\t%d)", name,
- format_time(ci.author_time, ci.author_tz,
+ format_time(ci.author_time, ci.author_tz.buf,
show_raw_time),
ent->lno + 1 + cnt);
} else {
@@ -1729,14 +1715,14 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt)
const char *name;
int pad;
if (opt & OUTPUT_SHOW_EMAIL)
- name = ci.author_mail;
+ name = ci.author_mail.buf;
else
- name = ci.author;
+ name = ci.author.buf;
pad = longest_author - utf8_strwidth(name);
printf(" (%s%*s %10s",
name, pad, "",
format_time(ci.author_time,
- ci.author_tz,
+ ci.author_tz.buf,
show_raw_time));
}
printf(" %*d) ",
@@ -1751,6 +1737,8 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt)
if (sb->final_buf_size && cp[-1] != '\n')
putchar('\n');
+
+ commit_info_destroy(&ci);
}
static void output(struct scoreboard *sb, int option)
@@ -1875,9 +1863,9 @@ static void find_alignment(struct scoreboard *sb, int *option)
suspect->commit->object.flags |= METAINFO_SHOWN;
get_commit_info(suspect->commit, &ci, 1);
if (*option & OUTPUT_SHOW_EMAIL)
- num = utf8_strwidth(ci.author_mail);
+ num = utf8_strwidth(ci.author_mail.buf);
else
- num = utf8_strwidth(ci.author);
+ num = utf8_strwidth(ci.author.buf);
if (longest_author < num)
longest_author = num;
}
@@ -1889,6 +1877,8 @@ static void find_alignment(struct scoreboard *sb, int *option)
longest_dst_lines = num;
if (largest_score < ent_score(sb, e))
largest_score = ent_score(sb, e);
+
+ commit_info_destroy(&ci);
}
max_orig_digits = decimal_width(longest_src_lines);
max_digits = decimal_width(longest_dst_lines);
@@ -2403,6 +2393,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
init_revisions(&revs, NULL);
revs.date_mode = blame_date_mode;
DIFF_OPT_SET(&revs.diffopt, ALLOW_TEXTCONV);
+ DIFF_OPT_SET(&revs.diffopt, FOLLOW_RENAMES);
save_commit_buffer = 0;
dashdash_pos = 0;
@@ -2426,6 +2417,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
parse_revision_opt(&revs, &ctx, options, blame_opt_usage);
}
parse_done:
+ no_whole_file_rename = !DIFF_OPT_TST(&revs.diffopt, FOLLOW_RENAMES);
+ DIFF_OPT_CLR(&revs.diffopt, FOLLOW_RENAMES);
argc = parse_options_end(&ctx);
if (0 < abbrev)
diff --git a/builtin/branch.c b/builtin/branch.c
index 1ec9c02612..873f624d1c 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -725,7 +725,7 @@ static int edit_branch_description(const char *branch_name)
stripspace(&buf, 1);
strbuf_addf(&name, "branch.%s.description", branch_name);
- status = git_config_set(name.buf, buf.buf);
+ status = git_config_set(name.buf, buf.len ? buf.buf : NULL);
strbuf_release(&name);
strbuf_release(&buf);
diff --git a/builtin/clean.c b/builtin/clean.c
index 69c1cda906..f4b760bf3d 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -10,6 +10,7 @@
#include "cache.h"
#include "dir.h"
#include "parse-options.h"
+#include "refs.h"
#include "string-list.h"
#include "quote.h"
@@ -20,6 +21,12 @@ static const char *const builtin_clean_usage[] = {
NULL
};
+static const char *msg_remove = N_("Removing %s\n");
+static const char *msg_would_remove = N_("Would remove %s\n");
+static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
+static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
+static const char *msg_warn_remove_failed = N_("failed to remove %s");
+
static int git_clean_config(const char *var, const char *value, void *cb)
{
if (!strcmp(var, "clean.requireforce"))
@@ -34,11 +41,112 @@ static int exclude_cb(const struct option *opt, const char *arg, int unset)
return 0;
}
+static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
+ int dry_run, int quiet, int *dir_gone)
+{
+ DIR *dir;
+ struct strbuf quoted = STRBUF_INIT;
+ struct dirent *e;
+ int res = 0, ret = 0, gone = 1, original_len = path->len, len, i;
+ unsigned char submodule_head[20];
+ struct string_list dels = STRING_LIST_INIT_DUP;
+
+ *dir_gone = 1;
+
+ if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
+ !resolve_gitlink_ref(path->buf, "HEAD", submodule_head)) {
+ if (!quiet) {
+ quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+ printf(dry_run ? _(msg_would_skip_git_dir) : _(msg_skip_git_dir),
+ quoted.buf);
+ }
+
+ *dir_gone = 0;
+ return 0;
+ }
+
+ dir = opendir(path->buf);
+ if (!dir) {
+ /* an empty dir could be removed even if it is unreadble */
+ res = dry_run ? 0 : rmdir(path->buf);
+ if (res) {
+ quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+ warning(_(msg_warn_remove_failed), quoted.buf);
+ *dir_gone = 0;
+ }
+ return res;
+ }
+
+ if (path->buf[original_len - 1] != '/')
+ strbuf_addch(path, '/');
+
+ len = path->len;
+ while ((e = readdir(dir)) != NULL) {
+ struct stat st;
+ if (is_dot_or_dotdot(e->d_name))
+ continue;
+
+ strbuf_setlen(path, len);
+ strbuf_addstr(path, e->d_name);
+ if (lstat(path->buf, &st))
+ ; /* fall thru */
+ else if (S_ISDIR(st.st_mode)) {
+ if (remove_dirs(path, prefix, force_flag, dry_run, quiet, &gone))
+ ret = 1;
+ if (gone) {
+ quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+ string_list_append(&dels, quoted.buf);
+ } else
+ *dir_gone = 0;
+ continue;
+ } else {
+ res = dry_run ? 0 : unlink(path->buf);
+ if (!res) {
+ quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+ string_list_append(&dels, quoted.buf);
+ } else {
+ quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+ warning(_(msg_warn_remove_failed), quoted.buf);
+ *dir_gone = 0;
+ ret = 1;
+ }
+ continue;
+ }
+
+ /* path too long, stat fails, or non-directory still exists */
+ *dir_gone = 0;
+ ret = 1;
+ break;
+ }
+ closedir(dir);
+
+ strbuf_setlen(path, original_len);
+
+ if (*dir_gone) {
+ res = dry_run ? 0 : rmdir(path->buf);
+ if (!res)
+ *dir_gone = 1;
+ else {
+ quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+ warning(_(msg_warn_remove_failed), quoted.buf);
+ *dir_gone = 0;
+ ret = 1;
+ }
+ }
+
+ if (!*dir_gone && !quiet) {
+ for (i = 0; i < dels.nr; i++)
+ printf(dry_run ? _(msg_would_remove) : _(msg_remove), dels.items[i].string);
+ }
+ string_list_clear(&dels, 0);
+ return ret;
+}
+
int cmd_clean(int argc, const char **argv, const char *prefix)
{
- int i;
- int show_only = 0, remove_directories = 0, quiet = 0, ignored = 0;
- int ignored_only = 0, config_set = 0, errors = 0;
+ int i, res;
+ int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
+ int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
struct strbuf directory = STRBUF_INIT;
struct dir_struct dir;
@@ -49,7 +157,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
char *seen = NULL;
struct option options[] = {
OPT__QUIET(&quiet, N_("do not print names of files removed")),
- OPT__DRY_RUN(&show_only, N_("dry run")),
+ OPT__DRY_RUN(&dry_run, N_("dry run")),
OPT__FORCE(&force, N_("force")),
OPT_BOOLEAN('d', NULL, &remove_directories,
N_("remove whole directories")),
@@ -77,7 +185,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (ignored && ignored_only)
die(_("-x and -X cannot be used together"));
- if (!show_only && !force) {
+ if (!dry_run && !force) {
if (config_set)
die(_("clean.requireForce set to true and neither -n nor -f given; "
"refusing to clean"));
@@ -149,38 +257,26 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (S_ISDIR(st.st_mode)) {
strbuf_addstr(&directory, ent->name);
- qname = quote_path_relative(directory.buf, directory.len, &buf, prefix);
- if (show_only && (remove_directories ||
- (matches == MATCHED_EXACTLY))) {
- printf(_("Would remove %s\n"), qname);
- } else if (remove_directories ||
- (matches == MATCHED_EXACTLY)) {
- if (!quiet)
- printf(_("Removing %s\n"), qname);
- if (remove_dir_recursively(&directory,
- rm_flags) != 0) {
- warning(_("failed to remove %s"), qname);
+ if (remove_directories || (matches == MATCHED_EXACTLY)) {
+ if (remove_dirs(&directory, prefix, rm_flags, dry_run, quiet, &gone))
errors++;
+ if (gone && !quiet) {
+ qname = quote_path_relative(directory.buf, directory.len, &buf, prefix);
+ printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
}
- } else if (show_only) {
- printf(_("Would not remove %s\n"), qname);
- } else {
- printf(_("Not removing %s\n"), qname);
}
strbuf_reset(&directory);
} else {
if (pathspec && !matches)
continue;
- qname = quote_path_relative(ent->name, -1, &buf, prefix);
- if (show_only) {
- printf(_("Would remove %s\n"), qname);
- continue;
- } else if (!quiet) {
- printf(_("Removing %s\n"), qname);
- }
- if (unlink(ent->name) != 0) {
- warning(_("failed to remove %s"), qname);
+ res = dry_run ? 0 : unlink(ent->name);
+ if (res) {
+ qname = quote_path_relative(ent->name, -1, &buf, prefix);
+ warning(_(msg_warn_remove_failed), qname);
errors++;
+ } else if (!quiet) {
+ qname = quote_path_relative(ent->name, -1, &buf, prefix);
+ printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
}
}
}
diff --git a/builtin/clone.c b/builtin/clone.c
index 8d23a62e8a..36ec99db3f 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -704,6 +704,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_origin)
die(_("--bare and --origin %s options are incompatible."),
option_origin);
+ if (real_git_dir)
+ die(_("--bare and --separate-git-dir are incompatible."));
option_no_checkout = 1;
}
diff --git a/builtin/commit.c b/builtin/commit.c
index d6dd3df8b1..7c2a3d48b4 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -103,7 +103,7 @@ static enum {
CLEANUP_NONE,
CLEANUP_ALL
} cleanup_mode;
-static char *cleanup_arg;
+static const char *cleanup_arg;
static enum commit_whence whence;
static int use_editor = 1, include_status = 1;
@@ -1320,6 +1320,8 @@ static int git_commit_config(const char *k, const char *v, void *cb)
include_status = git_config_bool(k, v);
return 0;
}
+ if (!strcmp(k, "commit.cleanup"))
+ return git_config_string(&cleanup_arg, k, v);
status = git_gpg_config(k, v, NULL);
if (status)
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 12220ad8da..77dffd1ce3 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -474,18 +474,21 @@ static void handle_tag(const char *name, struct tag *tag)
(int)message_size, (int)message_size, message ? message : "");
}
-static void get_tags_and_duplicates(struct object_array *pending,
+static void get_tags_and_duplicates(struct rev_cmdline_info *info,
struct string_list *extra_refs)
{
struct tag *tag;
int i;
- for (i = 0; i < pending->nr; i++) {
- struct object_array_entry *e = pending->objects + i;
+ for (i = 0; i < info->nr; i++) {
+ struct rev_cmdline_entry *e = info->rev + i;
unsigned char sha1[20];
- struct commit *commit = commit;
+ struct commit *commit;
char *full_name;
+ if (e->flags & UNINTERESTING)
+ continue;
+
if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1)
continue;
@@ -523,10 +526,14 @@ static void get_tags_and_duplicates(struct object_array *pending,
typename(e->item->type));
continue;
}
- if (commit->util)
- /* more than one name for the same object */
+
+ /*
+ * This ref will not be updated through a commit, lets make
+ * sure it gets properly updated eventually.
+ */
+ if (commit->util || commit->object.flags & SHOWN)
string_list_append(extra_refs, full_name)->util = commit;
- else
+ if (!commit->util)
commit->util = full_name;
}
}
@@ -614,6 +621,10 @@ static void import_marks(char *input_file)
if (object->flags & SHOWN)
error("Object %s already has a mark", sha1_to_hex(sha1));
+ if (object->type != OBJ_COMMIT)
+ /* only commits */
+ continue;
+
mark_object(object, mark);
if (last_idnum < mark)
last_idnum = mark;
@@ -677,7 +688,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
if (import_filename && revs.prune_data.nr)
full_tree = 1;
- get_tags_and_duplicates(&revs.pending, &extra_refs);
+ get_tags_and_duplicates(&revs.cmdline, &extra_refs);
if (prepare_revision_walk(&revs))
die("revision walk setup failed");
diff --git a/builtin/log.c b/builtin/log.c
index e7b7db1cac..8f0b2e84fe 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -22,6 +22,7 @@
#include "branch.h"
#include "streaming.h"
#include "version.h"
+#include "mailmap.h"
/* Set a default date-time format for git log ("log.date" config variable) */
static const char *default_date_mode = NULL;
@@ -30,6 +31,7 @@ static int default_abbrev_commit;
static int default_show_root = 1;
static int decoration_style;
static int decoration_given;
+static int use_mailmap_config;
static const char *fmt_patch_subject_prefix = "PATCH";
static const char *fmt_pretty;
@@ -94,16 +96,18 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
struct rev_info *rev, struct setup_revision_opt *opt)
{
struct userformat_want w;
- int quiet = 0, source = 0;
+ int quiet = 0, source = 0, mailmap = 0;
const struct option builtin_log_options[] = {
OPT_BOOLEAN(0, "quiet", &quiet, N_("suppress diff output")),
OPT_BOOLEAN(0, "source", &source, N_("show source")),
+ OPT_BOOLEAN(0, "use-mailmap", &mailmap, N_("Use mail map file")),
{ OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
PARSE_OPT_OPTARG, decorate_callback},
OPT_END()
};
+ mailmap = use_mailmap_config;
argc = parse_options(argc, argv, prefix,
builtin_log_options, builtin_log_usage,
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
@@ -136,6 +140,11 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
if (source)
rev->show_source = 1;
+ if (mailmap) {
+ rev->mailmap = xcalloc(1, sizeof(struct string_list));
+ read_mailmap(rev->mailmap, NULL);
+ }
+
if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {
/*
* "log --pretty=raw" is special; ignore UI oriented
@@ -351,6 +360,11 @@ static int git_log_config(const char *var, const char *value, void *cb)
}
if (!prefixcmp(var, "color.decorate."))
return parse_decorate_color_config(var, 15, value);
+ if (!strcmp(var, "log.mailmap")) {
+ use_mailmap_config = git_config_bool(var, value);
+ return 0;
+ }
+
if (grep_config(var, value, cb) < 0)
return -1;
return git_diff_ui_config(var, value, cb);
@@ -678,7 +692,7 @@ static int reopen_stdout(struct commit *commit, const char *subject,
struct rev_info *rev, int quiet)
{
struct strbuf filename = STRBUF_INIT;
- int suffix_len = strlen(fmt_patch_suffix) + 1;
+ int suffix_len = strlen(rev->patch_suffix) + 1;
if (output_directory) {
strbuf_addstr(&filename, output_directory);
@@ -689,7 +703,12 @@ static int reopen_stdout(struct commit *commit, const char *subject,
strbuf_addch(&filename, '/');
}
- get_patch_filename(commit, subject, rev->nr, fmt_patch_suffix, &filename);
+ if (rev->numbered_files)
+ strbuf_addf(&filename, "%d", rev->nr);
+ else if (commit)
+ fmt_output_commit(&filename, commit, rev);
+ else
+ fmt_output_subject(&filename, subject, rev);
if (!quiet)
fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
@@ -773,7 +792,6 @@ static void add_branch_description(struct strbuf *buf, const char *branch_name)
}
static void make_cover_letter(struct rev_info *rev, int use_stdout,
- int numbered, int numbered_files,
struct commit *origin,
int nr, struct commit **list, struct commit *head,
const char *branch_name,
@@ -796,7 +814,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
committer = git_committer_info(0);
if (!use_stdout &&
- reopen_stdout(NULL, numbered_files ? NULL : "cover-letter", rev, quiet))
+ reopen_stdout(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
return;
log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
@@ -1016,8 +1034,9 @@ static char *find_branch_name(struct rev_info *rev)
{
int i, positive = -1;
unsigned char branch_sha1[20];
- struct strbuf buf = STRBUF_INIT;
- const char *branch;
+ const unsigned char *tip_sha1;
+ const char *ref;
+ char *full_ref, *branch = NULL;
for (i = 0; i < rev->cmdline.nr; i++) {
if (rev->cmdline.rev[i].flags & UNINTERESTING)
@@ -1027,18 +1046,27 @@ static char *find_branch_name(struct rev_info *rev)
else
return NULL;
}
- if (positive < 0)
+ if (0 <= positive) {
+ ref = rev->cmdline.rev[positive].name;
+ tip_sha1 = rev->cmdline.rev[positive].item->sha1;
+ } else if (!rev->cmdline.nr && rev->pending.nr == 1 &&
+ !strcmp(rev->pending.objects[0].name, "HEAD")) {
+ /*
+ * No actual ref from command line, but "HEAD" from
+ * rev->def was added in setup_revisions()
+ * e.g. format-patch --cover-letter -12
+ */
+ ref = "HEAD";
+ tip_sha1 = rev->pending.objects[0].item->sha1;
+ } else {
return NULL;
- strbuf_addf(&buf, "refs/heads/%s", rev->cmdline.rev[positive].name);
- branch = resolve_ref_unsafe(buf.buf, branch_sha1, 1, NULL);
- if (!branch ||
- prefixcmp(branch, "refs/heads/") ||
- hashcmp(rev->cmdline.rev[positive].item->sha1, branch_sha1))
- branch = NULL;
- strbuf_release(&buf);
- if (branch)
- return xstrdup(rev->cmdline.rev[positive].name);
- return NULL;
+ }
+ if (dwim_ref(ref, strlen(ref), branch_sha1, &full_ref) &&
+ !prefixcmp(full_ref, "refs/heads/") &&
+ !hashcmp(tip_sha1, branch_sha1))
+ branch = xstrdup(full_ref + strlen("refs/heads/"));
+ free(full_ref);
+ return branch;
}
int cmd_format_patch(int argc, const char **argv, const char *prefix)
@@ -1050,7 +1078,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
int nr = 0, total, i;
int use_stdout = 0;
int start_number = -1;
- int numbered_files = 0; /* _just_ numbers */
+ int just_numbers = 0;
int ignore_if_in_upstream = 0;
int cover_letter = 0;
int boundary_count = 0;
@@ -1062,6 +1090,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
struct strbuf buf = STRBUF_INIT;
int use_patch_format = 0;
int quiet = 0;
+ int reroll_count = -1;
char *branch_name = NULL;
const struct option builtin_format_patch_options[] = {
{ OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
@@ -1075,12 +1104,14 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
N_("print patches to standard out")),
OPT_BOOLEAN(0, "cover-letter", &cover_letter,
N_("generate a cover letter")),
- OPT_BOOLEAN(0, "numbered-files", &numbered_files,
+ OPT_BOOLEAN(0, "numbered-files", &just_numbers,
N_("use simple number sequence for output file names")),
OPT_STRING(0, "suffix", &fmt_patch_suffix, N_("sfx"),
N_("use <sfx> instead of '.patch'")),
OPT_INTEGER(0, "start-number", &start_number,
N_("start numbering patches at <n> instead of 1")),
+ OPT_INTEGER('v', "reroll-count", &reroll_count,
+ N_("mark the series as Nth re-roll")),
{ OPTION_CALLBACK, 0, "subject-prefix", &rev, N_("prefix"),
N_("Use [<prefix>] instead of [PATCH]"),
PARSE_OPT_NONEG, subject_prefix_callback },
@@ -1154,6 +1185,14 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
PARSE_OPT_KEEP_DASHDASH);
+ if (0 < reroll_count) {
+ struct strbuf sprefix = STRBUF_INIT;
+ strbuf_addf(&sprefix, "%s v%d",
+ rev.subject_prefix, reroll_count);
+ rev.reroll_count = reroll_count;
+ rev.subject_prefix = strbuf_detach(&sprefix, NULL);
+ }
+
if (do_signoff) {
const char *committer;
const char *endpos;
@@ -1344,12 +1383,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
const char *msgid = clean_message_id(in_reply_to);
string_list_append(rev.ref_message_ids, msgid);
}
- rev.numbered_files = numbered_files;
+ rev.numbered_files = just_numbers;
rev.patch_suffix = fmt_patch_suffix;
if (cover_letter) {
if (thread)
gen_message_id(&rev, "cover");
- make_cover_letter(&rev, use_stdout, numbered, numbered_files,
+ make_cover_letter(&rev, use_stdout,
origin, nr, list, head, branch_name, quiet);
total++;
start_number--;
@@ -1396,7 +1435,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
}
if (!use_stdout &&
- reopen_stdout(numbered_files ? NULL : commit, NULL, &rev, quiet))
+ reopen_stdout(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
die(_("Failed to create output files"));
shown = log_tree_commit(&rev, commit);
free(commit->buffer);
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index b5434af0c8..373c573449 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -203,7 +203,7 @@ static void show_ru_info(void)
static int ce_excluded(struct path_exclude_check *check, struct cache_entry *ce)
{
int dtype = ce_to_dtype(ce);
- return path_excluded(check, ce->name, ce_namelen(ce), &dtype);
+ return is_path_excluded(check, ce->name, ce_namelen(ce), &dtype);
}
static void show_files(struct dir_struct *dir)
@@ -337,7 +337,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
matchbuf[0] = prefix;
matchbuf[1] = NULL;
init_pathspec(&pathspec, matchbuf);
- pathspec.items[0].use_wildcard = 0;
+ pathspec.items[0].nowildcard_len = pathspec.items[0].len;
} else
init_pathspec(&pathspec, NULL);
if (read_tree(tree, 1, &pathspec))
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 235c17cc01..fb76e38d84 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -168,7 +168,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
init_pathspec(&pathspec, get_pathspec(prefix, argv + 1));
for (i = 0; i < pathspec.nr; i++)
- pathspec.items[i].use_wildcard = 0;
+ pathspec.items[i].nowildcard_len = pathspec.items[i].len;
pathspec.has_wildcard = 0;
tree = parse_tree_indirect(sha1);
if (!tree)
diff --git a/builtin/merge-index.c b/builtin/merge-index.c
index 2338832587..be5e514324 100644
--- a/builtin/merge-index.c
+++ b/builtin/merge-index.c
@@ -42,7 +42,7 @@ static int merge_entry(int pos, const char *path)
return found;
}
-static void merge_file(const char *path)
+static void merge_one_path(const char *path)
{
int pos = cache_name_pos(path, strlen(path));
@@ -102,7 +102,7 @@ int cmd_merge_index(int argc, const char **argv, const char *prefix)
}
die("git merge-index: unknown option %s", arg);
}
- merge_file(arg);
+ merge_one_path(arg);
}
if (err && !quiet)
die("merge program failed");
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 897a563bc6..e0d0b7d28b 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -3,17 +3,15 @@
#include "xdiff-interface.h"
#include "blob.h"
#include "exec_cmd.h"
-#include "merge-file.h"
+#include "merge-blobs.h"
static const char merge_tree_usage[] = "git merge-tree <base-tree> <branch1> <branch2>";
-static int resolve_directories = 1;
struct merge_list {
struct merge_list *next;
struct merge_list *link; /* other stages for this object */
- unsigned int stage : 2,
- flags : 30;
+ unsigned int stage : 2;
unsigned int mode;
const char *path;
struct blob *blob;
@@ -27,7 +25,7 @@ static void add_merge_entry(struct merge_list *entry)
merge_result_end = &entry->next;
}
-static void merge_trees(struct tree_desc t[3], const char *base);
+static void merge_trees_recursive(struct tree_desc t[3], const char *base, int df_conflict);
static const char *explanation(struct merge_list *entry)
{
@@ -76,7 +74,7 @@ static void *result(struct merge_list *entry, unsigned long *size)
their = NULL;
if (entry)
their = entry->blob;
- return merge_file(path, base, our, their, size);
+ return merge_blobs(path, base, our, their, size);
}
static void *origin(struct merge_list *entry, unsigned long *size)
@@ -174,17 +172,17 @@ static char *traverse_path(const struct traverse_info *info, const struct name_e
return make_traverse_path(path, info, n);
}
-static void resolve(const struct traverse_info *info, struct name_entry *branch1, struct name_entry *result)
+static void resolve(const struct traverse_info *info, struct name_entry *ours, struct name_entry *result)
{
struct merge_list *orig, *final;
const char *path;
- /* If it's already branch1, don't bother showing it */
- if (!branch1)
+ /* If it's already ours, don't bother showing it */
+ if (!ours)
return;
path = traverse_path(info, result);
- orig = create_entry(2, branch1->mode, branch1->sha1, path);
+ orig = create_entry(2, ours->mode, ours->sha1, path);
final = create_entry(0, result->mode, result->sha1, path);
final->link = orig;
@@ -192,34 +190,35 @@ static void resolve(const struct traverse_info *info, struct name_entry *branch1
add_merge_entry(final);
}
-static int unresolved_directory(const struct traverse_info *info, struct name_entry n[3])
+static void unresolved_directory(const struct traverse_info *info, struct name_entry n[3],
+ int df_conflict)
{
char *newbase;
struct name_entry *p;
struct tree_desc t[3];
void *buf0, *buf1, *buf2;
- if (!resolve_directories)
- return 0;
- p = n;
- if (!p->mode) {
- p++;
- if (!p->mode)
- p++;
+ for (p = n; p < n + 3; p++) {
+ if (p->mode && S_ISDIR(p->mode))
+ break;
}
- if (!S_ISDIR(p->mode))
- return 0;
+ if (n + 3 <= p)
+ return; /* there is no tree here */
+
newbase = traverse_path(info, p);
- buf0 = fill_tree_descriptor(t+0, n[0].sha1);
- buf1 = fill_tree_descriptor(t+1, n[1].sha1);
- buf2 = fill_tree_descriptor(t+2, n[2].sha1);
- merge_trees(t, newbase);
+
+#define ENTRY_SHA1(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->sha1 : NULL)
+ buf0 = fill_tree_descriptor(t+0, ENTRY_SHA1(n + 0));
+ buf1 = fill_tree_descriptor(t+1, ENTRY_SHA1(n + 1));
+ buf2 = fill_tree_descriptor(t+2, ENTRY_SHA1(n + 2));
+#undef ENTRY_SHA1
+
+ merge_trees_recursive(t, newbase, df_conflict);
free(buf0);
free(buf1);
free(buf2);
free(newbase);
- return 1;
}
@@ -242,18 +241,26 @@ static struct merge_list *link_entry(unsigned stage, const struct traverse_info
static void unresolved(const struct traverse_info *info, struct name_entry n[3])
{
struct merge_list *entry = NULL;
+ int i;
+ unsigned dirmask = 0, mask = 0;
+
+ for (i = 0; i < 3; i++) {
+ mask |= (1 << 1);
+ if (n[i].mode && S_ISDIR(n[i].mode))
+ dirmask |= (1 << i);
+ }
- if (unresolved_directory(info, n))
+ unresolved_directory(info, n, dirmask && (dirmask != mask));
+
+ if (dirmask == mask)
return;
- /*
- * Do them in reverse order so that the resulting link
- * list has the stages in order - link_entry adds new
- * links at the front.
- */
- entry = link_entry(3, info, n + 2, entry);
- entry = link_entry(2, info, n + 1, entry);
- entry = link_entry(1, info, n + 0, entry);
+ if (n[2].mode && !S_ISDIR(n[2].mode))
+ entry = link_entry(3, info, n + 2, entry);
+ if (n[1].mode && !S_ISDIR(n[1].mode))
+ entry = link_entry(2, info, n + 1, entry);
+ if (n[0].mode && !S_ISDIR(n[0].mode))
+ entry = link_entry(1, info, n + 0, entry);
add_merge_entry(entry);
}
@@ -292,20 +299,29 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s
/* Same in both? */
if (same_entry(entry+1, entry+2)) {
if (entry[0].sha1) {
+ /* Modified identically */
resolve(info, NULL, entry+1);
return mask;
}
+ /* "Both added the same" is left unresolved */
}
if (same_entry(entry+0, entry+1)) {
if (entry[2].sha1 && !S_ISDIR(entry[2].mode)) {
+ /* We did not touch, they modified -- take theirs */
resolve(info, entry+1, entry+2);
return mask;
}
+ /*
+ * If we did not touch a directory but they made it
+ * into a file, we fall through and unresolved()
+ * recurses down. Likewise for the opposite case.
+ */
}
if (same_entry(entry+0, entry+2)) {
if (entry[1].sha1 && !S_ISDIR(entry[1].mode)) {
+ /* We modified, they did not touch -- take ours */
resolve(info, NULL, entry+1);
return mask;
}
@@ -315,15 +331,21 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s
return mask;
}
-static void merge_trees(struct tree_desc t[3], const char *base)
+static void merge_trees_recursive(struct tree_desc t[3], const char *base, int df_conflict)
{
struct traverse_info info;
setup_traverse_info(&info, base);
+ info.data = &df_conflict;
info.fn = threeway_callback;
traverse_trees(3, t, &info);
}
+static void merge_trees(struct tree_desc t[3], const char *base)
+{
+ merge_trees_recursive(t, base, 0);
+}
+
static void *get_tree_descriptor(struct tree_desc *desc, const char *rev)
{
unsigned char sha1[20];
diff --git a/builtin/push.c b/builtin/push.c
index db9ba30b08..8491e431e4 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -220,31 +220,42 @@ static const char message_advice_checkout_pull_push[] =
"(e.g. 'git pull') before pushing again.\n"
"See the 'Note about fast-forwards' in 'git push --help' for details.");
+static const char message_advice_ref_already_exists[] =
+ N_("Updates were rejected because the destination reference already exists\n"
+ "in the remote.");
+
static void advise_pull_before_push(void)
{
- if (!advice_push_non_ff_current || !advice_push_nonfastforward)
+ if (!advice_push_non_ff_current || !advice_push_update_rejected)
return;
advise(_(message_advice_pull_before_push));
}
static void advise_use_upstream(void)
{
- if (!advice_push_non_ff_default || !advice_push_nonfastforward)
+ if (!advice_push_non_ff_default || !advice_push_update_rejected)
return;
advise(_(message_advice_use_upstream));
}
static void advise_checkout_pull_push(void)
{
- if (!advice_push_non_ff_matching || !advice_push_nonfastforward)
+ if (!advice_push_non_ff_matching || !advice_push_update_rejected)
return;
advise(_(message_advice_checkout_pull_push));
}
+static void advise_ref_already_exists(void)
+{
+ if (!advice_push_already_exists || !advice_push_update_rejected)
+ return;
+ advise(_(message_advice_ref_already_exists));
+}
+
static int push_with_options(struct transport *transport, int flags)
{
int err;
- int nonfastforward;
+ unsigned int reject_reasons;
transport_set_verbosity(transport, verbosity, progress);
@@ -257,7 +268,7 @@ static int push_with_options(struct transport *transport, int flags)
if (verbosity > 0)
fprintf(stderr, _("Pushing to %s\n"), transport->url);
err = transport_push(transport, refspec_nr, refspec, flags,
- &nonfastforward);
+ &reject_reasons);
if (err != 0)
error(_("failed to push some refs to '%s'"), transport->url);
@@ -265,18 +276,15 @@ static int push_with_options(struct transport *transport, int flags)
if (!err)
return 0;
- switch (nonfastforward) {
- default:
- break;
- case NON_FF_HEAD:
+ if (reject_reasons & REJECT_NON_FF_HEAD) {
advise_pull_before_push();
- break;
- case NON_FF_OTHER:
+ } else if (reject_reasons & REJECT_NON_FF_OTHER) {
if (default_matching_used)
advise_use_upstream();
else
advise_checkout_pull_push();
- break;
+ } else if (reject_reasons & REJECT_ALREADY_EXISTS) {
+ advise_ref_already_exists();
}
return 1;
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index d34201372d..f849e0a4a0 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -44,6 +44,11 @@ static void print_helper_status(struct ref *ref)
msg = "non-fast forward";
break;
+ case REF_STATUS_REJECT_ALREADY_EXISTS:
+ res = "error";
+ msg = "already exists";
+ break;
+
case REF_STATUS_REJECT_NODELETE:
case REF_STATUS_REMOTE_REJECT:
res = "error";
@@ -85,7 +90,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
int send_all = 0;
const char *receivepack = "git-receive-pack";
int flags;
- int nonfastforward = 0;
+ unsigned int reject_reasons;
int progress = -1;
argv++;
@@ -223,7 +228,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
ret |= finish_connect(conn);
if (!helper_status)
- transport_print_push_status(dest, remote_refs, args.verbose, 0, &nonfastforward);
+ transport_print_push_status(dest, remote_refs, args.verbose, 0, &reject_reasons);
if (!args.dry_run && remote) {
struct ref *ref;
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 83605143ac..240bff3efa 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -36,52 +36,28 @@ static void insert_one_record(struct shortlog *log,
const char *dot3 = log->common_repo_prefix;
char *buffer, *p;
struct string_list_item *item;
- char namebuf[1024];
- char emailbuf[1024];
- size_t len;
+ const char *mailbuf, *namebuf;
+ size_t namelen, maillen;
const char *eol;
- const char *boemail, *eoemail;
struct strbuf subject = STRBUF_INIT;
+ struct strbuf namemailbuf = STRBUF_INIT;
+ struct ident_split ident;
- boemail = strchr(author, '<');
- if (!boemail)
- return;
- eoemail = strchr(boemail, '>');
- if (!eoemail)
+ if (split_ident_line(&ident, author, strlen(author)))
return;
- /* copy author name to namebuf, to support matching on both name and email */
- memcpy(namebuf, author, boemail - author);
- len = boemail - author;
- while (len > 0 && isspace(namebuf[len-1]))
- len--;
- namebuf[len] = 0;
-
- /* copy email name to emailbuf, to allow email replacement as well */
- memcpy(emailbuf, boemail+1, eoemail - boemail);
- emailbuf[eoemail - boemail - 1] = 0;
-
- if (!map_user(&log->mailmap, emailbuf, sizeof(emailbuf), namebuf, sizeof(namebuf))) {
- while (author < boemail && isspace(*author))
- author++;
- for (len = 0;
- len < sizeof(namebuf) - 1 && author + len < boemail;
- len++)
- namebuf[len] = author[len];
- while (0 < len && isspace(namebuf[len-1]))
- len--;
- namebuf[len] = '\0';
- }
- else
- len = strlen(namebuf);
+ namebuf = ident.name_begin;
+ mailbuf = ident.mail_begin;
+ namelen = ident.name_end - ident.name_begin;
+ maillen = ident.mail_end - ident.mail_begin;
- if (log->email) {
- size_t room = sizeof(namebuf) - len - 1;
- int maillen = strlen(emailbuf);
- snprintf(namebuf + len, room, " <%.*s>", maillen, emailbuf);
- }
+ map_user(&log->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
+ strbuf_add(&namemailbuf, namebuf, namelen);
+
+ if (log->email)
+ strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf);
- item = string_list_insert(&log->list, namebuf);
+ item = string_list_insert(&log->list, namemailbuf.buf);
if (item->util == NULL)
item->util = xcalloc(1, sizeof(struct string_list));
diff --git a/cache.h b/cache.h
index 18fdd18f36..c257953fa7 100644
--- a/cache.h
+++ b/cache.h
@@ -362,6 +362,7 @@ static inline enum object_type object_type(unsigned int mode)
#define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
#define GIT_NOTES_REWRITE_REF_ENVIRONMENT "GIT_NOTES_REWRITE_REF"
#define GIT_NOTES_REWRITE_MODE_ENVIRONMENT "GIT_NOTES_REWRITE_MODE"
+#define GIT_LITERAL_PATHSPECS_ENVIRONMENT "GIT_LITERAL_PATHSPECS"
/*
* Repository-local GIT_* environment variables
@@ -473,6 +474,8 @@ extern int index_name_is_other(const struct index_state *, const char *, int);
extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
+#define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */
+
struct pathspec {
const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
int nr;
@@ -482,7 +485,8 @@ struct pathspec {
struct pathspec_item {
const char *match;
int len;
- unsigned int use_wildcard:1;
+ int nowildcard_len;
+ int flags;
} *items;
};
@@ -490,6 +494,8 @@ extern int init_pathspec(struct pathspec *, const char **);
extern void free_pathspec(struct pathspec *);
extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
+extern int limit_pathspec_to_literal(void);
+
#define HASH_WRITE_OBJECT 1
#define HASH_FORMAT_CHECK 2
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
@@ -714,10 +720,11 @@ static inline int is_absolute_path(const char *path)
}
int is_directory(const char *);
const char *real_path(const char *path);
+const char *real_path_if_valid(const char *path);
const char *absolute_path(const char *path);
const char *relative_path(const char *abs, const char *base);
int normalize_path_copy(char *dst, const char *src);
-int longest_ancestor_length(const char *path, const char *prefix_list);
+int longest_ancestor_length(const char *path, struct string_list *prefixes);
char *strip_path_suffix(const char *path, const char *suffix);
int daemon_avoid_alias(const char *path);
int offset_1st_component(const char *path);
@@ -999,14 +1006,19 @@ struct ref {
unsigned char old_sha1[20];
unsigned char new_sha1[20];
char *symref;
- unsigned int force:1,
+ unsigned int
+ force:1,
+ requires_force:1,
merge:1,
nonfastforward:1,
+ not_forwardable:1,
+ update:1,
deletion:1;
enum {
REF_STATUS_NONE = 0,
REF_STATUS_OK,
REF_STATUS_REJECT_NONFASTFORWARD,
+ REF_STATUS_REJECT_ALREADY_EXISTS,
REF_STATUS_REJECT_NODELETE,
REF_STATUS_UPTODATE,
REF_STATUS_REMOTE_REJECT,
@@ -1136,6 +1148,9 @@ extern int check_repository_format_version(const char *var, const char *value, v
extern int git_env_bool(const char *, int);
extern int git_config_system(void);
extern int config_error_nonbool(const char *);
+#ifdef __GNUC__
+#define config_error_nonbool(s) (config_error_nonbool(s), -1)
+#endif
extern const char *get_log_output_encoding(void);
extern const char *get_commit_output_encoding(void);
@@ -1155,6 +1170,7 @@ extern int author_ident_sufficiently_given(void);
extern const char *git_commit_encoding;
extern const char *git_log_output_encoding;
extern const char *git_mailmap_file;
+extern const char *git_mailmap_blob;
/* IO helper functions */
extern void maybe_flush_or_die(FILE *, const char *);
diff --git a/commit.h b/commit.h
index b6ad8f3f30..c16c8a7534 100644
--- a/commit.h
+++ b/commit.h
@@ -89,6 +89,8 @@ struct pretty_print_context {
char *notes_message;
struct reflog_walk_info *reflog_info;
const char *output_encoding;
+ struct string_list *mailmap;
+ int color;
};
struct userformat_want {
diff --git a/compat/fnmatch/fnmatch.c b/compat/fnmatch/fnmatch.c
index b8b7dc2543..5ef0685135 100644
--- a/compat/fnmatch/fnmatch.c
+++ b/compat/fnmatch/fnmatch.c
@@ -55,7 +55,8 @@
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
-#if defined _LIBC || !defined __GNU_LIBRARY__
+#if defined NO_FNMATCH || defined NO_FNMATCH_CASEFOLD || \
+ defined _LIBC || !defined __GNU_LIBRARY__
# if defined STDC_HEADERS || !defined isascii
diff --git a/config.c b/config.c
index b5696354fa..7b444b68ab 100644
--- a/config.c
+++ b/config.c
@@ -839,6 +839,8 @@ static int git_default_mailmap_config(const char *var, const char *value)
{
if (!strcmp(var, "mailmap.file"))
return git_config_string(&git_mailmap_file, var, value);
+ if (!strcmp(var, "mailmap.blob"))
+ return git_config_string(&git_mailmap_blob, var, value);
/* Add other config variables here and to Documentation/config.txt. */
return 0;
@@ -1660,6 +1662,7 @@ int git_config_rename_section(const char *old_name, const char *new_name)
* Call this to report error for your variable that should not
* get a boolean value (i.e. "[my] var" means "true").
*/
+#undef config_error_nonbool
int config_error_nonbool(const char *var)
{
return error("Missing value for '%s'", var);
diff --git a/config.mak.uname b/config.mak.uname
new file mode 100644
index 0000000000..bea34f0511
--- /dev/null
+++ b/config.mak.uname
@@ -0,0 +1,539 @@
+# Platform specific Makefile tweaks based on uname detection
+
+uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
+uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
+uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
+uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
+uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
+uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
+
+ifdef MSVC
+ # avoid the MingW and Cygwin configuration sections
+ uname_S := Windows
+ uname_O := Windows
+endif
+
+# We choose to avoid "if .. else if .. else .. endif endif"
+# because maintaining the nesting to match is a pain. If
+# we had "elif" things would have been much nicer...
+
+ifeq ($(uname_M),x86_64)
+ XDL_FAST_HASH = YesPlease
+endif
+ifeq ($(uname_S),OSF1)
+ # Need this for u_short definitions et al
+ BASIC_CFLAGS += -D_OSF_SOURCE
+ SOCKLEN_T = int
+ NO_STRTOULL = YesPlease
+ NO_NSEC = YesPlease
+endif
+ifeq ($(uname_S),Linux)
+ NO_STRLCPY = YesPlease
+ NO_MKSTEMPS = YesPlease
+ HAVE_PATHS_H = YesPlease
+ LIBC_CONTAINS_LIBINTL = YesPlease
+ HAVE_DEV_TTY = YesPlease
+endif
+ifeq ($(uname_S),GNU/kFreeBSD)
+ NO_STRLCPY = YesPlease
+ NO_MKSTEMPS = YesPlease
+ HAVE_PATHS_H = YesPlease
+ DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
+ LIBC_CONTAINS_LIBINTL = YesPlease
+endif
+ifeq ($(uname_S),UnixWare)
+ CC = cc
+ NEEDS_SOCKET = YesPlease
+ NEEDS_NSL = YesPlease
+ NEEDS_SSL_WITH_CRYPTO = YesPlease
+ NEEDS_LIBICONV = YesPlease
+ SHELL_PATH = /usr/local/bin/bash
+ NO_IPV6 = YesPlease
+ NO_HSTRERROR = YesPlease
+ NO_MKSTEMPS = YesPlease
+ BASIC_CFLAGS += -Kthread
+ BASIC_CFLAGS += -I/usr/local/include
+ BASIC_LDFLAGS += -L/usr/local/lib
+ INSTALL = ginstall
+ TAR = gtar
+ NO_STRCASESTR = YesPlease
+ NO_MEMMEM = YesPlease
+endif
+ifeq ($(uname_S),SCO_SV)
+ ifeq ($(uname_R),3.2)
+ CFLAGS = -O2
+ endif
+ ifeq ($(uname_R),5)
+ CC = cc
+ BASIC_CFLAGS += -Kthread
+ endif
+ NEEDS_SOCKET = YesPlease
+ NEEDS_NSL = YesPlease
+ NEEDS_SSL_WITH_CRYPTO = YesPlease
+ NEEDS_LIBICONV = YesPlease
+ SHELL_PATH = /usr/bin/bash
+ NO_IPV6 = YesPlease
+ NO_HSTRERROR = YesPlease
+ NO_MKSTEMPS = YesPlease
+ BASIC_CFLAGS += -I/usr/local/include
+ BASIC_LDFLAGS += -L/usr/local/lib
+ NO_STRCASESTR = YesPlease
+ NO_MEMMEM = YesPlease
+ INSTALL = ginstall
+ TAR = gtar
+endif
+ifeq ($(uname_S),Darwin)
+ NEEDS_CRYPTO_WITH_SSL = YesPlease
+ NEEDS_SSL_WITH_CRYPTO = YesPlease
+ NEEDS_LIBICONV = YesPlease
+ ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2)
+ OLD_ICONV = UnfortunatelyYes
+ endif
+ ifeq ($(shell expr "$(uname_R)" : '[15]\.'),2)
+ NO_STRLCPY = YesPlease
+ endif
+ NO_MEMMEM = YesPlease
+ USE_ST_TIMESPEC = YesPlease
+ HAVE_DEV_TTY = YesPlease
+ COMPAT_OBJS += compat/precompose_utf8.o
+ BASIC_CFLAGS += -DPRECOMPOSE_UNICODE
+endif
+ifeq ($(uname_S),SunOS)
+ NEEDS_SOCKET = YesPlease
+ NEEDS_NSL = YesPlease
+ SHELL_PATH = /bin/bash
+ SANE_TOOL_PATH = /usr/xpg6/bin:/usr/xpg4/bin
+ NO_STRCASESTR = YesPlease
+ NO_MEMMEM = YesPlease
+ NO_MKDTEMP = YesPlease
+ NO_MKSTEMPS = YesPlease
+ NO_REGEX = YesPlease
+ NO_FNMATCH_CASEFOLD = YesPlease
+ NO_MSGFMT_EXTENDED_OPTIONS = YesPlease
+ HAVE_DEV_TTY = YesPlease
+ ifeq ($(uname_R),5.6)
+ SOCKLEN_T = int
+ NO_HSTRERROR = YesPlease
+ NO_IPV6 = YesPlease
+ NO_SOCKADDR_STORAGE = YesPlease
+ NO_UNSETENV = YesPlease
+ NO_SETENV = YesPlease
+ NO_STRLCPY = YesPlease
+ NO_STRTOUMAX = YesPlease
+ GIT_TEST_CMP = cmp
+ endif
+ ifeq ($(uname_R),5.7)
+ NEEDS_RESOLV = YesPlease
+ NO_IPV6 = YesPlease
+ NO_SOCKADDR_STORAGE = YesPlease
+ NO_UNSETENV = YesPlease
+ NO_SETENV = YesPlease
+ NO_STRLCPY = YesPlease
+ NO_STRTOUMAX = YesPlease
+ GIT_TEST_CMP = cmp
+ endif
+ ifeq ($(uname_R),5.8)
+ NO_UNSETENV = YesPlease
+ NO_SETENV = YesPlease
+ NO_STRTOUMAX = YesPlease
+ GIT_TEST_CMP = cmp
+ endif
+ ifeq ($(uname_R),5.9)
+ NO_UNSETENV = YesPlease
+ NO_SETENV = YesPlease
+ NO_STRTOUMAX = YesPlease
+ GIT_TEST_CMP = cmp
+ endif
+ INSTALL = /usr/ucb/install
+ TAR = gtar
+ BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H
+endif
+ifeq ($(uname_O),Cygwin)
+ ifeq ($(shell expr "$(uname_R)" : '1\.[1-6]\.'),4)
+ NO_D_TYPE_IN_DIRENT = YesPlease
+ NO_D_INO_IN_DIRENT = YesPlease
+ NO_STRCASESTR = YesPlease
+ NO_MEMMEM = YesPlease
+ NO_MKSTEMPS = YesPlease
+ NO_SYMLINK_HEAD = YesPlease
+ NO_IPV6 = YesPlease
+ OLD_ICONV = UnfortunatelyYes
+ CYGWIN_V15_WIN32API = YesPlease
+ endif
+ NO_THREAD_SAFE_PREAD = YesPlease
+ NEEDS_LIBICONV = YesPlease
+ NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
+ NO_TRUSTABLE_FILEMODE = UnfortunatelyYes
+ NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
+ # There are conflicting reports about this.
+ # On some boxes NO_MMAP is needed, and not so elsewhere.
+ # Try commenting this out if you suspect MMAP is more efficient
+ NO_MMAP = YesPlease
+ X = .exe
+ COMPAT_OBJS += compat/cygwin.o
+ UNRELIABLE_FSTAT = UnfortunatelyYes
+ SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield
+endif
+ifeq ($(uname_S),FreeBSD)
+ NEEDS_LIBICONV = YesPlease
+ OLD_ICONV = YesPlease
+ NO_MEMMEM = YesPlease
+ BASIC_CFLAGS += -I/usr/local/include
+ BASIC_LDFLAGS += -L/usr/local/lib
+ DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
+ USE_ST_TIMESPEC = YesPlease
+ ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
+ PTHREAD_LIBS = -pthread
+ NO_UINTMAX_T = YesPlease
+ NO_STRTOUMAX = YesPlease
+ endif
+ PYTHON_PATH = /usr/local/bin/python
+ HAVE_PATHS_H = YesPlease
+endif
+ifeq ($(uname_S),OpenBSD)
+ NO_STRCASESTR = YesPlease
+ NO_MEMMEM = YesPlease
+ USE_ST_TIMESPEC = YesPlease
+ NEEDS_LIBICONV = YesPlease
+ BASIC_CFLAGS += -I/usr/local/include
+ BASIC_LDFLAGS += -L/usr/local/lib
+ HAVE_PATHS_H = YesPlease
+endif
+ifeq ($(uname_S),NetBSD)
+ ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2)
+ NEEDS_LIBICONV = YesPlease
+ endif
+ BASIC_CFLAGS += -I/usr/pkg/include
+ BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
+ USE_ST_TIMESPEC = YesPlease
+ NO_MKSTEMPS = YesPlease
+ HAVE_PATHS_H = YesPlease
+endif
+ifeq ($(uname_S),AIX)
+ DEFAULT_PAGER = more
+ NO_STRCASESTR = YesPlease
+ NO_MEMMEM = YesPlease
+ NO_MKDTEMP = YesPlease
+ NO_MKSTEMPS = YesPlease
+ NO_STRLCPY = YesPlease
+ NO_NSEC = YesPlease
+ FREAD_READS_DIRECTORIES = UnfortunatelyYes
+ INTERNAL_QSORT = UnfortunatelyYes
+ NEEDS_LIBICONV = YesPlease
+ BASIC_CFLAGS += -D_LARGE_FILES
+ ifeq ($(shell expr "$(uname_V)" : '[1234]'),1)
+ NO_PTHREADS = YesPlease
+ else
+ PTHREAD_LIBS = -lpthread
+ endif
+ ifeq ($(shell expr "$(uname_V).$(uname_R)" : '5\.1'),3)
+ INLINE = ''
+ endif
+ GIT_TEST_CMP = cmp
+endif
+ifeq ($(uname_S),GNU)
+ # GNU/Hurd
+ NO_STRLCPY = YesPlease
+ NO_MKSTEMPS = YesPlease
+ HAVE_PATHS_H = YesPlease
+ LIBC_CONTAINS_LIBINTL = YesPlease
+endif
+ifeq ($(uname_S),IRIX)
+ NO_SETENV = YesPlease
+ NO_UNSETENV = YesPlease
+ NO_STRCASESTR = YesPlease
+ 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_REGEX = YesPlease
+ NO_FNMATCH_CASEFOLD = YesPlease
+ SNPRINTF_RETURNS_BOGUS = YesPlease
+ SHELL_PATH = /usr/gnu/bin/bash
+ NEEDS_LIBGEN = YesPlease
+endif
+ifeq ($(uname_S),IRIX64)
+ NO_SETENV = YesPlease
+ NO_UNSETENV = YesPlease
+ NO_STRCASESTR = YesPlease
+ 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_REGEX = YesPlease
+ NO_FNMATCH_CASEFOLD = YesPlease
+ SNPRINTF_RETURNS_BOGUS = YesPlease
+ SHELL_PATH = /usr/gnu/bin/bash
+ NEEDS_LIBGEN = YesPlease
+endif
+ifeq ($(uname_S),HP-UX)
+ INLINE = __inline
+ NO_IPV6 = YesPlease
+ NO_SETENV = YesPlease
+ NO_STRCASESTR = YesPlease
+ NO_MEMMEM = YesPlease
+ NO_MKSTEMPS = YesPlease
+ NO_STRLCPY = YesPlease
+ NO_MKDTEMP = YesPlease
+ NO_UNSETENV = YesPlease
+ NO_HSTRERROR = YesPlease
+ NO_SYS_SELECT_H = YesPlease
+ NO_FNMATCH_CASEFOLD = YesPlease
+ SNPRINTF_RETURNS_BOGUS = YesPlease
+ NO_NSEC = YesPlease
+ ifeq ($(uname_R),B.11.00)
+ NO_INET_NTOP = YesPlease
+ NO_INET_PTON = YesPlease
+ endif
+ ifeq ($(uname_R),B.10.20)
+ # Override HP-UX 11.x setting:
+ INLINE =
+ SOCKLEN_T = size_t
+ NO_PREAD = YesPlease
+ NO_INET_NTOP = YesPlease
+ NO_INET_PTON = YesPlease
+ endif
+ GIT_TEST_CMP = cmp
+endif
+ifeq ($(uname_S),Windows)
+ GIT_VERSION := $(GIT_VERSION).MSVC
+ pathsep = ;
+ NO_PREAD = YesPlease
+ NEEDS_CRYPTO_WITH_SSL = YesPlease
+ NO_LIBGEN_H = YesPlease
+ NO_POLL = YesPlease
+ NO_SYMLINK_HEAD = YesPlease
+ NO_IPV6 = YesPlease
+ NO_UNIX_SOCKETS = YesPlease
+ NO_SETENV = YesPlease
+ NO_UNSETENV = YesPlease
+ NO_STRCASESTR = YesPlease
+ NO_STRLCPY = YesPlease
+ NO_STRTOK_R = YesPlease
+ NO_FNMATCH = YesPlease
+ NO_MEMMEM = YesPlease
+ # NEEDS_LIBICONV = YesPlease
+ NO_ICONV = YesPlease
+ NO_STRTOUMAX = YesPlease
+ NO_STRTOULL = YesPlease
+ NO_MKDTEMP = YesPlease
+ NO_MKSTEMPS = YesPlease
+ SNPRINTF_RETURNS_BOGUS = YesPlease
+ NO_SVN_TESTS = YesPlease
+ NO_PERL_MAKEMAKER = YesPlease
+ RUNTIME_PREFIX = YesPlease
+ NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
+ NO_NSEC = YesPlease
+ USE_WIN32_MMAP = YesPlease
+ # USE_NED_ALLOCATOR = YesPlease
+ UNRELIABLE_FSTAT = UnfortunatelyYes
+ OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
+ NO_REGEX = YesPlease
+ NO_CURL = YesPlease
+ NO_PYTHON = YesPlease
+ BLK_SHA1 = YesPlease
+ NO_POSIX_GOODIES = UnfortunatelyYes
+ NATIVE_CRLF = YesPlease
+ DEFAULT_HELP_FORMAT = html
+
+ 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
+ COMPAT_OBJS = compat/msvc.o compat/winansi.o \
+ compat/win32/pthread.o compat/win32/syslog.o \
+ compat/win32/dirent.o
+ COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
+ BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
+ EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib
+ PTHREAD_LIBS =
+ lib =
+ifndef DEBUG
+ BASIC_CFLAGS += -GL -Os -MT
+ BASIC_LDFLAGS += -LTCG
+ AR += -LTCG
+else
+ BASIC_CFLAGS += -Zi -MTd
+endif
+ X = .exe
+endif
+ifeq ($(uname_S),Interix)
+ NO_INITGROUPS = YesPlease
+ NO_IPV6 = YesPlease
+ NO_MEMMEM = YesPlease
+ NO_MKDTEMP = YesPlease
+ NO_STRTOUMAX = YesPlease
+ NO_NSEC = YesPlease
+ NO_MKSTEMPS = YesPlease
+ ifeq ($(uname_R),3.5)
+ NO_INET_NTOP = YesPlease
+ NO_INET_PTON = YesPlease
+ NO_SOCKADDR_STORAGE = YesPlease
+ NO_FNMATCH_CASEFOLD = YesPlease
+ endif
+ ifeq ($(uname_R),5.2)
+ NO_INET_NTOP = YesPlease
+ NO_INET_PTON = YesPlease
+ NO_SOCKADDR_STORAGE = YesPlease
+ NO_FNMATCH_CASEFOLD = YesPlease
+ endif
+endif
+ifeq ($(uname_S),Minix)
+ NO_IPV6 = YesPlease
+ NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
+ NO_NSEC = YesPlease
+ NEEDS_LIBGEN =
+ NEEDS_CRYPTO_WITH_SSL = YesPlease
+ NEEDS_IDN_WITH_CURL = YesPlease
+ NEEDS_SSL_WITH_CURL = YesPlease
+ NEEDS_RESOLV =
+ NO_HSTRERROR = YesPlease
+ NO_MMAP = YesPlease
+ NO_CURL =
+ NO_EXPAT =
+endif
+ifeq ($(uname_S),NONSTOP_KERNEL)
+ # Needs some C99 features, "inline" is just one of them.
+ # INLINE='' would just replace one set of warnings with another and
+ # still not compile in c89 mode, due to non-const array initializations.
+ CC = cc -c99
+ # Disable all optimization, seems to result in bad code, with -O or -O2
+ # or even -O1 (default), /usr/local/libexec/git-core/git-pack-objects
+ # abends on "git push". Needs more investigation.
+ CFLAGS = -g -O0
+ # We'd want it to be here.
+ prefix = /usr/local
+ # Our's are in ${prefix}/bin (perl might also be in /usr/bin/perl).
+ PERL_PATH = ${prefix}/bin/perl
+ PYTHON_PATH = ${prefix}/bin/python
+
+ # As detected by './configure'.
+ # Missdetected, hence commented out, see below.
+ #NO_CURL = YesPlease
+ # Added manually, see above.
+ NEEDS_SSL_WITH_CURL = YesPlease
+ HAVE_LIBCHARSET_H = YesPlease
+ HAVE_STRINGS_H = YesPlease
+ NEEDS_LIBICONV = YesPlease
+ NEEDS_LIBINTL_BEFORE_LIBICONV = YesPlease
+ NO_SYS_SELECT_H = UnfortunatelyYes
+ NO_D_TYPE_IN_DIRENT = YesPlease
+ NO_HSTRERROR = YesPlease
+ NO_STRCASESTR = YesPlease
+ NO_FNMATCH_CASEFOLD = YesPlease
+ NO_MEMMEM = YesPlease
+ NO_STRLCPY = YesPlease
+ NO_SETENV = YesPlease
+ NO_UNSETENV = YesPlease
+ NO_MKDTEMP = YesPlease
+ NO_MKSTEMPS = YesPlease
+ # Currently libiconv-1.9.1.
+ OLD_ICONV = UnfortunatelyYes
+ NO_REGEX = YesPlease
+ NO_PTHREADS = UnfortunatelyYes
+
+ # Not detected (nor checked for) by './configure'.
+ # We don't have SA_RESTART on NonStop, unfortunalety.
+ COMPAT_CFLAGS += -DSA_RESTART=0
+ # Apparently needed in compat/fnmatch/fnmatch.c.
+ COMPAT_CFLAGS += -DHAVE_STRING_H=1
+ NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
+ NO_NSEC = YesPlease
+ NO_PREAD = YesPlease
+ NO_MMAP = YesPlease
+ NO_POLL = YesPlease
+ NO_INTPTR_T = UnfortunatelyYes
+ # Bug report 10-120822-4477 submitted to HP NonStop development.
+ MKDIR_WO_TRAILING_SLASH = YesPlease
+ # RFE 10-120912-4693 submitted to HP NonStop development.
+ NO_SETITIMER = UnfortunatelyYes
+ SANE_TOOL_PATH = /usr/coreutils/bin:/usr/local/bin
+ SHELL_PATH = /usr/local/bin/bash
+ # as of H06.25/J06.14, we might better use this
+ #SHELL_PATH = /usr/coreutils/bin/bash
+endif
+ifneq (,$(findstring MINGW,$(uname_S)))
+ pathsep = ;
+ NO_PREAD = YesPlease
+ NEEDS_CRYPTO_WITH_SSL = YesPlease
+ NO_LIBGEN_H = YesPlease
+ NO_POLL = YesPlease
+ NO_SYMLINK_HEAD = YesPlease
+ NO_UNIX_SOCKETS = YesPlease
+ NO_SETENV = YesPlease
+ NO_UNSETENV = YesPlease
+ NO_STRCASESTR = YesPlease
+ NO_STRLCPY = YesPlease
+ NO_STRTOK_R = YesPlease
+ NO_FNMATCH = YesPlease
+ NO_MEMMEM = YesPlease
+ NEEDS_LIBICONV = YesPlease
+ OLD_ICONV = YesPlease
+ NO_STRTOUMAX = YesPlease
+ NO_MKDTEMP = YesPlease
+ NO_MKSTEMPS = YesPlease
+ NO_SVN_TESTS = YesPlease
+ NO_PERL_MAKEMAKER = YesPlease
+ RUNTIME_PREFIX = YesPlease
+ NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
+ NO_NSEC = YesPlease
+ USE_WIN32_MMAP = YesPlease
+ USE_NED_ALLOCATOR = YesPlease
+ UNRELIABLE_FSTAT = UnfortunatelyYes
+ OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
+ NO_REGEX = YesPlease
+ NO_PYTHON = YesPlease
+ BLK_SHA1 = YesPlease
+ ETAGS_TARGET = ETAGS
+ NO_INET_PTON = YesPlease
+ NO_INET_NTOP = YesPlease
+ NO_POSIX_GOODIES = UnfortunatelyYes
+ COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/win32
+ COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
+ COMPAT_OBJS += compat/mingw.o compat/winansi.o \
+ compat/win32/pthread.o compat/win32/syslog.o \
+ compat/win32/dirent.o
+ EXTLIBS += -lws2_32
+ PTHREAD_LIBS =
+ X = .exe
+ SPARSE_FLAGS = -Wno-one-bit-signed-bitfield
+ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
+ htmldir = doc/git/html/
+ prefix =
+ INSTALL = /bin/install
+ EXTLIBS += /mingw/lib/libz.a
+ NO_R_TO_GCC_LINKER = YesPlease
+ INTERNAL_QSORT = YesPlease
+ HAVE_LIBCHARSET_H = YesPlease
+else
+ NO_CURL = YesPlease
+endif
+endif
+ifeq ($(uname_S),QNX)
+ COMPAT_CFLAGS += -DSA_RESTART=0
+ HAVE_STRINGS_H = YesPlease
+ NEEDS_SOCKET = YesPlease
+ NO_FNMATCH_CASEFOLD = YesPlease
+ NO_GETPAGESIZE = YesPlease
+ NO_ICONV = YesPlease
+ NO_MEMMEM = YesPlease
+ NO_MKDTEMP = YesPlease
+ NO_MKSTEMPS = YesPlease
+ NO_NSEC = YesPlease
+ NO_PTHREADS = YesPlease
+ NO_R_TO_GCC_LINKER = YesPlease
+ NO_STRCASESTR = YesPlease
+ NO_STRLCPY = YesPlease
+endif
diff --git a/configure.ac b/configure.ac
index 41ac9a5e2d..1991258ae0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -753,6 +753,14 @@ AC_CHECK_MEMBER(struct dirent.d_type,
[#include <dirent.h>])
GIT_CONF_SUBST([NO_D_TYPE_IN_DIRENT])
#
+# Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd
+# in the C library.
+AC_CHECK_MEMBER(struct passwd.pw_gecos,
+[NO_GECOS_IN_PWENT=],
+[NO_GECOS_IN_PWENT=YesPlease],
+[#include <pwd.h>])
+GIT_CONF_SUBST([NO_GECOS_IN_PWENT])
+#
# Define NO_SOCKADDR_STORAGE if your platform does not have struct
# sockaddr_storage.
AC_CHECK_TYPE(struct sockaddr_storage,
@@ -872,6 +880,12 @@ AC_CHECK_HEADER([libcharset.h],
[HAVE_LIBCHARSET_H=YesPlease],
[HAVE_LIBCHARSET_H=])
GIT_CONF_SUBST([HAVE_LIBCHARSET_H])
+#
+# Define HAVE_STRINGS_H if you have strings.h
+AC_CHECK_HEADER([strings.h],
+[HAVE_STRINGS_H=YesPlease],
+[HAVE_STRINGS_H=])
+GIT_CONF_SUBST([HAVE_STRINGS_H])
# Define CHARSET_LIB if libiconv does not export the locale_charset symbol
# and libcharset does
CHARSET_LIB=
diff --git a/contrib/ciabot/ciabot.py b/contrib/ciabot/ciabot.py
index bd24395d4c..36b5665ff8 100755
--- a/contrib/ciabot/ciabot.py
+++ b/contrib/ciabot/ciabot.py
@@ -47,7 +47,13 @@
# we default to that.
#
-import os, sys, commands, socket, urllib
+import sys
+if sys.hexversion < 0x02000000:
+ # The limiter is the xml.sax module
+ sys.stderr.write("ciabot.py: requires Python 2.0.0 or later.\n")
+ sys.exit(1)
+
+import os, commands, socket, urllib
from xml.sax.saxutils import escape
# Changeset URL prefix for your repo: when the commit ID is appended
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index a4c48e179e..14dd5e7ca2 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -397,7 +397,7 @@ __git_complete_revlist_file ()
*) pfx="$ref:$pfx" ;;
esac
- __gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" \
+ __gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" 2>/dev/null \
| sed '/^100... blob /{
s,^.* ,,
s,$, ,
diff --git a/contrib/completion/git-completion.tcsh b/contrib/completion/git-completion.tcsh
index 8aafb63315..3e3889f2b4 100644
--- a/contrib/completion/git-completion.tcsh
+++ b/contrib/completion/git-completion.tcsh
@@ -13,6 +13,7 @@
#
# To use this completion script:
#
+# 0) You need tcsh 6.16.00 or newer.
# 1) Copy both this file and the bash completion script to ${HOME}.
# You _must_ use the name ${HOME}/.git-completion.bash for the
# bash script.
@@ -24,6 +25,15 @@
# set autolist=ambiguous
# It will tell tcsh to list the possible completion choices.
+set __git_tcsh_completion_version = `\echo ${tcsh} | \sed 's/\./ /g'`
+if ( ${__git_tcsh_completion_version[1]} < 6 || \
+ ( ${__git_tcsh_completion_version[1]} == 6 && \
+ ${__git_tcsh_completion_version[2]} < 16 ) ) then
+ echo "git-completion.tcsh: Your version of tcsh is too old, you need version 6.16.00 or newer. Git completion will not work."
+ exit
+endif
+unset __git_tcsh_completion_version
+
set __git_tcsh_completion_original_script = ${HOME}/.git-completion.bash
set __git_tcsh_completion_script = ${HOME}/.git-completion.tcsh.bash
@@ -64,9 +74,7 @@ fi
_\${1}
IFS=\$'\n'
-if [ \${#COMPREPLY[*]} -gt 0 ]; then
- echo "\${COMPREPLY[*]}" | sort | uniq
-else
+if [ \${#COMPREPLY[*]} -eq 0 ]; then
# No completions suggested. In this case, we want tcsh to perform
# standard file completion. However, there does not seem to be way
# to tell tcsh to do that. To help the user, we try to simulate
@@ -85,19 +93,20 @@ else
# We don't support ~ expansion: too tricky.
if [ "\${TO_COMPLETE:0:1}" != "~" ]; then
# Use ls so as to add the '/' at the end of directories.
- RESULT=(\`ls -dp \${TO_COMPLETE}* 2> /dev/null\`)
- echo \${RESULT[*]}
-
- # If there is a single completion and it is a directory,
- # we output it a second time to trick tcsh into not adding a space
- # after it.
- if [ \${#RESULT[*]} -eq 1 ] && [ "\${RESULT[0]: -1}" == "/" ]; then
- echo \${RESULT[*]}
- fi
+ COMPREPLY=(\`ls -dp \${TO_COMPLETE}* 2> /dev/null\`)
fi
fi
fi
+# tcsh does not automatically remove duplicates, so we do it ourselves
+echo "\${COMPREPLY[*]}" | sort | uniq
+
+# If there is a single completion and it is a directory, we output it
+# a second time to trick tcsh into not adding a space after it.
+if [ \${#COMPREPLY[*]} -eq 1 ] && [ "\${COMPREPLY[0]: -1}" == "/" ]; then
+ echo "\${COMPREPLY[*]}"
+fi
+
EOF
# Don't need this variable anymore, so don't pollute the users environment
diff --git a/contrib/fast-import/import-zips.py b/contrib/fast-import/import-zips.py
index 82f5ed3ddc..5cec9b0129 100755
--- a/contrib/fast-import/import-zips.py
+++ b/contrib/fast-import/import-zips.py
@@ -9,10 +9,15 @@
## git log --stat import-zips
from os import popen, path
-from sys import argv, exit
+from sys import argv, exit, hexversion, stderr
from time import mktime
from zipfile import ZipFile
+if hexversion < 0x01060000:
+ # The limiter is the zipfile module
+ sys.stderr.write("import-zips.py: requires Python 1.6.0 or later.\n")
+ sys.exit(1)
+
if len(argv) < 2:
print 'Usage:', argv[0], '<zipfile>...'
exit(1)
diff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py
index 046cb2b268..232625a7b7 100755
--- a/contrib/hg-to-git/hg-to-git.py
+++ b/contrib/hg-to-git/hg-to-git.py
@@ -23,6 +23,11 @@ import os, os.path, sys
import tempfile, pickle, getopt
import re
+if sys.hexversion < 0x02030000:
+ # The behavior of the pickle module changed significantly in 2.3
+ sys.stderr.write("hg-to-git.py: requires Python 2.3 or later.\n")
+ sys.exit(1)
+
# Maps hg version -> git version
hgvers = {}
# List of children for each hg revision
diff --git a/contrib/p4import/git-p4import.py b/contrib/p4import/git-p4import.py
index b6e534b65b..593d6a0682 100644
--- a/contrib/p4import/git-p4import.py
+++ b/contrib/p4import/git-p4import.py
@@ -14,6 +14,11 @@ import sys
import time
import getopt
+if sys.hexversion < 0x02020000:
+ # The behavior of the marshal module changed significantly in 2.2
+ sys.stderr.write("git-p4import.py: requires Python 2.2 or later.\n")
+ sys.exit(1)
+
from signal import signal, \
SIGPIPE, SIGINT, SIG_DFL, \
default_int_handler
diff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr
new file mode 100755
index 0000000000..c5822e4ac9
--- /dev/null
+++ b/contrib/remote-helpers/git-remote-bzr
@@ -0,0 +1,725 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+
+#
+# Just copy to your ~/bin, or anywhere in your $PATH.
+# Then you can clone with:
+# % git clone bzr::/path/to/bzr/repo/or/url
+#
+# For example:
+# % git clone bzr::$HOME/myrepo
+# or
+# % git clone bzr::lp:myrepo
+#
+
+import sys
+
+import bzrlib
+if hasattr(bzrlib, "initialize"):
+ bzrlib.initialize()
+
+import bzrlib.plugin
+bzrlib.plugin.load_plugins()
+
+import bzrlib.generate_ids
+import bzrlib.transport
+
+import sys
+import os
+import json
+import re
+import StringIO
+
+NAME_RE = re.compile('^([^<>]+)')
+AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]*)>$')
+RAW_AUTHOR_RE = re.compile('^(\w+) (.+)? <(.*)> (\d+) ([+-]\d+)')
+
+def die(msg, *args):
+ sys.stderr.write('ERROR: %s\n' % (msg % args))
+ sys.exit(1)
+
+def warn(msg, *args):
+ sys.stderr.write('WARNING: %s\n' % (msg % args))
+
+def gittz(tz):
+ return '%+03d%02d' % (tz / 3600, tz % 3600 / 60)
+
+class Marks:
+
+ def __init__(self, path):
+ self.path = path
+ self.tips = {}
+ self.marks = {}
+ self.rev_marks = {}
+ self.last_mark = 0
+ self.load()
+
+ def load(self):
+ if not os.path.exists(self.path):
+ return
+
+ tmp = json.load(open(self.path))
+ self.tips = tmp['tips']
+ self.marks = tmp['marks']
+ self.last_mark = tmp['last-mark']
+
+ for rev, mark in self.marks.iteritems():
+ self.rev_marks[mark] = rev
+
+ def dict(self):
+ return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }
+
+ def store(self):
+ json.dump(self.dict(), open(self.path, 'w'))
+
+ def __str__(self):
+ return str(self.dict())
+
+ def from_rev(self, rev):
+ return self.marks[rev]
+
+ def to_rev(self, mark):
+ return self.rev_marks[mark]
+
+ def next_mark(self):
+ self.last_mark += 1
+ return self.last_mark
+
+ def get_mark(self, rev):
+ self.last_mark += 1
+ self.marks[rev] = self.last_mark
+ return self.last_mark
+
+ def is_marked(self, rev):
+ return self.marks.has_key(rev)
+
+ def new_mark(self, rev, mark):
+ self.marks[rev] = mark
+ self.rev_marks[mark] = rev
+ self.last_mark = mark
+
+ def get_tip(self, branch):
+ return self.tips.get(branch, None)
+
+ def set_tip(self, branch, tip):
+ self.tips[branch] = tip
+
+class Parser:
+
+ def __init__(self, repo):
+ self.repo = repo
+ self.line = self.get_line()
+
+ def get_line(self):
+ return sys.stdin.readline().strip()
+
+ def __getitem__(self, i):
+ return self.line.split()[i]
+
+ def check(self, word):
+ return self.line.startswith(word)
+
+ def each_block(self, separator):
+ while self.line != separator:
+ yield self.line
+ self.line = self.get_line()
+
+ def __iter__(self):
+ return self.each_block('')
+
+ def next(self):
+ self.line = self.get_line()
+ if self.line == 'done':
+ self.line = None
+
+ def get_mark(self):
+ i = self.line.index(':') + 1
+ return int(self.line[i:])
+
+ def get_data(self):
+ if not self.check('data'):
+ return None
+ i = self.line.index(' ') + 1
+ size = int(self.line[i:])
+ return sys.stdin.read(size)
+
+ def get_author(self):
+ m = RAW_AUTHOR_RE.match(self.line)
+ if not m:
+ return None
+ _, name, email, date, tz = m.groups()
+ committer = '%s <%s>' % (name, email)
+ tz = int(tz)
+ tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
+ return (committer, int(date), tz)
+
+def rev_to_mark(rev):
+ global marks
+ return marks.from_rev(rev)
+
+def mark_to_rev(mark):
+ global marks
+ return marks.to_rev(mark)
+
+def fixup_user(user):
+ name = mail = None
+ user = user.replace('"', '')
+ m = AUTHOR_RE.match(user)
+ if m:
+ name = m.group(1)
+ mail = m.group(2).strip()
+ else:
+ m = NAME_RE.match(user)
+ if m:
+ name = m.group(1).strip()
+
+ return '%s <%s>' % (name, mail)
+
+def get_filechanges(cur, prev):
+ modified = {}
+ removed = {}
+
+ changes = cur.changes_from(prev)
+
+ for path, fid, kind in changes.added:
+ modified[path] = fid
+ for path, fid, kind in changes.removed:
+ removed[path] = None
+ for path, fid, kind, mod, _ in changes.modified:
+ modified[path] = fid
+ for oldpath, newpath, fid, kind, mod, _ in changes.renamed:
+ removed[oldpath] = None
+ modified[newpath] = fid
+
+ return modified, removed
+
+def export_files(tree, files):
+ global marks, filenodes
+
+ final = []
+ for path, fid in files.iteritems():
+ kind = tree.kind(fid)
+
+ h = tree.get_file_sha1(fid)
+
+ if kind == 'symlink':
+ d = tree.get_symlink_target(fid)
+ mode = '120000'
+ elif kind == 'file':
+
+ if tree.is_executable(fid):
+ mode = '100755'
+ else:
+ mode = '100644'
+
+ # is the blog already exported?
+ if h in filenodes:
+ mark = filenodes[h]
+ final.append((mode, mark, path))
+ continue
+
+ d = tree.get_file_text(fid)
+ elif kind == 'directory':
+ continue
+ else:
+ die("Unhandled kind '%s' for path '%s'" % (kind, path))
+
+ mark = marks.next_mark()
+ filenodes[h] = mark
+
+ print "blob"
+ print "mark :%u" % mark
+ print "data %d" % len(d)
+ print d
+
+ final.append((mode, mark, path))
+
+ return final
+
+def export_branch(branch, name):
+ global prefix, dirname
+
+ ref = '%s/heads/%s' % (prefix, name)
+ tip = marks.get_tip(name)
+
+ repo = branch.repository
+ repo.lock_read()
+ revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward')
+ count = 0
+
+ revs = [revid for revid, _, _, _ in revs if not marks.is_marked(revid)]
+
+ for revid in revs:
+
+ rev = repo.get_revision(revid)
+
+ parents = rev.parent_ids
+ time = rev.timestamp
+ tz = rev.timezone
+ committer = rev.committer.encode('utf-8')
+ committer = "%s %u %s" % (fixup_user(committer), time, gittz(tz))
+ author = committer
+ msg = rev.message.encode('utf-8')
+
+ msg += '\n'
+
+ if len(parents) == 0:
+ parent = bzrlib.revision.NULL_REVISION
+ else:
+ parent = parents[0]
+
+ cur_tree = repo.revision_tree(revid)
+ prev = repo.revision_tree(parent)
+ modified, removed = get_filechanges(cur_tree, prev)
+
+ modified_final = export_files(cur_tree, modified)
+
+ if len(parents) == 0:
+ print 'reset %s' % ref
+
+ print "commit %s" % ref
+ print "mark :%d" % (marks.get_mark(revid))
+ print "author %s" % (author)
+ print "committer %s" % (committer)
+ print "data %d" % (len(msg))
+ print msg
+
+ for i, p in enumerate(parents):
+ try:
+ m = rev_to_mark(p)
+ except KeyError:
+ # ghost?
+ continue
+ if i == 0:
+ print "from :%s" % m
+ else:
+ print "merge :%s" % m
+
+ for f in modified_final:
+ print "M %s :%u %s" % f
+ for f in removed:
+ print "D %s" % (f)
+ print
+
+ count += 1
+ if (count % 100 == 0):
+ print "progress revision %s (%d/%d)" % (revid, count, len(revs))
+ print "#############################################################"
+
+ repo.unlock()
+
+ revid = branch.last_revision()
+
+ # make sure the ref is updated
+ print "reset %s" % ref
+ print "from :%u" % rev_to_mark(revid)
+ print
+
+ marks.set_tip(name, revid)
+
+def export_tag(repo, name):
+ global tags
+ try:
+ print "reset refs/tags/%s" % name
+ print "from :%u" % rev_to_mark(tags[name])
+ print
+ except KeyError:
+ warn("TODO: fetch tag '%s'" % name)
+
+def do_import(parser):
+ global dirname
+
+ branch = parser.repo
+ path = os.path.join(dirname, 'marks-git')
+
+ print "feature done"
+ if os.path.exists(path):
+ print "feature import-marks=%s" % path
+ print "feature export-marks=%s" % path
+ sys.stdout.flush()
+
+ while parser.check('import'):
+ ref = parser[1]
+ if ref.startswith('refs/heads/'):
+ name = ref[len('refs/heads/'):]
+ export_branch(branch, name)
+ if ref.startswith('refs/tags/'):
+ name = ref[len('refs/tags/'):]
+ export_tag(branch, name)
+ parser.next()
+
+ print 'done'
+
+ sys.stdout.flush()
+
+def parse_blob(parser):
+ global blob_marks
+
+ parser.next()
+ mark = parser.get_mark()
+ parser.next()
+ data = parser.get_data()
+ blob_marks[mark] = data
+ parser.next()
+
+class CustomTree():
+
+ def __init__(self, repo, revid, parents, files):
+ global files_cache
+
+ self.repo = repo
+ self.revid = revid
+ self.parents = parents
+ self.updates = {}
+
+ def copy_tree(revid):
+ files = files_cache[revid] = {}
+ tree = repo.repository.revision_tree(revid)
+ repo.lock_read()
+ try:
+ for path, entry in tree.iter_entries_by_dir():
+ files[path] = entry.file_id
+ finally:
+ repo.unlock()
+ return files
+
+ if len(parents) == 0:
+ self.base_id = bzrlib.revision.NULL_REVISION
+ self.base_files = {}
+ else:
+ self.base_id = parents[0]
+ self.base_files = files_cache.get(self.base_id, None)
+ if not self.base_files:
+ self.base_files = copy_tree(self.base_id)
+
+ self.files = files_cache[revid] = self.base_files.copy()
+
+ for path, f in files.iteritems():
+ fid = self.files.get(path, None)
+ if not fid:
+ fid = bzrlib.generate_ids.gen_file_id(path)
+ f['path'] = path
+ self.updates[fid] = f
+
+ def last_revision(self):
+ return self.base_id
+
+ def iter_changes(self):
+ changes = []
+
+ def get_parent(dirname, basename):
+ parent_fid = self.base_files.get(dirname, None)
+ if parent_fid:
+ return parent_fid
+ parent_fid = self.files.get(dirname, None)
+ if parent_fid:
+ return parent_fid
+ if basename == '':
+ return None
+ fid = bzrlib.generate_ids.gen_file_id(path)
+ d = add_entry(fid, dirname, 'directory')
+ return fid
+
+ def add_entry(fid, path, kind, mode = None):
+ dirname, basename = os.path.split(path)
+ parent_fid = get_parent(dirname, basename)
+
+ executable = False
+ if mode == '100755':
+ executable = True
+ elif mode == '120000':
+ kind = 'symlink'
+
+ change = (fid,
+ (None, path),
+ True,
+ (False, True),
+ (None, parent_fid),
+ (None, basename),
+ (None, kind),
+ (None, executable))
+ self.files[path] = change[0]
+ changes.append(change)
+ return change
+
+ def update_entry(fid, path, kind, mode = None):
+ dirname, basename = os.path.split(path)
+ parent_fid = get_parent(dirname, basename)
+
+ executable = False
+ if mode == '100755':
+ executable = True
+ elif mode == '120000':
+ kind = 'symlink'
+
+ change = (fid,
+ (path, path),
+ True,
+ (True, True),
+ (None, parent_fid),
+ (None, basename),
+ (None, kind),
+ (None, executable))
+ self.files[path] = change[0]
+ changes.append(change)
+ return change
+
+ def remove_entry(fid, path, kind):
+ dirname, basename = os.path.split(path)
+ parent_fid = get_parent(dirname, basename)
+ change = (fid,
+ (path, None),
+ True,
+ (True, False),
+ (parent_fid, None),
+ (None, None),
+ (None, None),
+ (None, None))
+ del self.files[path]
+ changes.append(change)
+ return change
+
+ for fid, f in self.updates.iteritems():
+ path = f['path']
+
+ if 'deleted' in f:
+ remove_entry(fid, path, 'file')
+ continue
+
+ if path in self.base_files:
+ update_entry(fid, path, 'file', f['mode'])
+ else:
+ add_entry(fid, path, 'file', f['mode'])
+
+ return changes
+
+ def get_file_with_stat(self, file_id, path=None):
+ return (StringIO.StringIO(self.updates[file_id]['data']), None)
+
+ def get_symlink_target(self, file_id):
+ return self.updates[file_id]['data']
+
+def parse_commit(parser):
+ global marks, blob_marks, bmarks, parsed_refs
+ global mode
+
+ parents = []
+
+ ref = parser[1]
+ parser.next()
+
+ if ref != 'refs/heads/master':
+ die("bzr doesn't support multiple branches; use 'master'")
+
+ commit_mark = parser.get_mark()
+ parser.next()
+ author = parser.get_author()
+ parser.next()
+ committer = parser.get_author()
+ parser.next()
+ data = parser.get_data()
+ parser.next()
+ if parser.check('from'):
+ parents.append(parser.get_mark())
+ parser.next()
+ while parser.check('merge'):
+ parents.append(parser.get_mark())
+ parser.next()
+
+ files = {}
+
+ for line in parser:
+ if parser.check('M'):
+ t, m, mark_ref, path = line.split(' ', 3)
+ mark = int(mark_ref[1:])
+ f = { 'mode' : m, 'data' : blob_marks[mark] }
+ elif parser.check('D'):
+ t, path = line.split(' ')
+ f = { 'deleted' : True }
+ else:
+ die('Unknown file command: %s' % line)
+ files[path] = f
+
+ repo = parser.repo
+
+ committer, date, tz = committer
+ parents = [str(mark_to_rev(p)) for p in parents]
+ revid = bzrlib.generate_ids.gen_revision_id(committer, date)
+ props = {}
+ props['branch-nick'] = repo.nick
+
+ mtree = CustomTree(repo, revid, parents, files)
+ changes = mtree.iter_changes()
+
+ repo.lock_write()
+ try:
+ builder = repo.get_commit_builder(parents, None, date, tz, committer, props, revid)
+ try:
+ list(builder.record_iter_changes(mtree, mtree.last_revision(), changes))
+ builder.finish_inventory()
+ builder.commit(data.decode('utf-8', 'replace'))
+ except Exception, e:
+ builder.abort()
+ raise
+ finally:
+ repo.unlock()
+
+ parsed_refs[ref] = revid
+ marks.new_mark(revid, commit_mark)
+
+def parse_reset(parser):
+ global parsed_refs
+
+ ref = parser[1]
+ parser.next()
+
+ if ref != 'refs/heads/master':
+ die("bzr doesn't support multiple branches; use 'master'")
+
+ # ugh
+ if parser.check('commit'):
+ parse_commit(parser)
+ return
+ if not parser.check('from'):
+ return
+ from_mark = parser.get_mark()
+ parser.next()
+
+ parsed_refs[ref] = mark_to_rev(from_mark)
+
+def do_export(parser):
+ global parsed_refs, dirname, peer
+
+ parser.next()
+
+ for line in parser.each_block('done'):
+ if parser.check('blob'):
+ parse_blob(parser)
+ elif parser.check('commit'):
+ parse_commit(parser)
+ elif parser.check('reset'):
+ parse_reset(parser)
+ elif parser.check('tag'):
+ pass
+ elif parser.check('feature'):
+ pass
+ else:
+ die('unhandled export command: %s' % line)
+
+ repo = parser.repo
+
+ for ref, revid in parsed_refs.iteritems():
+ if ref == 'refs/heads/master':
+ repo.generate_revision_history(revid, marks.get_tip('master'))
+ revno, revid = repo.last_revision_info()
+ if peer:
+ if hasattr(peer, "import_last_revision_info_and_tags"):
+ peer.import_last_revision_info_and_tags(repo, revno, revid)
+ else:
+ peer.import_last_revision_info(repo.repository, revno, revid)
+ wt = peer.bzrdir.open_workingtree()
+ else:
+ wt = repo.bzrdir.open_workingtree()
+ wt.update()
+ print "ok %s" % ref
+ print
+
+def do_capabilities(parser):
+ global dirname
+
+ print "import"
+ print "export"
+ print "refspec refs/heads/*:%s/heads/*" % prefix
+
+ path = os.path.join(dirname, 'marks-git')
+
+ if os.path.exists(path):
+ print "*import-marks %s" % path
+ print "*export-marks %s" % path
+
+ print
+
+def do_list(parser):
+ global tags
+ print "? refs/heads/%s" % 'master'
+ for tag, revid in parser.repo.tags.get_tag_dict().items():
+ print "? refs/tags/%s" % tag
+ tags[tag] = revid
+ print "@refs/heads/%s HEAD" % 'master'
+ print
+
+def get_repo(url, alias):
+ global dirname, peer
+
+ origin = bzrlib.bzrdir.BzrDir.open(url)
+ branch = origin.open_branch()
+
+ if not isinstance(origin.transport, bzrlib.transport.local.LocalTransport):
+ clone_path = os.path.join(dirname, 'clone')
+ remote_branch = branch
+ if os.path.exists(clone_path):
+ # pull
+ d = bzrlib.bzrdir.BzrDir.open(clone_path)
+ branch = d.open_branch()
+ result = branch.pull(remote_branch, [], None, False)
+ else:
+ # clone
+ d = origin.sprout(clone_path, None,
+ hardlink=True, create_tree_if_local=False,
+ source_branch=remote_branch)
+ branch = d.open_branch()
+ branch.bind(remote_branch)
+
+ peer = remote_branch
+ else:
+ peer = None
+
+ return branch
+
+def main(args):
+ global marks, prefix, dirname
+ global tags, filenodes
+ global blob_marks
+ global parsed_refs
+ global files_cache
+
+ alias = args[1]
+ url = args[2]
+
+ prefix = 'refs/bzr/%s' % alias
+ tags = {}
+ filenodes = {}
+ blob_marks = {}
+ parsed_refs = {}
+ files_cache = {}
+
+ gitdir = os.environ['GIT_DIR']
+ dirname = os.path.join(gitdir, 'bzr', alias)
+
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+
+ repo = get_repo(url, alias)
+
+ marks_path = os.path.join(dirname, 'marks-int')
+ marks = Marks(marks_path)
+
+ parser = Parser(repo)
+ for line in parser:
+ if parser.check('capabilities'):
+ do_capabilities(parser)
+ elif parser.check('list'):
+ do_list(parser)
+ elif parser.check('import'):
+ do_import(parser)
+ elif parser.check('export'):
+ do_export(parser)
+ else:
+ die('unhandled command: %s' % line)
+ sys.stdout.flush()
+
+ marks.store()
+
+sys.exit(main(sys.argv))
diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index c7006000a6..328c2dc76d 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -53,7 +53,7 @@ def gittz(tz):
return '%+03d%02d' % (-tz / 3600, -tz % 3600 / 60)
def hgmode(mode):
- m = { '0100755': 'x', '0120000': 'l' }
+ m = { '100755': 'x', '120000': 'l' }
return m.get(mode, '')
def get_config(config):
@@ -720,6 +720,14 @@ def do_export(parser):
if peer:
parser.repo.push(peer, force=False)
+def fix_path(alias, repo, orig_url):
+ repo_url = util.url(repo.url())
+ url = util.url(orig_url)
+ if str(url) == str(repo_url):
+ return
+ cmd = ['git', 'config', 'remote.%s.url' % alias, "hg::%s" % repo_url]
+ subprocess.call(cmd)
+
def main(args):
global prefix, dirname, branches, bmarks
global marks, blob_marks, parsed_refs
@@ -766,6 +774,9 @@ def main(args):
repo = get_repo(url, alias)
prefix = 'refs/hg/%s' % alias
+ if not is_tmp:
+ fix_path(alias, peer or repo, url)
+
if not os.path.exists(dirname):
os.makedirs(dirname)
diff --git a/contrib/remote-helpers/test-bzr.sh b/contrib/remote-helpers/test-bzr.sh
new file mode 100755
index 0000000000..70aa8a010a
--- /dev/null
+++ b/contrib/remote-helpers/test-bzr.sh
@@ -0,0 +1,143 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+
+test_description='Test remote-bzr'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+ skip_all='skipping remote-bzr tests; python not available'
+ test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import bzrlib'; then
+ skip_all='skipping remote-bzr tests; bzr not available'
+ test_done
+fi
+
+cmd='
+import bzrlib
+bzrlib.initialize()
+import bzrlib.plugin
+bzrlib.plugin.load_plugins()
+import bzrlib.plugins.fastimport
+'
+
+if ! "$PYTHON_PATH" -c "$cmd"; then
+ echo "consider setting BZR_PLUGIN_PATH=$HOME/.bazaar/plugins" 1>&2
+ skip_all='skipping remote-bzr tests; bzr-fastimport not available'
+ test_done
+fi
+
+check () {
+ (cd $1 &&
+ git log --format='%s' -1 &&
+ git symbolic-ref HEAD) > actual &&
+ (echo $2 &&
+ echo "refs/heads/$3") > expected &&
+ test_cmp expected actual
+}
+
+bzr whoami "A U Thor <author@example.com>"
+
+test_expect_success 'cloning' '
+ (bzr init bzrrepo &&
+ cd bzrrepo &&
+ echo one > content &&
+ bzr add content &&
+ bzr commit -m one
+ ) &&
+
+ git clone "bzr::$PWD/bzrrepo" gitrepo &&
+ check gitrepo one master
+'
+
+test_expect_success 'pulling' '
+ (cd bzrrepo &&
+ echo two > content &&
+ bzr commit -m two
+ ) &&
+
+ (cd gitrepo && git pull) &&
+
+ check gitrepo two master
+'
+
+test_expect_success 'pushing' '
+ (cd gitrepo &&
+ echo three > content &&
+ git commit -a -m three &&
+ git push
+ ) &&
+
+ echo three > expected &&
+ cat bzrrepo/content > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'roundtrip' '
+ (cd gitrepo &&
+ git pull &&
+ git log --format="%s" -1 origin/master > actual) &&
+ echo three > expected &&
+ test_cmp expected actual &&
+
+ (cd gitrepo && git push && git pull) &&
+
+ (cd bzrrepo &&
+ echo four > content &&
+ bzr commit -m four
+ ) &&
+
+ (cd gitrepo && git pull && git push) &&
+
+ check gitrepo four master &&
+
+ (cd gitrepo &&
+ echo five > content &&
+ git commit -a -m five &&
+ git push && git pull
+ ) &&
+
+ (cd bzrrepo && bzr revert) &&
+
+ echo five > expected &&
+ cat bzrrepo/content > actual &&
+ test_cmp expected actual
+'
+
+cat > expected <<EOF
+100644 blob 54f9d6da5c91d556e6b54340b1327573073030af content
+100755 blob 68769579c3eaadbe555379b9c3538e6628bae1eb executable
+120000 blob 6b584e8ece562ebffc15d38808cd6b98fc3d97ea link
+EOF
+
+test_expect_success 'special modes' '
+ (cd bzrrepo &&
+ echo exec > executable
+ chmod +x executable &&
+ bzr add executable
+ bzr commit -m exec &&
+ ln -s content link
+ bzr add link
+ bzr commit -m link &&
+ mkdir dir &&
+ bzr add dir &&
+ bzr commit -m dir) &&
+
+ (cd gitrepo &&
+ git pull
+ git ls-tree HEAD > ../actual) &&
+
+ test_cmp expected actual &&
+
+ (cd gitrepo &&
+ git cat-file -p HEAD:link > ../actual) &&
+
+ echo -n content > expected &&
+ test_cmp expected actual
+'
+
+test_done
diff --git a/contrib/remote-helpers/test-hg-hg-git.sh b/contrib/remote-helpers/test-hg-hg-git.sh
index 3e76d9fb60..7e3967f5b6 100755
--- a/contrib/remote-helpers/test-hg-hg-git.sh
+++ b/contrib/remote-helpers/test-hg-hg-git.sh
@@ -109,6 +109,74 @@ setup () {
setup
+test_expect_success 'executable bit' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ git init -q gitrepo &&
+ cd gitrepo &&
+ echo alpha > alpha &&
+ chmod 0644 alpha &&
+ git add alpha &&
+ git commit -m "add alpha" &&
+ chmod 0755 alpha &&
+ git add alpha &&
+ git commit -m "set executable bit" &&
+ chmod 0644 alpha &&
+ git add alpha &&
+ git commit -m "clear executable bit"
+ ) &&
+
+ for x in hg git; do
+ (
+ hg_clone_$x gitrepo hgrepo-$x &&
+ cd hgrepo-$x &&
+ hg_log . &&
+ hg manifest -r 1 -v &&
+ hg manifest -v
+ ) > output-$x &&
+
+ git_clone_$x hgrepo-$x gitrepo2-$x &&
+ git_log gitrepo2-$x > log-$x
+ done &&
+ cp -r log-* output-* /tmp/foo/ &&
+
+ test_cmp output-hg output-git &&
+ test_cmp log-hg log-git
+'
+
+test_expect_success 'symlink' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ git init -q gitrepo &&
+ cd gitrepo &&
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -m "add alpha" &&
+ ln -s alpha beta &&
+ git add beta &&
+ git commit -m "add beta"
+ ) &&
+
+ for x in hg git; do
+ (
+ hg_clone_$x gitrepo hgrepo-$x &&
+ cd hgrepo-$x &&
+ hg_log . &&
+ hg manifest -v
+ ) > output-$x &&
+
+ git_clone_$x hgrepo-$x gitrepo2-$x &&
+ git_log gitrepo2-$x > log-$x
+ done &&
+
+ test_cmp output-hg output-git &&
+ test_cmp log-hg log-git
+'
+
test_expect_success 'merge conflict 1' '
mkdir -p tmp && cd tmp &&
test_when_finished "cd .. && rm -rf tmp" &&
diff --git a/contrib/svn-fe/svnrdump_sim.py b/contrib/svn-fe/svnrdump_sim.py
index 1cfac4a6f8..17cf6f961f 100755
--- a/contrib/svn-fe/svnrdump_sim.py
+++ b/contrib/svn-fe/svnrdump_sim.py
@@ -7,6 +7,10 @@ to the highest revision that should be available.
"""
import sys, os
+if sys.hexversion < 0x02040000:
+ # The limiter is the ValueError() calls. This may be too conservative
+ sys.stderr.write("svnrdump-sim.py: requires Python 2.4 or later.\n")
+ sys.exit(1)
def getrevlimit():
var = 'SVNRMAX'
diff --git a/contrib/vim/README b/contrib/vim/README
index fca1e17251..8f16d06972 100644
--- a/contrib/vim/README
+++ b/contrib/vim/README
@@ -17,16 +17,6 @@ To install:
1. Copy these files to vim's syntax directory $HOME/.vim/syntax
2. To auto-detect the editing of various git-related filetypes:
- $ cat >>$HOME/.vim/filetype.vim <<'EOF'
- autocmd BufNewFile,BufRead *.git/COMMIT_EDITMSG setf gitcommit
- autocmd BufNewFile,BufRead *.git/config,.gitconfig setf gitconfig
- autocmd BufNewFile,BufRead git-rebase-todo setf gitrebase
- autocmd BufNewFile,BufRead .msg.[0-9]*
- \ if getline(1) =~ '^From.*# This line is ignored.$' |
- \ setf gitsendemail |
- \ endif
- autocmd BufNewFile,BufRead *.git/**
- \ if getline(1) =~ '^\x\{40\}\>\|^ref: ' |
- \ setf git |
- \ endif
- EOF
+
+ $ curl http://ftp.vim.org/pub/vim/runtime/filetype.vim |
+ sed -ne '/^" Git$/, /^$/ p' >>$HOME/.vim/filetype.vim
diff --git a/ctype.c b/ctype.c
index 935327164b..0bfebb4e75 100644
--- a/ctype.c
+++ b/ctype.c
@@ -11,18 +11,21 @@ enum {
D = GIT_DIGIT,
G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */
R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | */
- P = GIT_PATHSPEC_MAGIC /* other non-alnum, except for ] and } */
+ P = GIT_PATHSPEC_MAGIC, /* other non-alnum, except for ] and } */
+ X = GIT_CNTRL,
+ U = GIT_PUNCT,
+ Z = GIT_CNTRL | GIT_SPACE
};
-unsigned char sane_ctype[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, 0, S, 0, 0, /* 0.. 15 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16.. 31 */
+const unsigned char sane_ctype[256] = {
+ X, X, X, X, X, X, X, X, X, Z, Z, X, X, Z, X, X, /* 0.. 15 */
+ X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 16.. 31 */
S, P, P, P, R, P, P, P, R, R, G, R, P, P, R, P, /* 32.. 47 */
D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, G, /* 48.. 63 */
P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */
- A, A, A, A, A, A, A, A, A, A, A, G, G, 0, R, P, /* 80.. 95 */
+ A, A, A, A, A, A, A, A, A, A, A, G, G, U, R, P, /* 80.. 95 */
P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */
- A, A, A, A, A, A, A, A, A, A, A, R, R, 0, P, 0, /* 112..127 */
+ A, A, A, A, A, A, A, A, A, A, A, R, R, U, P, X, /* 112..127 */
/* Nothing in the 128.. range */
};
diff --git a/diff.c b/diff.c
index 732d4c2275..348f71b462 100644
--- a/diff.c
+++ b/diff.c
@@ -3626,6 +3626,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
DIFF_OPT_SET(options, FIND_COPIES_HARDER);
else if (!strcmp(arg, "--follow"))
DIFF_OPT_SET(options, FOLLOW_RENAMES);
+ else if (!strcmp(arg, "--no-follow"))
+ DIFF_OPT_CLR(options, FOLLOW_RENAMES);
else if (!strcmp(arg, "--color"))
options->use_color = 1;
else if (!prefixcmp(arg, "--color=")) {
diff --git a/dir.c b/dir.c
index 5a83aa7897..9dde68a2f3 100644
--- a/dir.c
+++ b/dir.c
@@ -2,12 +2,15 @@
* This handles recursive filename detection with exclude
* files, index knowledge etc..
*
+ * See Documentation/technical/api-directory-listing.txt
+ *
* Copyright (C) Linus Torvalds, 2005-2006
* Junio Hamano, 2005-2006
*/
#include "cache.h"
#include "dir.h"
#include "refs.h"
+#include "wildmatch.h"
struct path_simplify {
int len;
@@ -34,10 +37,33 @@ int fnmatch_icase(const char *pattern, const char *string, int flags)
return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
}
+inline int git_fnmatch(const char *pattern, const char *string,
+ int flags, int prefix)
+{
+ int fnm_flags = 0;
+ if (flags & GFNM_PATHNAME)
+ fnm_flags |= FNM_PATHNAME;
+ if (prefix > 0) {
+ if (strncmp(pattern, string, prefix))
+ return FNM_NOMATCH;
+ pattern += prefix;
+ string += prefix;
+ }
+ if (flags & GFNM_ONESTAR) {
+ int pattern_len = strlen(++pattern);
+ int string_len = strlen(string);
+ return string_len < pattern_len ||
+ strcmp(pattern,
+ string + string_len - pattern_len);
+ }
+ return fnmatch(pattern, string, fnm_flags);
+}
+
static size_t common_prefix_len(const char **pathspec)
{
const char *n, *first;
size_t max = 0;
+ int literal = limit_pathspec_to_literal();
if (!pathspec)
return max;
@@ -47,7 +73,7 @@ static size_t common_prefix_len(const char **pathspec)
size_t i, len = 0;
for (i = 0; first == n || i < max; i++) {
char c = n[i];
- if (!c || c != first[i] || is_glob_special(c))
+ if (!c || c != first[i] || (!literal && is_glob_special(c)))
break;
if (c == '/')
len = i + 1;
@@ -117,6 +143,7 @@ int within_depth(const char *name, int namelen,
static int match_one(const char *match, const char *name, int namelen)
{
int matchlen;
+ int literal = limit_pathspec_to_literal();
/* If the match was just the prefix, we matched */
if (!*match)
@@ -126,7 +153,7 @@ static int match_one(const char *match, const char *name, int namelen)
for (;;) {
unsigned char c1 = tolower(*match);
unsigned char c2 = tolower(*name);
- if (c1 == '\0' || is_glob_special(c1))
+ if (c1 == '\0' || (!literal && is_glob_special(c1)))
break;
if (c1 != c2)
return 0;
@@ -138,7 +165,7 @@ static int match_one(const char *match, const char *name, int namelen)
for (;;) {
unsigned char c1 = *match;
unsigned char c2 = *name;
- if (c1 == '\0' || is_glob_special(c1))
+ if (c1 == '\0' || (!literal && is_glob_special(c1)))
break;
if (c1 != c2)
return 0;
@@ -148,14 +175,16 @@ static int match_one(const char *match, const char *name, int namelen)
}
}
-
/*
* If we don't match the matchstring exactly,
* we need to match by fnmatch
*/
matchlen = strlen(match);
- if (strncmp_icase(match, name, matchlen))
+ if (strncmp_icase(match, name, matchlen)) {
+ if (literal)
+ return 0;
return !fnmatch_icase(match, name, 0) ? MATCHED_FNMATCH : 0;
+ }
if (namelen == matchlen)
return MATCHED_EXACTLY;
@@ -230,7 +259,10 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
return MATCHED_RECURSIVELY;
}
- if (item->use_wildcard && !fnmatch(match, name, 0))
+ if (item->nowildcard_len < item->len &&
+ !git_fnmatch(match, name,
+ item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+ item->nowildcard_len - prefix))
return MATCHED_FNMATCH;
return 0;
@@ -347,7 +379,7 @@ void parse_exclude_pattern(const char **pattern,
}
void add_exclude(const char *string, const char *base,
- int baselen, struct exclude_list *which)
+ int baselen, struct exclude_list *el)
{
struct exclude *x;
int patternlen;
@@ -371,8 +403,8 @@ void add_exclude(const char *string, const char *base,
x->base = base;
x->baselen = baselen;
x->flags = flags;
- ALLOC_GROW(which->excludes, which->nr + 1, which->alloc);
- which->excludes[which->nr++] = x;
+ ALLOC_GROW(el->excludes, el->nr + 1, el->alloc);
+ el->excludes[el->nr++] = x;
}
static void *read_skip_worktree_file_from_index(const char *path, size_t *size)
@@ -398,7 +430,11 @@ static void *read_skip_worktree_file_from_index(const char *path, size_t *size)
return data;
}
-void free_excludes(struct exclude_list *el)
+/*
+ * Frees memory within el which was allocated for exclude patterns and
+ * the file buffer. Does not free el itself.
+ */
+void clear_exclude_list(struct exclude_list *el)
{
int i;
@@ -414,7 +450,7 @@ int add_excludes_from_file_to_list(const char *fname,
const char *base,
int baselen,
char **buf_p,
- struct exclude_list *which,
+ struct exclude_list *el,
int check_index)
{
struct stat st;
@@ -463,7 +499,7 @@ int add_excludes_from_file_to_list(const char *fname,
if (buf[i] == '\n') {
if (entry != buf + i && entry[0] != '#') {
buf[i - (i && buf[i-1] == '\r')] = 0;
- add_exclude(entry, base, baselen, which);
+ add_exclude(entry, base, baselen, el);
}
entry = buf + i + 1;
}
@@ -478,6 +514,10 @@ void add_excludes_from_file(struct dir_struct *dir, const char *fname)
die("cannot use %s as an exclude file", fname);
}
+/*
+ * Loads the per-directory exclude list for the substring of base
+ * which has a char length of baselen.
+ */
static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
{
struct exclude_list *el;
@@ -488,7 +528,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
(baselen + strlen(dir->exclude_per_dir) >= PATH_MAX))
return; /* too long a path -- ignore */
- /* Pop the ones that are not the prefix of the path being checked. */
+ /* Pop the directories that are not the prefix of the path being checked. */
el = &dir->exclude_list[EXC_DIRS];
while ((stk = dir->exclude_stack) != NULL) {
if (stk->baselen <= baselen &&
@@ -595,25 +635,30 @@ int match_pathname(const char *pathname, int pathlen,
namelen -= prefix;
}
- return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
+ return wildmatch(pattern, name,
+ ignore_case ? FNM_CASEFOLD : 0) == 0;
}
-/* Scan the list and let the last match determine the fate.
- * Return 1 for exclude, 0 for include and -1 for undecided.
+/*
+ * Scan the given exclude list in reverse to see whether pathname
+ * should be ignored. The first match (i.e. the last on the list), if
+ * any, determines the fate. Returns the exclude_list element which
+ * matched, or NULL for undecided.
*/
-int excluded_from_list(const char *pathname,
- int pathlen, const char *basename, int *dtype,
- struct exclude_list *el)
+static struct exclude *last_exclude_matching_from_list(const char *pathname,
+ int pathlen,
+ const char *basename,
+ int *dtype,
+ struct exclude_list *el)
{
int i;
if (!el->nr)
- return -1; /* undefined */
+ return NULL; /* undefined */
for (i = el->nr - 1; 0 <= i; i--) {
struct exclude *x = el->excludes[i];
const char *exclude = x->pattern;
- int to_exclude = x->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
int prefix = x->nowildcardlen;
if (x->flags & EXC_FLAG_MUSTBEDIR) {
@@ -628,7 +673,7 @@ int excluded_from_list(const char *pathname,
pathlen - (basename - pathname),
exclude, prefix, x->patternlen,
x->flags))
- return to_exclude;
+ return x;
continue;
}
@@ -636,28 +681,64 @@ int excluded_from_list(const char *pathname,
if (match_pathname(pathname, pathlen,
x->base, x->baselen ? x->baselen - 1 : 0,
exclude, prefix, x->patternlen, x->flags))
- return to_exclude;
+ return x;
}
+ return NULL; /* undecided */
+}
+
+/*
+ * Scan the list and let the last match determine the fate.
+ * Return 1 for exclude, 0 for include and -1 for undecided.
+ */
+int is_excluded_from_list(const char *pathname,
+ int pathlen, const char *basename, int *dtype,
+ struct exclude_list *el)
+{
+ struct exclude *exclude;
+ exclude = last_exclude_matching_from_list(pathname, pathlen, basename, dtype, el);
+ if (exclude)
+ return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
return -1; /* undecided */
}
-static int excluded(struct dir_struct *dir, const char *pathname, int *dtype_p)
+/*
+ * Loads the exclude lists for the directory containing pathname, then
+ * scans all exclude lists to determine whether pathname is excluded.
+ * Returns the exclude_list element which matched, or NULL for
+ * undecided.
+ */
+static struct exclude *last_exclude_matching(struct dir_struct *dir,
+ const char *pathname,
+ int *dtype_p)
{
int pathlen = strlen(pathname);
int st;
+ struct exclude *exclude;
const char *basename = strrchr(pathname, '/');
basename = (basename) ? basename+1 : pathname;
prep_exclude(dir, pathname, basename-pathname);
for (st = EXC_CMDL; st <= EXC_FILE; st++) {
- switch (excluded_from_list(pathname, pathlen, basename,
- dtype_p, &dir->exclude_list[st])) {
- case 0:
- return 0;
- case 1:
- return 1;
- }
+ exclude = last_exclude_matching_from_list(
+ pathname, pathlen, basename, dtype_p,
+ &dir->exclude_list[st]);
+ if (exclude)
+ return exclude;
}
+ return NULL;
+}
+
+/*
+ * Loads the exclude lists for the directory containing pathname, then
+ * scans all exclude lists to determine whether pathname is excluded.
+ * Returns 1 if true, otherwise 0.
+ */
+static int is_excluded(struct dir_struct *dir, const char *pathname, int *dtype_p)
+{
+ struct exclude *exclude =
+ last_exclude_matching(dir, pathname, dtype_p);
+ if (exclude)
+ return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
return 0;
}
@@ -665,6 +746,7 @@ void path_exclude_check_init(struct path_exclude_check *check,
struct dir_struct *dir)
{
check->dir = dir;
+ check->exclude = NULL;
strbuf_init(&check->path, 256);
}
@@ -674,32 +756,41 @@ void path_exclude_check_clear(struct path_exclude_check *check)
}
/*
- * Is this name excluded? This is for a caller like show_files() that
- * do not honor directory hierarchy and iterate through paths that are
- * possibly in an ignored directory.
+ * For each subdirectory in name, starting with the top-most, checks
+ * to see if that subdirectory is excluded, and if so, returns the
+ * corresponding exclude structure. Otherwise, checks whether name
+ * itself (which is presumably a file) is excluded.
*
* A path to a directory known to be excluded is left in check->path to
* optimize for repeated checks for files in the same excluded directory.
*/
-int path_excluded(struct path_exclude_check *check,
- const char *name, int namelen, int *dtype)
+struct exclude *last_exclude_matching_path(struct path_exclude_check *check,
+ const char *name, int namelen,
+ int *dtype)
{
int i;
struct strbuf *path = &check->path;
+ struct exclude *exclude;
/*
* we allow the caller to pass namelen as an optimization; it
* must match the length of the name, as we eventually call
- * excluded() on the whole name string.
+ * is_excluded() on the whole name string.
*/
if (namelen < 0)
namelen = strlen(name);
+ /*
+ * If path is non-empty, and name is equal to path or a
+ * subdirectory of path, name should be excluded, because
+ * it's inside a directory which is already known to be
+ * excluded and was previously left in check->path.
+ */
if (path->len &&
path->len <= namelen &&
!memcmp(name, path->buf, path->len) &&
(!name[path->len] || name[path->len] == '/'))
- return 1;
+ return check->exclude;
strbuf_setlen(path, 0);
for (i = 0; name[i]; i++) {
@@ -707,8 +798,12 @@ int path_excluded(struct path_exclude_check *check,
if (ch == '/') {
int dt = DT_DIR;
- if (excluded(check->dir, path->buf, &dt))
- return 1;
+ exclude = last_exclude_matching(check->dir,
+ path->buf, &dt);
+ if (exclude) {
+ check->exclude = exclude;
+ return exclude;
+ }
}
strbuf_addch(path, ch);
}
@@ -716,7 +811,22 @@ int path_excluded(struct path_exclude_check *check,
/* An entry in the index; cannot be a directory with subentries */
strbuf_setlen(path, 0);
- return excluded(check->dir, name, dtype);
+ return last_exclude_matching(check->dir, name, dtype);
+}
+
+/*
+ * Is this name excluded? This is for a caller like show_files() that
+ * do not honor directory hierarchy and iterate through paths that are
+ * possibly in an ignored directory.
+ */
+int is_path_excluded(struct path_exclude_check *check,
+ const char *name, int namelen, int *dtype)
+{
+ struct exclude *exclude =
+ last_exclude_matching_path(check, name, namelen, dtype);
+ if (exclude)
+ return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
+ return 0;
}
static struct dir_entry *dir_entry_new(const char *pathname, int len)
@@ -732,7 +842,8 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len)
static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
{
- if (cache_name_exists(pathname, len, ignore_case))
+ if (!(dir->flags & DIR_SHOW_IGNORED) &&
+ cache_name_exists(pathname, len, ignore_case))
return NULL;
ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
@@ -834,8 +945,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
* traversal routine.
*
* Case 1: If we *already* have entries in the index under that
- * directory name, we always recurse into the directory to see
- * all the files.
+ * directory name, we recurse into the directory to see all the files,
+ * unless the directory is excluded and we want to show ignored
+ * directories
*
* Case 2: If we *already* have that directory name as a gitlink,
* we always continue to see it as a gitlink, regardless of whether
@@ -849,6 +961,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
* just a directory, unless "hide_empty_directories" is
* also true and the directory is empty, in which case
* we just ignore it entirely.
+ * if we are looking for ignored directories, look if it
+ * contains only ignored files to decide if it must be shown as
+ * ignored or not.
* (b) if it looks like a git directory, and we don't have
* 'no_gitlinks' set we treat it as a gitlink, and show it
* as a directory.
@@ -861,12 +976,15 @@ enum directory_treatment {
};
static enum directory_treatment treat_directory(struct dir_struct *dir,
- const char *dirname, int len,
+ const char *dirname, int len, int exclude,
const struct path_simplify *simplify)
{
/* The "len-1" is to strip the final '/' */
switch (directory_exists_in_index(dirname, len-1)) {
case index_directory:
+ if ((dir->flags & DIR_SHOW_OTHER_DIRECTORIES) && exclude)
+ break;
+
return recurse_into_directory;
case index_gitdir:
@@ -886,7 +1004,23 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
}
/* This is the "show_other_directories" case */
- if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
+
+ /*
+ * We are looking for ignored files and our directory is not ignored,
+ * check if it contains only ignored files
+ */
+ if ((dir->flags & DIR_SHOW_IGNORED) && !exclude) {
+ int ignored;
+ dir->flags &= ~DIR_SHOW_IGNORED;
+ dir->flags |= DIR_HIDE_EMPTY_DIRECTORIES;
+ ignored = read_directory_recursive(dir, dirname, len, 1, simplify);
+ dir->flags &= ~DIR_HIDE_EMPTY_DIRECTORIES;
+ dir->flags |= DIR_SHOW_IGNORED;
+
+ return ignored ? ignore_directory : show_directory;
+ }
+ if (!(dir->flags & DIR_SHOW_IGNORED) &&
+ !(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
return show_directory;
if (!read_directory_recursive(dir, dirname, len, 1, simplify))
return ignore_directory;
@@ -894,6 +1028,45 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
}
/*
+ * Decide what to do when we find a file while traversing the
+ * filesystem. Mostly two cases:
+ *
+ * 1. We are looking for ignored files
+ * (a) File is ignored, include it
+ * (b) File is in ignored path, include it
+ * (c) File is not ignored, exclude it
+ *
+ * 2. Other scenarios, include the file if not excluded
+ *
+ * Return 1 for exclude, 0 for include.
+ */
+static int treat_file(struct dir_struct *dir, struct strbuf *path, int exclude, int *dtype)
+{
+ struct path_exclude_check check;
+ int exclude_file = 0;
+
+ if (exclude)
+ exclude_file = !(dir->flags & DIR_SHOW_IGNORED);
+ else if (dir->flags & DIR_SHOW_IGNORED) {
+ /* Always exclude indexed files */
+ struct cache_entry *ce = index_name_exists(&the_index,
+ path->buf, path->len, ignore_case);
+
+ if (ce)
+ return 1;
+
+ path_exclude_check_init(&check, dir);
+
+ if (!is_path_excluded(&check, path->buf, path->len, dtype))
+ exclude_file = 1;
+
+ path_exclude_check_clear(&check);
+ }
+
+ return exclude_file;
+}
+
+/*
* This is an inexact early pruning of any recursive directory
* reading - if the path cannot possibly be in the pathspec,
* return true, and we'll skip it early.
@@ -1016,7 +1189,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
const struct path_simplify *simplify,
int dtype, struct dirent *de)
{
- int exclude = excluded(dir, path->buf, &dtype);
+ int exclude = is_excluded(dir, path->buf, &dtype);
if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
&& exclude_matches_pathspec(path->buf, path->len, simplify))
dir_add_ignored(dir, path->buf, path->len);
@@ -1031,27 +1204,14 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
if (dtype == DT_UNKNOWN)
dtype = get_dtype(de, path->buf, path->len);
- /*
- * Do we want to see just the ignored files?
- * We still need to recurse into directories,
- * even if we don't ignore them, since the
- * directory may contain files that we do..
- */
- if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
- if (dtype != DT_DIR)
- return path_ignored;
- }
-
switch (dtype) {
default:
return path_ignored;
case DT_DIR:
strbuf_addch(path, '/');
- switch (treat_directory(dir, path->buf, path->len, simplify)) {
+
+ switch (treat_directory(dir, path->buf, path->len, exclude, simplify)) {
case show_directory:
- if (exclude != !!(dir->flags
- & DIR_SHOW_IGNORED))
- return path_ignored;
break;
case recurse_into_directory:
return path_recurse;
@@ -1061,7 +1221,12 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
break;
case DT_REG:
case DT_LNK:
- break;
+ switch (treat_file(dir, path, exclude, &dtype)) {
+ case 1:
+ return path_ignored;
+ default:
+ break;
+ }
}
return path_handled;
}
@@ -1429,9 +1594,18 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
item->match = path;
item->len = strlen(path);
- item->use_wildcard = !no_wildcard(path);
- if (item->use_wildcard)
- pathspec->has_wildcard = 1;
+ item->flags = 0;
+ if (limit_pathspec_to_literal()) {
+ item->nowildcard_len = item->len;
+ } else {
+ item->nowildcard_len = simple_length(path);
+ if (item->nowildcard_len < item->len) {
+ pathspec->has_wildcard = 1;
+ if (path[item->nowildcard_len] == '*' &&
+ no_wildcard(path + item->nowildcard_len + 1))
+ item->flags |= PATHSPEC_ONESTAR;
+ }
+ }
}
qsort(pathspec->items, pathspec->nr,
@@ -1445,3 +1619,11 @@ void free_pathspec(struct pathspec *pathspec)
free(pathspec->items);
pathspec->items = NULL;
}
+
+int limit_pathspec_to_literal(void)
+{
+ static int flag = -1;
+ if (flag < 0)
+ flag = git_env_bool(GIT_LITERAL_PATHSPECS_ENVIRONMENT, 0);
+ return flag;
+}
diff --git a/dir.h b/dir.h
index f5c89e3b80..ae1bc467ae 100644
--- a/dir.h
+++ b/dir.h
@@ -1,6 +1,8 @@
#ifndef DIR_H
#define DIR_H
+/* See Documentation/technical/api-directory-listing.txt */
+
#include "strbuf.h"
struct dir_entry {
@@ -13,6 +15,12 @@ struct dir_entry {
#define EXC_FLAG_MUSTBEDIR 8
#define EXC_FLAG_NEGATIVE 16
+/*
+ * Each .gitignore file will be parsed into patterns which are then
+ * appended to the relevant exclude_list (either EXC_DIRS or
+ * EXC_FILE). exclude_lists are also used to represent the list of
+ * --exclude values passed via CLI args (EXC_CMDL).
+ */
struct exclude_list {
int nr;
int alloc;
@@ -26,9 +34,15 @@ struct exclude_list {
} **excludes;
};
+/*
+ * The contents of the per-directory exclude files are lazily read on
+ * demand and then cached in memory, one per exclude_stack struct, in
+ * order to avoid opening and parsing each one every time that
+ * directory is traversed.
+ */
struct exclude_stack {
- struct exclude_stack *prev;
- char *filebuf;
+ struct exclude_stack *prev; /* the struct exclude_stack for the parent directory */
+ char *filebuf; /* remember pointer to per-directory exclude file contents so we can free() */
int baselen;
int exclude_ix;
};
@@ -59,6 +73,14 @@ struct dir_struct {
#define EXC_DIRS 1
#define EXC_FILE 2
+ /*
+ * Temporary variables which are used during loading of the
+ * per-directory exclude lists.
+ *
+ * exclude_stack points to the top of the exclude_stack, and
+ * basebuf contains the full path to the current
+ * (sub)directory in the traversal.
+ */
struct exclude_stack *exclude_stack;
char basebuf[PATH_MAX];
};
@@ -76,8 +98,8 @@ extern int within_depth(const char *name, int namelen, int depth, int max_depth)
extern int fill_directory(struct dir_struct *dir, const char **pathspec);
extern int read_directory(struct dir_struct *, const char *path, int len, const char **pathspec);
-extern int excluded_from_list(const char *pathname, int pathlen, const char *basename,
- int *dtype, struct exclude_list *el);
+extern int is_excluded_from_list(const char *pathname, int pathlen, const char *basename,
+ int *dtype, struct exclude_list *el);
struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len);
/*
@@ -91,26 +113,29 @@ extern int match_pathname(const char *, int,
const char *, int, int, int);
/*
- * The excluded() API is meant for callers that check each level of leading
- * directory hierarchies with excluded() to avoid recursing into excluded
+ * The is_excluded() API is meant for callers that check each level of leading
+ * directory hierarchies with is_excluded() to avoid recursing into excluded
* directories. Callers that do not do so should use this API instead.
*/
struct path_exclude_check {
struct dir_struct *dir;
+ struct exclude *exclude;
struct strbuf path;
};
extern void path_exclude_check_init(struct path_exclude_check *, struct dir_struct *);
extern void path_exclude_check_clear(struct path_exclude_check *);
-extern int path_excluded(struct path_exclude_check *, const char *, int namelen, int *dtype);
+extern struct exclude *last_exclude_matching_path(struct path_exclude_check *, const char *,
+ int namelen, int *dtype);
+extern int is_path_excluded(struct path_exclude_check *, const char *, int namelen, int *dtype);
extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
- char **buf_p, struct exclude_list *which, int check_index);
+ char **buf_p, struct exclude_list *el, int check_index);
extern void add_excludes_from_file(struct dir_struct *, const char *fname);
extern void parse_exclude_pattern(const char **string, int *patternlen, int *flags, int *nowildcardlen);
extern void add_exclude(const char *string, const char *base,
- int baselen, struct exclude_list *which);
-extern void free_excludes(struct exclude_list *el);
+ int baselen, struct exclude_list *el);
+extern void clear_exclude_list(struct exclude_list *el);
extern int file_exists(const char *);
extern int is_inside_dir(const char *dir);
@@ -139,4 +164,13 @@ extern int strcmp_icase(const char *a, const char *b);
extern int strncmp_icase(const char *a, const char *b, size_t count);
extern int fnmatch_icase(const char *pattern, const char *string, int flags);
+/*
+ * The prefix part of pattern must not contains wildcards.
+ */
+#define GFNM_PATHNAME 1 /* similar to FNM_PATHNAME */
+#define GFNM_ONESTAR 2 /* there is only _one_ wildcard, a star */
+
+extern int git_fnmatch(const char *pattern, const char *string,
+ int flags, int prefix);
+
#endif
diff --git a/fetch-pack.c b/fetch-pack.c
index 099ff4ddff..f0acdf7331 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -874,8 +874,6 @@ static int fetch_pack_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}
-static struct lock_file lock;
-
static void fetch_pack_setup(void)
{
static int did_setup;
@@ -917,6 +915,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
ref_cpy = do_fetch_pack(args, fd, ref, sought, pack_lockfile);
if (args->depth > 0) {
+ static struct lock_file lock;
struct cache_time mtime;
struct strbuf sb = STRBUF_INIT;
char *shallow = git_path("shallow");
diff --git a/fsck.c b/fsck.c
index 7395ef6a42..99c0497674 100644
--- a/fsck.c
+++ b/fsck.c
@@ -142,6 +142,9 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
int has_null_sha1 = 0;
int has_full_path = 0;
int has_empty_name = 0;
+ int has_dot = 0;
+ int has_dotdot = 0;
+ int has_dotgit = 0;
int has_zero_pad = 0;
int has_bad_modes = 0;
int has_dup_entries = 0;
@@ -168,6 +171,12 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
has_full_path = 1;
if (!*name)
has_empty_name = 1;
+ if (!strcmp(name, "."))
+ has_dot = 1;
+ if (!strcmp(name, ".."))
+ has_dotdot = 1;
+ if (!strcmp(name, ".git"))
+ has_dotgit = 1;
has_zero_pad |= *(char *)desc.buffer == '0';
update_tree_entry(&desc);
@@ -217,6 +226,12 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
retval += error_func(&item->object, FSCK_WARN, "contains full pathnames");
if (has_empty_name)
retval += error_func(&item->object, FSCK_WARN, "contains empty pathname");
+ if (has_dot)
+ retval += error_func(&item->object, FSCK_WARN, "contains '.'");
+ if (has_dotdot)
+ retval += error_func(&item->object, FSCK_WARN, "contains '..'");
+ if (has_dotgit)
+ retval += error_func(&item->object, FSCK_WARN, "contains '.git'");
if (has_zero_pad)
retval += error_func(&item->object, FSCK_WARN, "contains zero-padded file modes");
if (has_bad_modes)
diff --git a/git-compat-util.h b/git-compat-util.h
index 590d5d3188..e5a4b7450b 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -75,7 +75,7 @@
# endif
#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
!defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
- !defined(__TANDEM)
+ !defined(__TANDEM) && !defined(__QNX__)
#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
#endif
@@ -99,12 +99,14 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
-#ifdef __TANDEM /* or HAVE_STRINGS_H or !NO_STRINGS_H? */
+#ifdef HAVE_STRINGS_H
#include <strings.h> /* for strcasecmp() */
#endif
#include <errno.h>
#include <limits.h>
+#ifdef NEEDS_SYS_PARAM_H
#include <sys/param.h>
+#endif
#include <sys/types.h>
#include <dirent.h>
#include <sys/time.h>
@@ -288,6 +290,17 @@ extern NORETURN void die_errno(const char *err, ...) __attribute__((format (prin
extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
+/*
+ * Let callers be aware of the constant return value; this can help
+ * gcc with -Wuninitialized analysis. We have to restrict this trick to
+ * gcc, though, because of the variadic macro and the magic ## comma pasting
+ * behavior. But since we're only trying to help gcc, anyway, it's OK; other
+ * compilers will fall back to using the function as usual.
+ */
+#ifdef __GNUC__
+#define error(fmt, ...) (error((fmt), ##__VA_ARGS__), -1)
+#endif
+
extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
extern void set_error_routine(void (*routine)(const char *err, va_list params));
@@ -411,6 +424,10 @@ void *gitmemmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen);
#endif
+#ifdef NO_GETPAGESIZE
+#define getpagesize() sysconf(_SC_PAGESIZE)
+#endif
+
#ifdef FREAD_READS_DIRECTORIES
#ifdef fopen
#undef fopen
@@ -511,13 +528,19 @@ extern const char tolower_trans_tbl[256];
#undef isupper
#undef tolower
#undef toupper
-extern unsigned char sane_ctype[256];
+#undef iscntrl
+#undef ispunct
+#undef isxdigit
+
+extern const unsigned char sane_ctype[256];
#define GIT_SPACE 0x01
#define GIT_DIGIT 0x02
#define GIT_ALPHA 0x04
#define GIT_GLOB_SPECIAL 0x08
#define GIT_REGEX_SPECIAL 0x10
#define GIT_PATHSPEC_MAGIC 0x20
+#define GIT_CNTRL 0x40
+#define GIT_PUNCT 0x80
#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
#define isascii(x) (((x) & ~0x7f) == 0)
#define isspace(x) sane_istest(x,GIT_SPACE)
@@ -529,6 +552,10 @@ extern unsigned char sane_ctype[256];
#define isupper(x) sane_iscase(x, 0)
#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL)
#define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL)
+#define iscntrl(x) (sane_istest(x,GIT_CNTRL))
+#define ispunct(x) sane_istest(x, GIT_PUNCT | GIT_REGEX_SPECIAL | \
+ GIT_GLOB_SPECIAL | GIT_PATHSPEC_MAGIC)
+#define isxdigit(x) (hexval_table[x] != -1)
#define tolower(x) sane_case((unsigned char)(x), 0x20)
#define toupper(x) sane_case((unsigned char)(x), 0)
#define is_pathspec_magic(x) sane_istest(x,GIT_PATHSPEC_MAGIC)
diff --git a/git-p4.py b/git-p4.py
index 253ad06cc2..2da564995d 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -8,7 +8,13 @@
# License: MIT <http://www.opensource.org/licenses/mit-license.php>
#
-import optparse, sys, os, marshal, subprocess, shelve
+import sys
+if sys.hexversion < 0x02040000:
+ # The limiter is the subprocess module
+ sys.stderr.write("git-p4: requires Python 2.4 or later.\n")
+ sys.exit(1)
+
+import optparse, os, marshal, subprocess, shelve
import tempfile, getopt, os.path, time, platform
import re, shutil
diff --git a/git-rebase--am.sh b/git-rebase--am.sh
index 392ebc9790..97f31dc7af 100644
--- a/git-rebase--am.sh
+++ b/git-rebase--am.sh
@@ -18,6 +18,7 @@ esac
test -n "$rebase_root" && root_flag=--root
+ret=0
if test -n "$keep_empty"
then
# we have to do this the hard way. git format-patch completely squashes
@@ -25,13 +26,49 @@ then
# itself well to recording empty patches. fortunately, cherry-pick
# makes this easy
git cherry-pick --allow-empty "$revisions"
+ ret=$?
else
+ rm -f "$GIT_DIR/rebased-patches"
+
git format-patch -k --stdout --full-index --ignore-if-in-upstream \
--src-prefix=a/ --dst-prefix=b/ \
- --no-renames $root_flag "$revisions" |
- git am $git_am_opt --rebasing --resolvemsg="$resolvemsg"
-fi && move_to_original_branch
+ --no-renames $root_flag "$revisions" >"$GIT_DIR/rebased-patches"
+ ret=$?
+
+ if test 0 != $ret
+ then
+ rm -f "$GIT_DIR/rebased-patches"
+ case "$head_name" in
+ refs/heads/*)
+ git checkout -q "$head_name"
+ ;;
+ *)
+ git checkout -q "$orig_head"
+ ;;
+ esac
+
+ cat >&2 <<-EOF
+
+ git encountered an error while preparing the patches to replay
+ these revisions:
+
+ $revisions
+
+ As a result, git cannot rebase them.
+ EOF
+ exit $?
+ fi
+
+ git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" <"$GIT_DIR/rebased-patches"
+ ret=$?
+
+ rm -f "$GIT_DIR/rebased-patches"
+fi
+
+if test 0 != $ret
+then
+ test -d "$state_dir" && write_basic_state
+ exit $ret
+fi
-ret=$?
-test 0 != $ret -a -d "$state_dir" && write_basic_state
-exit $ret
+move_to_original_branch
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 44901d53c4..8ed7fccc18 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -190,6 +190,11 @@ is_empty_commit() {
test "$tree" = "$ptree"
}
+is_merge_commit()
+{
+ git rev-parse --verify --quiet "$1"^2 >/dev/null 2>&1
+}
+
# Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
# GIT_AUTHOR_DATE exported from the current environment.
do_with_author () {
@@ -874,7 +879,7 @@ git rev-list $merges_option --pretty=oneline --abbrev-commit \
while read -r shortsha1 rest
do
- if test -z "$keep_empty" && is_empty_commit $shortsha1
+ if test -z "$keep_empty" && is_empty_commit $shortsha1 && ! is_merge_commit $shortsha1
then
comment_out="# "
else
diff --git a/git-remote-testgit b/git-remote-testgit
new file mode 100755
index 0000000000..b395c8de59
--- /dev/null
+++ b/git-remote-testgit
@@ -0,0 +1,90 @@
+#!/usr/bin/env bash
+# Copyright (c) 2012 Felipe Contreras
+
+alias=$1
+url=$2
+
+dir="$GIT_DIR/testgit/$alias"
+prefix="refs/testgit/$alias"
+
+default_refspec="refs/heads/*:${prefix}/heads/*"
+
+refspec="${GIT_REMOTE_TESTGIT_REFSPEC-$default_refspec}"
+
+test -z "$refspec" && prefix="refs"
+
+export GIT_DIR="$url/.git"
+
+mkdir -p "$dir"
+
+if test -z "$GIT_REMOTE_TESTGIT_NO_MARKS"
+then
+ gitmarks="$dir/git.marks"
+ testgitmarks="$dir/testgit.marks"
+ test -e "$gitmarks" || >"$gitmarks"
+ test -e "$testgitmarks" || >"$testgitmarks"
+ testgitmarks_args=( "--"{import,export}"-marks=$testgitmarks" )
+fi
+
+while read line
+do
+ case $line in
+ capabilities)
+ echo 'import'
+ echo 'export'
+ test -n "$refspec" && echo "refspec $refspec"
+ if test -n "$gitmarks"
+ then
+ echo "*import-marks $gitmarks"
+ echo "*export-marks $gitmarks"
+ fi
+ echo
+ ;;
+ list)
+ git for-each-ref --format='? %(refname)' 'refs/heads/'
+ head=$(git symbolic-ref HEAD)
+ echo "@$head HEAD"
+ echo
+ ;;
+ import*)
+ # read all import lines
+ while true
+ do
+ ref="${line#* }"
+ refs="$refs $ref"
+ read line
+ test "${line%% *}" != "import" && break
+ done
+
+ if test -n "$gitmarks"
+ then
+ echo "feature import-marks=$gitmarks"
+ echo "feature export-marks=$gitmarks"
+ fi
+ echo "feature done"
+ git fast-export "${testgitmarks_args[@]}" $refs |
+ sed -e "s#refs/heads/#${prefix}/heads/#g"
+ echo "done"
+ ;;
+ export)
+ before=$(git for-each-ref --format='%(refname) %(objectname)')
+
+ git fast-import "${testgitmarks_args[@]}" --quiet
+
+ after=$(git for-each-ref --format='%(refname) %(objectname)')
+
+ # figure out which refs were updated
+ join -e 0 -o '0 1.2 2.2' -a 2 <(echo "$before") <(echo "$after") |
+ while read ref a b
+ do
+ test $a == $b && continue
+ echo "ok $ref"
+ done
+
+ echo
+ ;;
+ '')
+ exit
+ ;;
+ esac
+done
diff --git a/git-remote-testgit.py b/git-remote-testpy.py
index 5f3ebd244d..d94a66a870 100644
--- a/git-remote-testgit.py
+++ b/git-remote-testpy.py
@@ -31,6 +31,11 @@ from git_remote_helpers.git.exporter import GitExporter
from git_remote_helpers.git.importer import GitImporter
from git_remote_helpers.git.non_local import NonLocalGit
+if sys.hexversion < 0x01050200:
+ # os.makedirs() is the limiter
+ sys.stderr.write("git-remote-testgit: requires Python 1.5.2 or later.\n")
+ sys.exit(1)
+
def get_repo(alias, url):
"""Returns a git repository object initialized for usage.
"""
@@ -91,7 +96,7 @@ def do_capabilities(repo, args):
if not os.path.exists(dirname):
os.makedirs(dirname)
- path = os.path.join(dirname, 'testgit.marks')
+ path = os.path.join(dirname, 'git.marks')
print "*export-marks %s" % path
if os.path.exists(path):
@@ -159,6 +164,11 @@ def do_import(repo, args):
ref = line[7:].strip()
refs.append(ref)
+ print "feature done"
+
+ if os.environ.get("GIT_REMOTE_TESTGIT_FAILURE"):
+ die('Told to fail')
+
repo = update_local_repo(repo)
repo.exporter.export_repo(repo.gitdir, refs)
@@ -172,6 +182,9 @@ def do_export(repo, args):
if not repo.gitdir:
die("Need gitdir to export")
+ if os.environ.get("GIT_REMOTE_TESTGIT_FAILURE"):
+ die('Told to fail')
+
update_local_repo(repo)
changed = repo.importer.do_import(repo.gitdir)
diff --git a/git-send-email.perl b/git-send-email.perl
index 94c7f76a15..be809e5b59 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1285,10 +1285,10 @@ foreach my $t (@files) {
}
if (defined $input_format && $input_format eq 'mbox') {
- if (/^Subject:\s+(.*)$/) {
+ if (/^Subject:\s+(.*)$/i) {
$subject = $1;
}
- elsif (/^From:\s+(.*)$/) {
+ elsif (/^From:\s+(.*)$/i) {
($author, $author_encoding) = unquote_rfc2047($1);
next if $suppress_cc{'author'};
next if $suppress_cc{'self'} and $author eq $sender;
@@ -1296,14 +1296,14 @@ foreach my $t (@files) {
$1, $_) unless $quiet;
push @cc, $1;
}
- elsif (/^To:\s+(.*)$/) {
+ elsif (/^To:\s+(.*)$/i) {
foreach my $addr (parse_address_line($1)) {
printf("(mbox) Adding to: %s from line '%s'\n",
$addr, $_) unless $quiet;
push @to, $addr;
}
}
- elsif (/^Cc:\s+(.*)$/) {
+ elsif (/^Cc:\s+(.*)$/i) {
foreach my $addr (parse_address_line($1)) {
if (unquote_rfc2047($addr) eq $sender) {
next if ($suppress_cc{'self'});
@@ -1325,7 +1325,7 @@ foreach my $t (@files) {
elsif (/^Message-Id: (.*)/i) {
$message_id = $1;
}
- elsif (!/^Date:\s/ && /^[-A-Za-z]+:\s+\S/) {
+ elsif (!/^Date:\s/i && /^[-A-Za-z]+:\s+\S/) {
push @xh, $_;
}
diff --git a/git-submodule.sh b/git-submodule.sh
index 2365149d0b..22ec5b63b4 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -8,7 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
or: $dashless [--quiet] init [--] [<path>...]
- or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+ or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: $dashless [--quiet] foreach [--recursive] <command>
or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
@@ -26,6 +26,7 @@ cached=
recursive=
init=
files=
+remote=
nofetch=
update=
prefix=
@@ -153,6 +154,32 @@ die_if_unmatched ()
}
#
+# Print a submodule configuration setting
+#
+# $1 = submodule name
+# $2 = option name
+# $3 = default value
+#
+# Checks in the usual git-config places first (for overrides),
+# otherwise it falls back on .gitmodules. This allows you to
+# distribute project-wide defaults in .gitmodules, while still
+# customizing individual repositories if necessary. If the option is
+# not in .gitmodules either, print a default value.
+#
+get_submodule_config () {
+ name="$1"
+ option="$2"
+ default="$3"
+ value=$(git config submodule."$name"."$option")
+ if test -z "$value"
+ then
+ value=$(git config -f .gitmodules submodule."$name"."$option")
+ fi
+ printf '%s' "${value:-$default}"
+}
+
+
+#
# Map submodule path to submodule name
#
# $1 = path
@@ -390,6 +417,10 @@ Use -f if you really want to add it." >&2
git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
git config -f .gitmodules submodule."$sm_name".url "$repo" &&
+ if test -n "$branch"
+ then
+ git config -f .gitmodules submodule."$sm_name".branch "$branch"
+ fi &&
git add --force .gitmodules ||
die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
}
@@ -533,6 +564,9 @@ cmd_update()
-i|--init)
init=1
;;
+ --remote)
+ remote=1
+ ;;
-N|--no-fetch)
nofetch=1
;;
@@ -593,6 +627,7 @@ cmd_update()
fi
name=$(module_name "$sm_path") || exit
url=$(git config submodule."$name".url)
+ branch=$(get_submodule_config "$name" branch master)
if ! test -z "$update"
then
update_module=$update
@@ -627,6 +662,20 @@ Maybe you want to use 'update --init'?")"
die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")"
fi
+ if test -n "$remote"
+ then
+ if test -z "$nofetch"
+ then
+ # Fetch remote before determining tracking $sha1
+ (clear_local_git_env; cd "$sm_path" && git-fetch) ||
+ die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
+ fi
+ remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote)
+ sha1=$(clear_local_git_env; cd "$sm_path" &&
+ git rev-parse --verify "${remote_name}/${branch}") ||
+ die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
+ fi
+
if test "$subsha1" != "$sha1" -o -n "$force"
then
subforce=$force
diff --git a/git-svn.perl b/git-svn.perl
index bd5266c86b..d0866946ce 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -114,6 +114,7 @@ my ($_stdin, $_help, $_edit,
$_message, $_file, $_branch_dest,
$_template, $_shared,
$_version, $_fetch_all, $_no_rebase, $_fetch_parent,
+ $_before, $_after,
$_merge, $_strategy, $_preserve_merges, $_dry_run, $_local,
$_prefix, $_no_checkout, $_url, $_verbose,
$_commit_url, $_tag, $_merge_info, $_interactive);
@@ -258,7 +259,8 @@ my %cmd = (
} ],
'find-rev' => [ \&cmd_find_rev,
"Translate between SVN revision numbers and tree-ish",
- {} ],
+ { 'before' => \$_before,
+ 'after' => \$_after } ],
'rebase' => [ \&cmd_rebase, "Fetch and rebase your working directory",
{ 'merge|m|M' => \$_merge,
'verbose|v' => \$_verbose,
@@ -1191,7 +1193,13 @@ sub cmd_find_rev {
"$head history\n";
}
my $desired_revision = substr($revision_or_hash, 1);
- $result = $gs->rev_map_get($desired_revision, $uuid);
+ if ($_before) {
+ $result = $gs->find_rev_before($desired_revision, 1);
+ } elsif ($_after) {
+ $result = $gs->find_rev_after($desired_revision, 1);
+ } else {
+ $result = $gs->rev_map_get($desired_revision, $uuid);
+ }
} else {
my (undef, $rev, undef) = cmt_metadata($revision_or_hash);
$result = $rev;
diff --git a/git.c b/git.c
index d33f9b32a2..ed66c660d1 100644
--- a/git.c
+++ b/git.c
@@ -135,6 +135,14 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
git_config_push_parameter((*argv)[1]);
(*argv)++;
(*argc)--;
+ } else if (!strcmp(cmd, "--literal-pathspecs")) {
+ setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "1", 1);
+ if (envchanged)
+ *envchanged = 1;
+ } else if (!strcmp(cmd, "--no-literal-pathspecs")) {
+ setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "0", 1);
+ if (envchanged)
+ *envchanged = 1;
} else {
fprintf(stderr, "Unknown option: %s\n", cmd);
usage(git_usage_string);
diff --git a/git_remote_helpers/git/__init__.py b/git_remote_helpers/git/__init__.py
index e69de29bb2..1dbb1b0148 100644
--- a/git_remote_helpers/git/__init__.py
+++ b/git_remote_helpers/git/__init__.py
@@ -0,0 +1,5 @@
+import sys
+if sys.hexversion < 0x02040000:
+ # The limiter is the subprocess module
+ sys.stderr.write("git_remote_helpers: requires Python 2.4 or later.\n")
+ sys.exit(1)
diff --git a/git_remote_helpers/git/importer.py b/git_remote_helpers/git/importer.py
index 5c6b595e16..e28cc8f986 100644
--- a/git_remote_helpers/git/importer.py
+++ b/git_remote_helpers/git/importer.py
@@ -39,7 +39,7 @@ class GitImporter(object):
gitdir = self.repo.gitpath
else:
gitdir = os.path.abspath(os.path.join(dirname, '.git'))
- path = os.path.abspath(os.path.join(dirname, 'git.marks'))
+ path = os.path.abspath(os.path.join(dirname, 'testgit.marks'))
if not os.path.exists(dirname):
os.makedirs(dirname)
diff --git a/http-push.c b/http-push.c
index 8701c1215d..9923441a4e 100644
--- a/http-push.c
+++ b/http-push.c
@@ -172,28 +172,7 @@ enum dav_header_flag {
static char *xml_entities(const char *s)
{
struct strbuf buf = STRBUF_INIT;
- while (*s) {
- size_t len = strcspn(s, "\"<>&");
- strbuf_add(&buf, s, len);
- s += len;
- switch (*s) {
- case '"':
- strbuf_addstr(&buf, "&quot;");
- break;
- case '<':
- strbuf_addstr(&buf, "&lt;");
- break;
- case '>':
- strbuf_addstr(&buf, "&gt;");
- break;
- case '&':
- strbuf_addstr(&buf, "&amp;");
- break;
- case 0:
- return strbuf_detach(&buf, NULL);
- }
- s++;
- }
+ strbuf_addstr_xml_quoted(&buf, s);
return strbuf_detach(&buf, NULL);
}
diff --git a/imap-send.c b/imap-send.c
index d42e471297..e521e2fd22 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -69,8 +69,7 @@ struct store {
};
struct msg_data {
- char *data;
- int len;
+ struct strbuf data;
unsigned char flags;
};
@@ -1264,45 +1263,49 @@ static int imap_make_flags(int flags, char *buf)
return d;
}
-static void lf_to_crlf(struct msg_data *msg)
+static void lf_to_crlf(struct strbuf *msg)
{
+ size_t new_len;
char *new;
int i, j, lfnum = 0;
- if (msg->data[0] == '\n')
+ if (msg->buf[0] == '\n')
lfnum++;
for (i = 1; i < msg->len; i++) {
- if (msg->data[i - 1] != '\r' && msg->data[i] == '\n')
+ if (msg->buf[i - 1] != '\r' && msg->buf[i] == '\n')
lfnum++;
}
- new = xmalloc(msg->len + lfnum);
- if (msg->data[0] == '\n') {
+ new_len = msg->len + lfnum;
+ new = xmalloc(new_len + 1);
+ if (msg->buf[0] == '\n') {
new[0] = '\r';
new[1] = '\n';
i = 1;
j = 2;
} else {
- new[0] = msg->data[0];
+ new[0] = msg->buf[0];
i = 1;
j = 1;
}
for ( ; i < msg->len; i++) {
- if (msg->data[i] != '\n') {
- new[j++] = msg->data[i];
+ if (msg->buf[i] != '\n') {
+ new[j++] = msg->buf[i];
continue;
}
- if (msg->data[i - 1] != '\r')
+ if (msg->buf[i - 1] != '\r')
new[j++] = '\r';
/* otherwise it already had CR before */
new[j++] = '\n';
}
- msg->len += lfnum;
- free(msg->data);
- msg->data = new;
+ strbuf_attach(msg, new, new_len, new_len + 1);
}
-static int imap_store_msg(struct store *gctx, struct msg_data *data)
+/*
+ * Store msg to IMAP. Also detach and free the data from msg->data,
+ * leaving msg->data empty.
+ */
+static int imap_store_msg(struct store *gctx, struct msg_data *msg)
{
struct imap_store *ctx = (struct imap_store *)gctx;
struct imap *imap = ctx->imap;
@@ -1311,16 +1314,15 @@ static int imap_store_msg(struct store *gctx, struct msg_data *data)
int ret, d;
char flagstr[128];
- lf_to_crlf(data);
+ lf_to_crlf(&msg->data);
memset(&cb, 0, sizeof(cb));
- cb.dlen = data->len;
- cb.data = xmalloc(cb.dlen);
- memcpy(cb.data, data->data, data->len);
+ cb.dlen = msg->data.len;
+ cb.data = strbuf_detach(&msg->data, NULL);
d = 0;
- if (data->flags) {
- d = imap_make_flags(data->flags, flagstr);
+ if (msg->flags) {
+ d = imap_make_flags(msg->flags, flagstr);
flagstr[d++] = ' ';
}
flagstr[d] = 0;
@@ -1337,75 +1339,46 @@ static int imap_store_msg(struct store *gctx, struct msg_data *data)
return DRV_OK;
}
-static void encode_html_chars(struct strbuf *p)
-{
- int i;
- for (i = 0; i < p->len; i++) {
- if (p->buf[i] == '&')
- strbuf_splice(p, i, 1, "&amp;", 5);
- if (p->buf[i] == '<')
- strbuf_splice(p, i, 1, "&lt;", 4);
- if (p->buf[i] == '>')
- strbuf_splice(p, i, 1, "&gt;", 4);
- if (p->buf[i] == '"')
- strbuf_splice(p, i, 1, "&quot;", 6);
- }
-}
-static void wrap_in_html(struct msg_data *msg)
+static void wrap_in_html(struct strbuf *msg)
{
struct strbuf buf = STRBUF_INIT;
- struct strbuf **lines;
- struct strbuf **p;
static char *content_type = "Content-Type: text/html;\n";
static char *pre_open = "<pre>\n";
static char *pre_close = "</pre>\n";
- int added_header = 0;
-
- strbuf_attach(&buf, msg->data, msg->len, msg->len);
- lines = strbuf_split(&buf, '\n');
- strbuf_release(&buf);
- for (p = lines; *p; p++) {
- if (! added_header) {
- if ((*p)->len == 1 && *((*p)->buf) == '\n') {
- strbuf_addstr(&buf, content_type);
- strbuf_addbuf(&buf, *p);
- strbuf_addstr(&buf, pre_open);
- added_header = 1;
- continue;
- }
- }
- else
- encode_html_chars(*p);
- strbuf_addbuf(&buf, *p);
- }
+ const char *body = strstr(msg->buf, "\n\n");
+
+ if (!body)
+ return; /* Headers but no body; no wrapping needed */
+
+ body += 2;
+
+ strbuf_add(&buf, msg->buf, body - msg->buf - 1);
+ strbuf_addstr(&buf, content_type);
+ strbuf_addch(&buf, '\n');
+ strbuf_addstr(&buf, pre_open);
+ strbuf_addstr_xml_quoted(&buf, body);
strbuf_addstr(&buf, pre_close);
- strbuf_list_free(lines);
- msg->len = buf.len;
- msg->data = strbuf_detach(&buf, NULL);
+
+ strbuf_release(msg);
+ *msg = buf;
}
#define CHUNKSIZE 0x1000
-static int read_message(FILE *f, struct msg_data *msg)
+static int read_message(FILE *f, struct strbuf *all_msgs)
{
- struct strbuf buf = STRBUF_INIT;
-
- memset(msg, 0, sizeof(*msg));
-
do {
- if (strbuf_fread(&buf, CHUNKSIZE, f) <= 0)
+ if (strbuf_fread(all_msgs, CHUNKSIZE, f) <= 0)
break;
} while (!feof(f));
- msg->len = buf.len;
- msg->data = strbuf_detach(&buf, NULL);
- return msg->len;
+ return ferror(f) ? -1 : 0;
}
-static int count_messages(struct msg_data *msg)
+static int count_messages(struct strbuf *all_msgs)
{
int count = 0;
- char *p = msg->data;
+ char *p = all_msgs->buf;
while (1) {
if (!prefixcmp(p, "From ")) {
@@ -1426,34 +1399,39 @@ static int count_messages(struct msg_data *msg)
return count;
}
-static int split_msg(struct msg_data *all_msgs, struct msg_data *msg, int *ofs)
+/*
+ * Copy the next message from all_msgs, starting at offset *ofs, to
+ * msg. Update *ofs to the start of the following message. Return
+ * true iff a message was successfully copied.
+ */
+static int split_msg(struct strbuf *all_msgs, struct strbuf *msg, int *ofs)
{
char *p, *data;
+ size_t len;
- memset(msg, 0, sizeof *msg);
if (*ofs >= all_msgs->len)
return 0;
- data = &all_msgs->data[*ofs];
- msg->len = all_msgs->len - *ofs;
+ data = &all_msgs->buf[*ofs];
+ len = all_msgs->len - *ofs;
- if (msg->len < 5 || prefixcmp(data, "From "))
+ if (len < 5 || prefixcmp(data, "From "))
return 0;
p = strchr(data, '\n');
if (p) {
- p = &p[1];
- msg->len -= p-data;
- *ofs += p-data;
+ p++;
+ len -= p - data;
+ *ofs += p - data;
data = p;
}
p = strstr(data, "\nFrom ");
if (p)
- msg->len = &p[1] - data;
+ len = &p[1] - data;
- msg->data = xmemdupz(data, msg->len);
- *ofs += msg->len;
+ strbuf_add(msg, data, len);
+ *ofs += len;
return 1;
}
@@ -1504,7 +1482,8 @@ static int git_imap_config(const char *key, const char *val, void *cb)
int main(int argc, char **argv)
{
- struct msg_data all_msgs, msg;
+ struct strbuf all_msgs = STRBUF_INIT;
+ struct msg_data msg = {STRBUF_INIT, 0};
struct store *ctx = NULL;
int ofs = 0;
int r;
@@ -1537,7 +1516,12 @@ int main(int argc, char **argv)
}
/* read the messages */
- if (!read_message(stdin, &all_msgs)) {
+ if (read_message(stdin, &all_msgs)) {
+ fprintf(stderr, "error reading input\n");
+ return 1;
+ }
+
+ if (all_msgs.len == 0) {
fprintf(stderr, "nothing to send\n");
return 1;
}
@@ -1559,11 +1543,12 @@ int main(int argc, char **argv)
ctx->name = imap_folder;
while (1) {
unsigned percent = n * 100 / total;
+
fprintf(stderr, "%4u%% (%d/%d) done\r", percent, n, total);
- if (!split_msg(&all_msgs, &msg, &ofs))
+ if (!split_msg(&all_msgs, &msg.data, &ofs))
break;
if (server.use_html)
- wrap_in_html(&msg);
+ wrap_in_html(&msg.data);
r = imap_store_msg(ctx, &msg);
if (r != DRV_OK)
break;
diff --git a/log-tree.c b/log-tree.c
index 4f86defe32..5dc45c4812 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -299,26 +299,34 @@ static unsigned int digits_in_number(unsigned int number)
return result;
}
-void get_patch_filename(struct commit *commit, const char *subject, int nr,
- const char *suffix, struct strbuf *buf)
+void fmt_output_subject(struct strbuf *filename,
+ const char *subject,
+ struct rev_info *info)
{
- int suffix_len = strlen(suffix) + 1;
- int start_len = buf->len;
-
- strbuf_addf(buf, commit || subject ? "%04d-" : "%d", nr);
- if (commit || subject) {
- int max_len = start_len + FORMAT_PATCH_NAME_MAX - suffix_len;
- struct pretty_print_context ctx = {0};
-
- if (subject)
- strbuf_addstr(buf, subject);
- else if (commit)
- format_commit_message(commit, "%f", buf, &ctx);
-
- if (max_len < buf->len)
- strbuf_setlen(buf, max_len);
- strbuf_addstr(buf, suffix);
- }
+ const char *suffix = info->patch_suffix;
+ int nr = info->nr;
+ int start_len = filename->len;
+ int max_len = start_len + FORMAT_PATCH_NAME_MAX - (strlen(suffix) + 1);
+
+ if (0 < info->reroll_count)
+ strbuf_addf(filename, "v%d-", info->reroll_count);
+ strbuf_addf(filename, "%04d-%s", nr, subject);
+
+ if (max_len < filename->len)
+ strbuf_setlen(filename, max_len);
+ strbuf_addstr(filename, suffix);
+}
+
+void fmt_output_commit(struct strbuf *filename,
+ struct commit *commit,
+ struct rev_info *info)
+{
+ struct pretty_print_context ctx = {0};
+ struct strbuf subject = STRBUF_INIT;
+
+ format_commit_message(commit, "%f", &subject, &ctx);
+ fmt_output_subject(filename, subject.buf, info);
+ strbuf_release(&subject);
}
void log_write_email_headers(struct rev_info *opt, struct commit *commit,
@@ -387,8 +395,10 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
mime_boundary_leader, opt->mime_boundary);
extra_headers = subject_buffer;
- get_patch_filename(opt->numbered_files ? NULL : commit, NULL,
- opt->nr, opt->patch_suffix, &filename);
+ if (opt->numbered_files)
+ strbuf_addf(&filename, "%d", opt->nr);
+ else
+ fmt_output_commit(&filename, commit, opt);
snprintf(buffer, sizeof(buffer) - 1,
"\n--%s%s\n"
"Content-Type: text/x-patch;"
@@ -671,6 +681,8 @@ void show_log(struct rev_info *opt)
ctx.preserve_subject = opt->preserve_subject;
ctx.reflog_info = opt->reflog_info;
ctx.fmt = opt->commit_format;
+ ctx.mailmap = opt->mailmap;
+ ctx.color = opt->diffopt.use_color;
pretty_print_commit(&ctx, commit, &msgbuf);
if (opt->add_signoff)
diff --git a/log-tree.h b/log-tree.h
index f5ac238bba..9140f48216 100644
--- a/log-tree.h
+++ b/log-tree.h
@@ -21,7 +21,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
void load_ref_decorations(int flags);
#define FORMAT_PATCH_NAME_MAX 64
-void get_patch_filename(struct commit *commit, const char *subject, int nr,
- const char *suffix, struct strbuf *buf);
+void fmt_output_commit(struct strbuf *, struct commit *, struct rev_info *);
+void fmt_output_subject(struct strbuf *, const char *subject, struct rev_info *);
#endif
diff --git a/mailmap.c b/mailmap.c
index ea4b471ede..2a7b36628c 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -10,6 +10,7 @@ static inline void debug_mm(const char *format, ...) {}
#endif
const char *git_mailmap_file;
+const char *git_mailmap_blob;
struct mailmap_info {
char *name;
@@ -129,54 +130,120 @@ static char *parse_name_and_email(char *buffer, char **name,
return (*right == '\0' ? NULL : right);
}
-static int read_single_mailmap(struct string_list *map, const char *filename, char **repo_abbrev)
+static void read_mailmap_line(struct string_list *map, char *buffer,
+ char **repo_abbrev)
+{
+ char *name1 = NULL, *email1 = NULL, *name2 = NULL, *email2 = NULL;
+ if (buffer[0] == '#') {
+ static const char abbrev[] = "# repo-abbrev:";
+ int abblen = sizeof(abbrev) - 1;
+ int len = strlen(buffer);
+
+ if (!repo_abbrev)
+ return;
+
+ if (len && buffer[len - 1] == '\n')
+ buffer[--len] = 0;
+ if (!strncmp(buffer, abbrev, abblen)) {
+ char *cp;
+
+ if (repo_abbrev)
+ free(*repo_abbrev);
+ *repo_abbrev = xmalloc(len);
+
+ for (cp = buffer + abblen; isspace(*cp); cp++)
+ ; /* nothing */
+ strcpy(*repo_abbrev, cp);
+ }
+ return;
+ }
+ if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL)
+ parse_name_and_email(name2, &name2, &email2, 1);
+
+ if (email1)
+ add_mapping(map, name1, email1, name2, email2);
+}
+
+static int read_mailmap_file(struct string_list *map, const char *filename,
+ char **repo_abbrev)
{
char buffer[1024];
- FILE *f = (filename == NULL ? NULL : fopen(filename, "r"));
+ FILE *f;
- if (f == NULL)
- return 1;
- while (fgets(buffer, sizeof(buffer), f) != NULL) {
- char *name1 = NULL, *email1 = NULL, *name2 = NULL, *email2 = NULL;
- if (buffer[0] == '#') {
- static const char abbrev[] = "# repo-abbrev:";
- int abblen = sizeof(abbrev) - 1;
- int len = strlen(buffer);
-
- if (!repo_abbrev)
- continue;
-
- if (len && buffer[len - 1] == '\n')
- buffer[--len] = 0;
- if (!strncmp(buffer, abbrev, abblen)) {
- char *cp;
-
- if (repo_abbrev)
- free(*repo_abbrev);
- *repo_abbrev = xmalloc(len);
-
- for (cp = buffer + abblen; isspace(*cp); cp++)
- ; /* nothing */
- strcpy(*repo_abbrev, cp);
- }
- continue;
- }
- if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL)
- parse_name_and_email(name2, &name2, &email2, 1);
+ if (!filename)
+ return 0;
- if (email1)
- add_mapping(map, name1, email1, name2, email2);
+ f = fopen(filename, "r");
+ if (!f) {
+ if (errno == ENOENT)
+ return 0;
+ return error("unable to open mailmap at %s: %s",
+ filename, strerror(errno));
}
+
+ while (fgets(buffer, sizeof(buffer), f) != NULL)
+ read_mailmap_line(map, buffer, repo_abbrev);
fclose(f);
return 0;
}
+static void read_mailmap_buf(struct string_list *map,
+ const char *buf, unsigned long len,
+ char **repo_abbrev)
+{
+ while (len) {
+ const char *end = strchrnul(buf, '\n');
+ unsigned long linelen = end - buf + 1;
+ char *line = xmemdupz(buf, linelen);
+
+ read_mailmap_line(map, line, repo_abbrev);
+
+ free(line);
+ buf += linelen;
+ len -= linelen;
+ }
+}
+
+static int read_mailmap_blob(struct string_list *map,
+ const char *name,
+ char **repo_abbrev)
+{
+ unsigned char sha1[20];
+ char *buf;
+ unsigned long size;
+ enum object_type type;
+
+ if (!name)
+ return 0;
+ if (get_sha1(name, sha1) < 0)
+ return 0;
+
+ buf = read_sha1_file(sha1, &type, &size);
+ if (!buf)
+ return error("unable to read mailmap object at %s", name);
+ if (type != OBJ_BLOB)
+ return error("mailmap is not a blob: %s", name);
+
+ read_mailmap_buf(map, buf, size, repo_abbrev);
+
+ free(buf);
+ return 0;
+}
+
int read_mailmap(struct string_list *map, char **repo_abbrev)
{
+ int err = 0;
+
map->strdup_strings = 1;
- /* each failure returns 1, so >1 means both calls failed */
- return read_single_mailmap(map, ".mailmap", repo_abbrev) +
- read_single_mailmap(map, git_mailmap_file, repo_abbrev) > 1;
+ map->cmp = strcasecmp;
+
+ if (!git_mailmap_blob && is_bare_repository())
+ git_mailmap_blob = "HEAD:.mailmap";
+
+ err |= read_mailmap_file(map, ".mailmap", repo_abbrev);
+ err |= read_mailmap_blob(map, git_mailmap_blob, repo_abbrev);
+ err |= read_mailmap_file(map, git_mailmap_file, repo_abbrev);
+ return err;
}
void clear_mailmap(struct string_list *map)
@@ -187,60 +254,95 @@ void clear_mailmap(struct string_list *map)
debug_mm("mailmap: cleared\n");
}
+/*
+ * Look for an entry in map that match string[0:len]; string[len]
+ * does not have to be NUL (but it could be).
+ */
+static struct string_list_item *lookup_prefix(struct string_list *map,
+ const char *string, size_t len)
+{
+ int i = string_list_find_insert_index(map, string, 1);
+ if (i < 0) {
+ /* exact match */
+ i = -1 - i;
+ if (!string[len])
+ return &map->items[i];
+ /*
+ * that map entry matches exactly to the string, including
+ * the cruft at the end beyond "len". That is not a match
+ * with string[0:len] that we are looking for.
+ */
+ } else if (!string[len]) {
+ /*
+ * asked with the whole string, and got nothing. No
+ * matching entry can exist in the map.
+ */
+ return NULL;
+ }
+
+ /*
+ * i is at the exact match to an overlong key, or location the
+ * overlong key would be inserted, which must come after the
+ * real location of the key if one exists.
+ */
+ while (0 <= --i && i < map->nr) {
+ int cmp = strncasecmp(map->items[i].string, string, len);
+ if (cmp < 0)
+ /*
+ * "i" points at a key definitely below the prefix;
+ * the map does not have string[0:len] in it.
+ */
+ break;
+ else if (!cmp && !map->items[i].string[len])
+ /* found it */
+ return &map->items[i];
+ /*
+ * otherwise, the string at "i" may be string[0:len]
+ * followed by a string that sorts later than string[len:];
+ * keep trying.
+ */
+ }
+ return NULL;
+}
+
int map_user(struct string_list *map,
- char *email, int maxlen_email, char *name, int maxlen_name)
+ const char **email, size_t *emaillen,
+ const char **name, size_t *namelen)
{
- char *end_of_email;
struct string_list_item *item;
struct mailmap_entry *me;
- char buf[1024], *mailbuf;
- int i;
-
- /* figure out space requirement for email */
- end_of_email = strchr(email, '>');
- if (!end_of_email) {
- /* email passed in might not be wrapped in <>, but end with a \0 */
- end_of_email = memchr(email, '\0', maxlen_email);
- if (!end_of_email)
- return 0;
- }
- if (end_of_email - email + 1 < sizeof(buf))
- mailbuf = buf;
- else
- mailbuf = xmalloc(end_of_email - email + 1);
-
- /* downcase the email address */
- for (i = 0; i < end_of_email - email; i++)
- mailbuf[i] = tolower(email[i]);
- mailbuf[i] = 0;
-
- debug_mm("map_user: map '%s' <%s>\n", name, mailbuf);
- item = string_list_lookup(map, mailbuf);
+
+ debug_mm("map_user: map '%.*s' <%.*s>\n",
+ *name, *namelen, *emaillen, *email);
+
+ item = lookup_prefix(map, *email, *emaillen);
if (item != NULL) {
me = (struct mailmap_entry *)item->util;
if (me->namemap.nr) {
/* The item has multiple items, so we'll look up on name too */
/* If the name is not found, we choose the simple entry */
- struct string_list_item *subitem = string_list_lookup(&me->namemap, name);
+ struct string_list_item *subitem;
+ subitem = lookup_prefix(&me->namemap, *name, *namelen);
if (subitem)
item = subitem;
}
}
- if (mailbuf != buf)
- free(mailbuf);
if (item != NULL) {
struct mailmap_info *mi = (struct mailmap_info *)item->util;
- if (mi->name == NULL && (mi->email == NULL || maxlen_email == 0)) {
+ if (mi->name == NULL && mi->email == NULL) {
debug_mm("map_user: -- (no simple mapping)\n");
return 0;
}
- if (maxlen_email && mi->email)
- strlcpy(email, mi->email, maxlen_email);
- else
- *end_of_email = '\0';
- if (maxlen_name && mi->name)
- strlcpy(name, mi->name, maxlen_name);
- debug_mm("map_user: to '%s' <%s>\n", name, mi->email ? mi->email : "");
+ if (mi->email) {
+ *email = mi->email;
+ *emaillen = strlen(*email);
+ }
+ if (mi->name) {
+ *name = mi->name;
+ *namelen = strlen(*name);
+ }
+ debug_mm("map_user: to '%.*s' <.*%s>\n", *namelen, *name,
+ *emaillen, *email);
return 1;
}
debug_mm("map_user: --\n");
diff --git a/mailmap.h b/mailmap.h
index d5c3664322..ed7c93b05c 100644
--- a/mailmap.h
+++ b/mailmap.h
@@ -4,7 +4,7 @@
int read_mailmap(struct string_list *map, char **repo_abbrev);
void clear_mailmap(struct string_list *map);
-int map_user(struct string_list *mailmap,
- char *email, int maxlen_email, char *name, int maxlen_name);
+int map_user(struct string_list *map,
+ const char **email, size_t *emaillen, const char **name, size_t *namelen);
#endif
diff --git a/merge-file.c b/merge-blobs.c
index 7845528e88..57211bccb7 100644
--- a/merge-file.c
+++ b/merge-blobs.c
@@ -3,7 +3,7 @@
#include "xdiff-interface.h"
#include "ll-merge.h"
#include "blob.h"
-#include "merge-file.h"
+#include "merge-blobs.h"
static int fill_mmfile_blob(mmfile_t *f, struct blob *obj)
{
@@ -80,7 +80,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2)
return xdi_diff(f1, f2, &xpp, &xecfg, &ecb);
}
-void *merge_file(const char *path, struct blob *base, struct blob *our, struct blob *their, unsigned long *size)
+void *merge_blobs(const char *path, struct blob *base, struct blob *our, struct blob *their, unsigned long *size)
{
void *res = NULL;
mmfile_t f1, f2, common;
diff --git a/merge-blobs.h b/merge-blobs.h
new file mode 100644
index 0000000000..62b569e472
--- /dev/null
+++ b/merge-blobs.h
@@ -0,0 +1,8 @@
+#ifndef MERGE_BLOBS_H
+#define MERGE_BLOBS_H
+
+#include "blob.h"
+
+extern void *merge_blobs(const char *, struct blob *, struct blob *, struct blob *, unsigned long *);
+
+#endif /* MERGE_BLOBS_H */
diff --git a/merge-file.h b/merge-file.h
deleted file mode 100644
index 9b3b83ac6c..0000000000
--- a/merge-file.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef MERGE_FILE_H
-#define MERGE_FILE_H
-
-extern void *merge_file(const char *path, struct blob *base, struct blob *our,
- struct blob *their, unsigned long *size);
-
-#endif
diff --git a/merge-recursive.c b/merge-recursive.c
index d8820604ca..33ba5dc07c 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -976,7 +976,7 @@ merge_file_special_markers(struct merge_options *o,
return mfi;
}
-static struct merge_file_info merge_file(struct merge_options *o,
+static struct merge_file_info merge_file_one(struct merge_options *o,
const char *path,
const unsigned char *o_sha, int o_mode,
const unsigned char *a_sha, int a_mode,
@@ -1166,7 +1166,7 @@ static void conflict_rename_rename_1to2(struct merge_options *o,
struct merge_file_info mfi;
struct diff_filespec other;
struct diff_filespec *add;
- mfi = merge_file(o, one->path,
+ mfi = merge_file_one(o, one->path,
one->sha1, one->mode,
a->sha1, a->mode,
b->sha1, b->mode,
@@ -1450,7 +1450,7 @@ static int process_renames(struct merge_options *o,
ren1_dst, branch2);
if (o->call_depth) {
struct merge_file_info mfi;
- mfi = merge_file(o, ren1_dst, null_sha1, 0,
+ mfi = merge_file_one(o, ren1_dst, null_sha1, 0,
ren1->pair->two->sha1, ren1->pair->two->mode,
dst_other.sha1, dst_other.mode,
branch1, branch2);
diff --git a/mergetools/p4merge b/mergetools/p4merge
index 295361a8aa..52f7c8f705 100644
--- a/mergetools/p4merge
+++ b/mergetools/p4merge
@@ -1,29 +1,21 @@
diff_cmd () {
+ empty_file=
+
# p4merge does not like /dev/null
- rm_local=
- rm_remote=
if test "/dev/null" = "$LOCAL"
then
- LOCAL="./p4merge-dev-null.LOCAL.$$"
- >"$LOCAL"
- rm_local=true
+ LOCAL="$(create_empty_file)"
fi
if test "/dev/null" = "$REMOTE"
then
- REMOTE="./p4merge-dev-null.REMOTE.$$"
- >"$REMOTE"
- rm_remote=true
+ REMOTE="$(create_empty_file)"
fi
"$merge_tool_path" "$LOCAL" "$REMOTE"
- if test -n "$rm_local"
- then
- rm -f "$LOCAL"
- fi
- if test -n "$rm_remote"
+ if test -n "$empty_file"
then
- rm -f "$REMOTE"
+ rm -f "$empty_file"
fi
}
@@ -33,3 +25,10 @@ merge_cmd () {
"$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
check_unchanged
}
+
+create_empty_file () {
+ empty_file="${TMPDIR:-/tmp}/git-difftool-p4merge-empty-file.$$"
+ >"$empty_file"
+
+ printf "$empty_file"
+}
diff --git a/parse-options.c b/parse-options.c
index c1c66bd408..67e98a6323 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -18,15 +18,6 @@ int optbug(const struct option *opt, const char *reason)
return error("BUG: switch '%c' %s", opt->short_name, reason);
}
-int opterror(const struct option *opt, const char *reason, int flags)
-{
- if (flags & OPT_SHORT)
- return error("switch `%c' %s", opt->short_name, reason);
- if (flags & OPT_UNSET)
- return error("option `no-%s' %s", opt->long_name, reason);
- return error("option `%s' %s", opt->long_name, reason);
-}
-
static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
int flags, const char **arg)
{
@@ -594,3 +585,12 @@ static int parse_options_usage(struct parse_opt_ctx_t *ctx,
return usage_with_options_internal(ctx, usagestr, opts, 0, err);
}
+#undef opterror
+int opterror(const struct option *opt, const char *reason, int flags)
+{
+ if (flags & OPT_SHORT)
+ return error("switch `%c' %s", opt->short_name, reason);
+ if (flags & OPT_UNSET)
+ return error("option `no-%s' %s", opt->long_name, reason);
+ return error("option `%s' %s", opt->long_name, reason);
+}
diff --git a/parse-options.h b/parse-options.h
index 71a39c60d9..e703853749 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -177,6 +177,10 @@ extern NORETURN void usage_msg_opt(const char *msg,
extern int optbug(const struct option *opt, const char *reason);
extern int opterror(const struct option *opt, const char *reason, int flags);
+#ifdef __GNUC__
+#define opterror(o,r,f) (opterror((o),(r),(f)), -1)
+#endif
+
/*----- incremental advanced APIs -----*/
enum {
diff --git a/path.c b/path.c
index cbbdf7d6ba..d3d3f8b8ad 100644
--- a/path.c
+++ b/path.c
@@ -12,6 +12,7 @@
*/
#include "cache.h"
#include "strbuf.h"
+#include "string-list.h"
static char bad_path[] = "/bad-path/";
@@ -569,43 +570,38 @@ int normalize_path_copy(char *dst, const char *src)
/*
* path = Canonical absolute path
- * prefix_list = Colon-separated list of absolute paths
+ * prefixes = string_list containing normalized, absolute paths without
+ * trailing slashes (except for the root directory, which is denoted by "/").
*
- * Determines, for each path in prefix_list, whether the "prefix" really
+ * Determines, for each path in prefixes, whether the "prefix"
* is an ancestor directory of path. Returns the length of the longest
* ancestor directory, excluding any trailing slashes, or -1 if no prefix
- * is an ancestor. (Note that this means 0 is returned if prefix_list is
- * "/".) "/foo" is not considered an ancestor of "/foobar". Directories
+ * is an ancestor. (Note that this means 0 is returned if prefixes is
+ * ["/"].) "/foo" is not considered an ancestor of "/foobar". Directories
* are not considered to be their own ancestors. path must be in a
* canonical form: empty components, or "." or ".." components are not
- * allowed. prefix_list may be null, which is like "".
+ * allowed.
*/
-int longest_ancestor_length(const char *path, const char *prefix_list)
+int longest_ancestor_length(const char *path, struct string_list *prefixes)
{
- char buf[PATH_MAX+1];
- const char *ceil, *colon;
- int len, max_len = -1;
+ int i, max_len = -1;
- if (prefix_list == NULL || !strcmp(path, "/"))
+ if (!strcmp(path, "/"))
return -1;
- for (colon = ceil = prefix_list; *colon; ceil = colon+1) {
- for (colon = ceil; *colon && *colon != PATH_SEP; colon++);
- len = colon - ceil;
- if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
- continue;
- strlcpy(buf, ceil, len+1);
- if (normalize_path_copy(buf, buf) < 0)
- continue;
- len = strlen(buf);
- if (len > 0 && buf[len-1] == '/')
- buf[--len] = '\0';
+ for (i = 0; i < prefixes->nr; i++) {
+ const char *ceil = prefixes->items[i].string;
+ int len = strlen(ceil);
- if (!strncmp(path, buf, len) &&
- path[len] == '/' &&
- len > max_len) {
+ if (len == 1 && ceil[0] == '/')
+ len = 0; /* root matches anything, with length 0 */
+ else if (!strncmp(path, ceil, len) && path[len] == '/')
+ ; /* match of length len */
+ else
+ continue; /* no match */
+
+ if (len > max_len)
max_len = len;
- }
}
return max_len;
diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm
index 3bbc20a054..3db152155c 100644
--- a/perl/Git/SVN/Editor.pm
+++ b/perl/Git/SVN/Editor.pm
@@ -145,7 +145,8 @@ sub repo_path {
sub url_path {
my ($self, $path) = @_;
if ($self->{url} =~ m#^https?://#) {
- $path =~ s!([^~a-zA-Z0-9_./-])!uc sprintf("%%%02x",ord($1))!eg;
+ # characters are taken from subversion/libsvn_subr/path.c
+ $path =~ s#([^~a-zA-Z0-9_./!$&'()*+,-])#uc sprintf("%%%02x",ord($1))#eg;
}
$self->{url} . '/' . $self->repo_path($path);
}
@@ -358,12 +359,12 @@ sub T {
mode_a => $m->{mode_a}, mode_b => '000000',
sha1_a => $m->{sha1_a}, sha1_b => '0' x 40,
chg => 'D', file_b => $m->{file_b}
- });
+ }, $deletions);
$self->A({
mode_a => '000000', mode_b => $m->{mode_b},
sha1_a => '0' x 40, sha1_b => $m->{sha1_b},
chg => 'A', file_b => $m->{file_b}
- });
+ }, $deletions);
return;
}
diff --git a/perl/Git/SVN/Utils.pm b/perl/Git/SVN/Utils.pm
index 8b8cf3755c..3d1a0933a2 100644
--- a/perl/Git/SVN/Utils.pm
+++ b/perl/Git/SVN/Utils.pm
@@ -155,7 +155,7 @@ sub _canonicalize_url_path {
my @parts;
foreach my $part (split m{/+}, $uri_path) {
- $part =~ s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
+ $part =~ s/([^!\$%&'()*+,.\/\w:=\@_`~-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
push @parts, $part;
}
diff --git a/po/de.po b/po/de.po
index 0e8ed5437a..c8ad2f01c9 100644
--- a/po/de.po
+++ b/po/de.po
@@ -33,10 +33,10 @@ msgid ""
"appropriate to mark resolution and make a commit,\n"
"or use 'git commit -a'."
msgstr ""
-"Korrigiere dies im Arbeitsbaum,\n"
-"und benutze dann 'git add/rm <Datei>'\n"
+"Korrigieren Sie dies im Arbeitsbaum,\n"
+"und benutzen Sie dann 'git add/rm <Datei>'\n"
"um die Auflösung entsprechend zu markieren und einzutragen,\n"
-"oder benutze 'git commit -a'."
+"oder benutzen Sie 'git commit -a'."
#: archive.c:10
msgid "git archive [options] <tree-ish> [<path>...]"
@@ -131,7 +131,7 @@ msgid ""
"Use '\\!' for literal leading exclamation."
msgstr ""
"Verneinende Muster sind in Git-Attributen verboten.\n"
-"Benutze '\\!' für führende Ausrufezeichen."
+"Benutzen Sie '\\!' für führende Ausrufezeichen."
#: bundle.c:36
#, c-format
@@ -381,7 +381,7 @@ msgstr "Vorhandene Git-Kommandos in '%s'"
#: help.c:219
msgid "git commands available from elsewhere on your $PATH"
-msgstr "Vorhandene Git-Kommandos irgendwo in deinem $PATH"
+msgstr "Vorhandene Git-Kommandos irgendwo in Ihrem $PATH"
#: help.c:275
#, c-format
@@ -394,7 +394,7 @@ msgstr ""
#: help.c:332
msgid "Uh oh. Your system reports no Git commands at all."
-msgstr "Uh oh. Keine Git-Kommandos auf deinem System vorhanden."
+msgstr "Uh oh. Keine Git-Kommandos auf Ihrem System vorhanden."
#: help.c:354
#, c-format
@@ -402,8 +402,8 @@ msgid ""
"WARNING: You called a Git command named '%s', which does not exist.\n"
"Continuing under the assumption that you meant '%s'"
msgstr ""
-"Warnung: Du hast das nicht existierende Git-Kommando '%s' ausgeführt.\n"
-"Setze fort unter der Annahme das du '%s' gemeint hast"
+"Warnung: Sie haben das nicht existierende Git-Kommando '%s' ausgeführt.\n"
+"Setze fort unter der Annahme, dass Sie '%s' gemeint haben"
#: help.c:359
#, c-format
@@ -424,10 +424,10 @@ msgid_plural ""
"Did you mean one of these?"
msgstr[0] ""
"\n"
-"Hast du das gemeint?"
+"Haben Sie das gemeint?"
msgstr[1] ""
"\n"
-"Hast du eines von diesen gemeint?"
+"Haben Sie eines von diesen gemeint?"
#: merge.c:56
msgid "failed to read the cache"
@@ -721,12 +721,12 @@ msgstr " %s"
#, c-format
msgid "Your branch is ahead of '%s' by %d commit.\n"
msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
-msgstr[0] "Dein Zweig ist vor '%s' um %d Version.\n"
-msgstr[1] "Dein Zweig ist vor '%s' um %d Versionen.\n"
+msgstr[0] "Ihr Zweig ist vor '%s' um %d Version.\n"
+msgstr[1] "Ihr Zweig ist vor '%s' um %d Versionen.\n"
#: remote.c:1637
msgid " (use \"git push\" to publish your local commits)\n"
-msgstr " (benutze \"git push\" um deine lokalen Versionen herauszubringen)\n"
+msgstr " (benutzen Sie \"git push\" um lokalen Versionen herauszubringen)\n"
#: remote.c:1640
#, c-format
@@ -734,15 +734,15 @@ msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
msgid_plural ""
"Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n"
msgstr[0] ""
-"Dein Zweig ist zu '%s' um %d Version hinterher, und kann vorgespult werden.\n"
+"Ihr Zweig ist zu '%s' um %d Version hinterher, und kann vorgespult werden.\n"
msgstr[1] ""
-"Dein Zweig ist zu '%s' um %d Versionen hinterher, und kann vorgespult "
+"Ihr Zweig ist zu '%s' um %d Versionen hinterher, und kann vorgespult "
"werden.\n"
#: remote.c:1647
msgid " (use \"git pull\" to update your local branch)\n"
msgstr ""
-" (benutze \"git pull\" um deinen lokalen Zweig zu aktualisieren)\n"
+" (benutzen Sie \"git pull\" um Ihren lokalen Zweig zu aktualisieren)\n"
#: remote.c:1650
#, c-format
@@ -753,16 +753,16 @@ msgid_plural ""
"Your branch and '%s' have diverged,\n"
"and have %d and %d different commits each, respectively.\n"
msgstr[0] ""
-"Dein Zweig und '%s' sind divergiert,\n"
+"Ihr Zweig und '%s' sind divergiert,\n"
"und haben jeweils %d und %d unterschiedliche Versionen.\n"
msgstr[1] ""
-"Dein Zweig und '%s' sind divergiert,\n"
+"Ihr Zweig und '%s' sind divergiert,\n"
"und haben jeweils %d und %d unterschiedliche Versionen.\n"
#: remote.c:1659
msgid " (use \"git pull\" to merge the remote branch into yours)\n"
msgstr ""
-" (benutze \"git pull\" um deinen Zweig mit dem externen zusammenzuführen)\n"
+" (benutzen Sie \"git pull\" um Ihren Zweig mit dem externen zusammenzuführen)\n"
#: sequencer.c:123 builtin/merge.c:761 builtin/merge.c:874 builtin/merge.c:984
#: builtin/merge.c:994
@@ -781,7 +781,7 @@ msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
-"nach Auflösung der Konflikte, markiere die korrigierten Pfade\n"
+"nach Auflösung der Konflikte, markieren Sie die korrigierten Pfade\n"
"mit 'git add <Pfade>' oder 'git rm <Pfade>'"
#: sequencer.c:149
@@ -790,9 +790,9 @@ msgid ""
"with 'git add <paths>' or 'git rm <paths>'\n"
"and commit the result with 'git commit'"
msgstr ""
-"nach Auflösung der Konflikte, markiere die korrigierten Pfade\n"
-"mit 'git add <Pfade>' oder 'git rm <Pfade>'und trage das Ergebnis ein mit "
-"'git commit'"
+"nach Auflösung der Konflikte, markieren Sie die korrigierten Pfade\n"
+"mit 'git add <Pfade>' oder 'git rm <Pfade>'und tragen Sie das Ergebnis mit\n"
+"'git commit' ein"
#: sequencer.c:162 sequencer.c:770 sequencer.c:853
#, c-format
@@ -807,15 +807,15 @@ msgstr "Fehler bei Nachbereitung von %s"
#: sequencer.c:180
msgid "Your local changes would be overwritten by cherry-pick."
msgstr ""
-"Deine lokalen Änderungen würden von \"cherry-pick\" überschrieben werden."
+"Ihre lokalen Änderungen würden von \"cherry-pick\" überschrieben werden."
#: sequencer.c:182
msgid "Your local changes would be overwritten by revert."
-msgstr "Deine lokalen Änderungen würden von \"revert\" überschrieben werden."
+msgstr "Ihre lokalen Änderungen würden von \"revert\" überschrieben werden."
#: sequencer.c:185
msgid "Commit your changes or stash them to proceed."
-msgstr "Trage deine Änderungen ein oder benutze \"stash\" um fortzufahren."
+msgstr "Tragen Sie Ihre Änderungen ein oder benutzen Sie \"stash\" um fortzufahren."
#. TRANSLATORS: %s will be "revert" or "cherry-pick"
#: sequencer.c:235
@@ -843,11 +843,11 @@ msgstr "Konnte Elternversion %s nicht parsen\n"
#: sequencer.c:403
msgid "Your index file is unmerged."
-msgstr "Deine Bereitstellungsdatei ist nicht zusammengeführt."
+msgstr "Ihre Bereitstellungsdatei ist nicht zusammengeführt."
#: sequencer.c:406
msgid "You do not have a valid HEAD"
-msgstr "Du hast keine gültige Zweigspitze (HEAD)"
+msgstr "Sie haben keine gültige Zweigspitze (HEAD)"
#: sequencer.c:421
#, c-format
@@ -953,7 +953,7 @@ msgstr "\"cherry-pick\" oder \"revert\" ist bereits im Gang"
#: sequencer.c:752
msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
-msgstr "versuche \"git cherry-pick (--continue | --quit | --abort)\""
+msgstr "versuchen Sie \"git cherry-pick (--continue | --quit | --abort)\""
#: sequencer.c:756
#, c-format
@@ -1053,28 +1053,28 @@ msgstr "Nicht zusammengeführte Pfade:"
#, c-format
msgid " (use \"git reset %s <file>...\" to unstage)"
msgstr ""
-" (benutze \"git reset %s <Datei>...\" zum Herausnehmen aus der "
+" (benutzen Sie \"git reset %s <Datei>...\" zum Herausnehmen aus der "
"Bereitstellung)"
#: wt-status.c:169 wt-status.c:196
msgid " (use \"git rm --cached <file>...\" to unstage)"
msgstr ""
-" (benutze \"git rm --cached <Datei>...\" zum Herausnehmen aus der "
+" (benutzen Sie \"git rm --cached <Datei>...\" zum Herausnehmen aus der "
"Bereitstellung)"
#: wt-status.c:173
msgid " (use \"git add <file>...\" to mark resolution)"
-msgstr " (benutze \"git add/rm <Datei>...\" um die Auflösung zu markieren)"
+msgstr " (benutzen Sie \"git add/rm <Datei>...\" um die Auflösung zu markieren)"
#: wt-status.c:175 wt-status.c:179
msgid " (use \"git add/rm <file>...\" as appropriate to mark resolution)"
msgstr ""
-" (benutze \"git add/rm <Datei>...\" um die Auflösung entsprechend zu "
+" (benutzen Sie \"git add/rm <Datei>...\" um die Auflösung entsprechend zu "
"markieren)"
#: wt-status.c:177
msgid " (use \"git rm <file>...\" to mark resolution)"
-msgstr " (benutze \"git add/rm <Datei>...\" um die Auflösung zu markieren)"
+msgstr " (benutzen Sie \"git add/rm <Datei>...\" um die Auflösung zu markieren)"
#: wt-status.c:188
msgid "Changes to be committed:"
@@ -1086,29 +1086,29 @@ msgstr "Änderungen, die nicht zum Eintragen bereitgestellt sind:"
#: wt-status.c:210
msgid " (use \"git add <file>...\" to update what will be committed)"
-msgstr " (benutze \"git add <Datei>...\" zum Bereitstellen)"
+msgstr " (benutzen Sie \"git add <Datei>...\" zum Bereitstellen)"
#: wt-status.c:212
msgid " (use \"git add/rm <file>...\" to update what will be committed)"
-msgstr " (benutze \"git add/rm <Datei>...\" zum Bereitstellen)"
+msgstr " (benutzen Sie \"git add/rm <Datei>...\" zum Bereitstellen)"
#: wt-status.c:213
msgid ""
" (use \"git checkout -- <file>...\" to discard changes in working directory)"
msgstr ""
-" (benutze \"git checkout -- <Datei>...\" um die Änderungen im "
+" (benutzen Sie \"git checkout -- <Datei>...\" um die Änderungen im "
"Arbeitsverzeichnis zu verwerfen)"
#: wt-status.c:215
msgid " (commit or discard the untracked or modified content in submodules)"
msgstr ""
-" (trage ein oder verwerfe den unbeobachteten oder geänderten Inhalt in den "
+" (tragen Sie ein oder verwerfen Sie den unbeobachteten oder geänderten Inhalt in den "
"Unterprojekten)"
#: wt-status.c:227
#, c-format
msgid " (use \"git %s <file>...\" to include in what will be committed)"
-msgstr " (benutze \"git %s <Datei>...\" zum Einfügen in die Eintragung)"
+msgstr " (benutzen Sie \"git %s <Datei>...\" zum Einfügen in die Eintragung)"
#: wt-status.c:244
msgid "bug"
@@ -1201,20 +1201,20 @@ msgstr "Fehler: unbehandelter Differenz-Status %c"
#: wt-status.c:785
msgid "You have unmerged paths."
-msgstr "Du hast nicht zusammengeführte Pfade."
+msgstr "Sie haben nicht zusammengeführte Pfade."
#: wt-status.c:788 wt-status.c:912
msgid " (fix conflicts and run \"git commit\")"
-msgstr " (behebe die Konflikte und führe \"git commit\" aus)"
+msgstr " (beheben Sie die Konflikte und führen Sie \"git commit\" aus)"
#: wt-status.c:791
msgid "All conflicts fixed but you are still merging."
msgstr ""
-"Alle Konflikte sind behoben, aber du bist immer noch beim Zusammenführen."
+"Alle Konflikte sind behoben, aber Sie sind immer noch beim Zusammenführen."
#: wt-status.c:794
msgid " (use \"git commit\" to conclude merge)"
-msgstr " (benutze \"git commit\" um die Zusammenführung abzuschließen)"
+msgstr " (benutzen Sie \"git commit\" um die Zusammenführung abzuschließen)"
#: wt-status.c:804
msgid "You are in the middle of an am session."
@@ -1226,80 +1226,80 @@ msgstr "Der aktuelle Patch ist leer."
#: wt-status.c:811
msgid " (fix conflicts and then run \"git am --resolved\")"
-msgstr " (behebe die Konflikte und führe dann \"git am --resolved\" aus)"
+msgstr " (beheben Sie die Konflikte und führen Sie dann \"git am --resolved\" aus)"
#: wt-status.c:813
msgid " (use \"git am --skip\" to skip this patch)"
-msgstr " (benutze \"git am --skip\" um diesen Patch auszulassen)"
+msgstr " (benutzen Sie \"git am --skip\" um diesen Patch auszulassen)"
#: wt-status.c:815
msgid " (use \"git am --abort\" to restore the original branch)"
msgstr ""
-" (benutze \"git am --abort\" um den ursprünglichen Zweig wiederherzustellen)"
+" (benutzen Sie \"git am --abort\" um den ursprünglichen Zweig wiederherzustellen)"
#: wt-status.c:873 wt-status.c:883
msgid "You are currently rebasing."
-msgstr "Du bist gerade beim Neuaufbau."
+msgstr "Sie sind gerade beim Neuaufbau."
#: wt-status.c:876
msgid " (fix conflicts and then run \"git rebase --continue\")"
-msgstr " (behebe die Konflikte und führe dann \"git rebase --continue\" aus)"
+msgstr " (beheben Sie die Konflikte und führen Sie dann \"git rebase --continue\" aus)"
#: wt-status.c:878
msgid " (use \"git rebase --skip\" to skip this patch)"
-msgstr " (benutze \"git rebase --skip\" um diesen Patch auszulassen)"
+msgstr " (benutzen Sie \"git rebase --skip\" um diesen Patch auszulassen)"
#: wt-status.c:880
msgid " (use \"git rebase --abort\" to check out the original branch)"
msgstr ""
-" (benutze \"git rebase --abort\" um den ursprünglichen Zweig auszuchecken)"
+" (benutzen Sie \"git rebase --abort\" um den ursprünglichen Zweig auszuchecken)"
#: wt-status.c:886
msgid " (all conflicts fixed: run \"git rebase --continue\")"
-msgstr " (alle Konflikte behoben: führe \"git rebase --continue\" aus)"
+msgstr " (alle Konflikte behoben: führen Sie \"git rebase --continue\" aus)"
#: wt-status.c:888
msgid "You are currently splitting a commit during a rebase."
-msgstr "Du teilst gerade eine Version während eines Neuaufbaus auf."
+msgstr "Sie teilen gerade eine Version während eines Neuaufbaus auf."
#: wt-status.c:891
msgid " (Once your working directory is clean, run \"git rebase --continue\")"
msgstr ""
-" (Sobald dein Arbeitsverzeichnis sauber ist, führe \"git rebase --continue"
+" (Sobald Ihr Arbeitsverzeichnis sauber ist, führen Sie \"git rebase --continue"
"\" aus)"
#: wt-status.c:893
msgid "You are currently editing a commit during a rebase."
-msgstr "Du editierst gerade eine Version während eines Neuaufbaus."
+msgstr "Sie editieren gerade eine Version während eines Neuaufbaus."
#: wt-status.c:896
msgid " (use \"git commit --amend\" to amend the current commit)"
msgstr ""
-" (benutze \"git commit --amend\" um die aktuelle Version nachzubessern)"
+" (benutzen Sie \"git commit --amend\" um die aktuelle Version nachzubessern)"
#: wt-status.c:898
msgid ""
" (use \"git rebase --continue\" once you are satisfied with your changes)"
msgstr ""
-" (benutze \"git rebase --continue\" sobald deine Änderungen abgeschlossen "
+" (benutzen Sie \"git rebase --continue\" sobald Ihre Änderungen abgeschlossen "
"sind)"
#: wt-status.c:908
msgid "You are currently cherry-picking."
-msgstr "Du führst gerade \"cherry-pick\" aus."
+msgstr "Sie führen gerade \"cherry-pick\" aus."
#: wt-status.c:915
msgid " (all conflicts fixed: run \"git commit\")"
-msgstr " (alle Konflikte behoben: führe \"git commit\" aus)"
+msgstr " (alle Konflikte behoben: führen Sie \"git commit\" aus)"
#: wt-status.c:924
msgid "You are currently bisecting."
-msgstr "Du bist gerade beim Halbieren."
+msgstr "Sie sind gerade beim Halbieren."
#: wt-status.c:927
msgid " (use \"git bisect reset\" to get back to the original branch)"
msgstr ""
-" (benutze \"git bisect reset\" um zum ursprünglichen Zweig zurückzukehren)"
+" (benutzen Sie \"git bisect reset\" um zum ursprünglichen Zweig zurückzukehren)"
#: wt-status.c:978
msgid "On branch "
@@ -1328,7 +1328,7 @@ msgstr "Unbeobachtete Dateien nicht aufgelistet%s"
#: wt-status.c:1017
msgid " (use -u option to show untracked files)"
-msgstr " (benutze die Option -u um unbeobachteten Dateien anzuzeigen)"
+msgstr " (benutzen Sie die Option -u um unbeobachteten Dateien anzuzeigen)"
#: wt-status.c:1023
msgid "No changes"
@@ -1338,7 +1338,7 @@ msgstr "Keine Änderungen"
#, c-format
msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
msgstr ""
-"keine Änderungen zum Eintragen hinzugefügt (benutze \"git add\" und/oder "
+"keine Änderungen zum Eintragen hinzugefügt (benutzen Sie \"git add\" und/oder "
"\"git commit -a\")\n"
#: wt-status.c:1031
@@ -1353,7 +1353,7 @@ msgid ""
"track)\n"
msgstr ""
"nichts zum Eintragen hinzugefügt, aber es gibt unbeobachtete Dateien "
-"(benutze \"git add\" zum Beobachten)\n"
+"(benutzen Sie \"git add\" zum Beobachten)\n"
#: wt-status.c:1037
#, c-format
@@ -1364,8 +1364,8 @@ msgstr "nichts zum Eintragen hinzugefügt, aber es gibt unbeobachtete Dateien\n"
#, c-format
msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
msgstr ""
-"nichts einzutragen (Erstelle/Kopiere Dateien und benutze \"git add\" zum "
-"Beobachten)\n"
+"nichts einzutragen (Erstellen/Kopieren Sie Dateien und benutzen Sie \"git add\" "
+"zum Beobachten)\n"
#: wt-status.c:1043 wt-status.c:1048
#, c-format
@@ -1376,7 +1376,7 @@ msgstr "nichts einzutragen\n"
#, c-format
msgid "nothing to commit (use -u to show untracked files)\n"
msgstr ""
-"nichts einzutragen (benutze die Option -u, um unbeobachtete Dateien "
+"nichts einzutragen (benutzen Sie die Option -u, um unbeobachtete Dateien "
"anzuzeigen)\n"
#: wt-status.c:1050
@@ -1477,7 +1477,7 @@ msgstr "Konnte '%s' nicht anwenden."
#: builtin/add.c:313
msgid "The following paths are ignored by one of your .gitignore files:\n"
msgstr ""
-"Die folgenden Pfade werden durch eine deiner \".gitignore\" Dateien "
+"Die folgenden Pfade werden durch eine Ihrer \".gitignore\" Dateien "
"ignoriert:\n"
#: builtin/add.c:319 builtin/clean.c:52 builtin/fetch.c:78 builtin/mv.c:63
@@ -1538,7 +1538,7 @@ msgstr "prüft ob - auch fehlende - Dateien im Probelauf ignoriert werden"
#: builtin/add.c:353
#, c-format
msgid "Use -f if you really want to add them.\n"
-msgstr "Verwende -f wenn du diese wirklich hinzufügen möchtest.\n"
+msgstr "Verwenden Sie -f wenn Sie diese wirklich hinzufügen möchten.\n"
#: builtin/add.c:354
msgid "no files added"
@@ -1565,7 +1565,7 @@ msgstr "Nichts spezifiziert, nichts hinzugefügt.\n"
#: builtin/add.c:415
#, c-format
msgid "Maybe you wanted to say 'git add .'?\n"
-msgstr "Wolltest du vielleicht 'git add .' sagen?\n"
+msgstr "Wollten Sie vielleicht 'git add .' sagen?\n"
#: builtin/add.c:421 builtin/clean.c:95 builtin/commit.c:291 builtin/mv.c:82
#: builtin/rm.c:235
@@ -2269,7 +2269,7 @@ msgid ""
"If you are sure you want to delete it, run 'git branch -D %s'."
msgstr ""
"Der Zweig '%s' ist nicht vollständig zusammengeführt.\n"
-"Wenn du sicher bist diesen Zweig zu entfernen, führe 'git branch -D %s' aus."
+"Wenn Sie sicher sind diesen Zweig zu entfernen, führen Sie 'git branch -D %s' aus."
#: builtin/branch.c:180
msgid "Update of config-file failed"
@@ -2287,7 +2287,7 @@ msgstr "Konnte Versionsobjekt für Zweigspitze (HEAD) nicht nachschlagen."
#, c-format
msgid "Cannot delete the branch '%s' which you are currently on."
msgstr ""
-"Kann Zweig '%s' nicht entfernen, da du dich gerade auf diesem befindest."
+"Kann Zweig '%s' nicht entfernen, da Sie sich gerade auf diesem befinden."
#: builtin/branch.c:235
#, c-format
@@ -2365,7 +2365,7 @@ msgstr "Konnte einige Referenzen nicht lesen"
#: builtin/branch.c:638
msgid "cannot rename the current branch while not on any."
msgstr ""
-"Kann aktuellen Zweig nicht umbenennen, solange du dich auf keinem befindest."
+"Kann aktuellen Zweig nicht umbenennen, solange Sie sich auf keinem befinden."
#: builtin/branch.c:648
#, c-format
@@ -2527,8 +2527,8 @@ msgid ""
"The --set-upstream flag is deprecated and will be removed. Consider using --"
"track or --set-upstream-to\n"
msgstr ""
-"Die --set-upstream Option ist veraltet und wird entfernt. Benutze --track "
-"oder --set-upstream-to\n"
+"Die --set-upstream Option ist veraltet und wird entfernt. Benutzen Sie "
+"--track oder --set-upstream-to\n"
#: builtin/branch.c:934
#, c-format
@@ -2538,8 +2538,8 @@ msgid ""
"\n"
msgstr ""
"\n"
-"Wenn du wolltest, dass '%s' den Zweig '%s' als externen Ãœbernahmezweig hat, "
-"führe aus:\n"
+"Wenn Sie wollten, dass '%s' den Zweig '%s' als externen Ãœbernahmezweig hat, "
+"führen Sie aus:\n"
#: builtin/branch.c:935
#, c-format
@@ -2743,7 +2743,7 @@ msgstr "Pfad '%s' ist nicht zusammengeführt."
#: builtin/checkout.c:448
msgid "you need to resolve your current index first"
-msgstr "Du musst zuerst deine aktuelle Bereitstellung auflösen."
+msgstr "Sie müssen zuerst Ihre aktuelle Bereitstellung auflösen."
#: builtin/checkout.c:569
#, c-format
@@ -2798,13 +2798,13 @@ msgid_plural ""
"\n"
"%s\n"
msgstr[0] ""
-"Warnung: Du bist um %d Version hinterher, nicht verbunden zu\n"
-"einem deiner Zweige:\n"
+"Warnung: Sie sind um %d Version hinterher, nicht verbunden zu\n"
+"einem Ihrer Zweige:\n"
"\n"
"%s\n"
msgstr[1] ""
-"Warnung: Du bist um %d Versionen hinterher, nicht verbunden zu\n"
-"einem deiner Zweige:\n"
+"Warnung: Sie sind um %d Versionen hinterher, nicht verbunden zu\n"
+"einem Ihrer Zweige:\n"
"\n"
"%s\n"
@@ -2817,7 +2817,7 @@ msgid ""
" git branch new_branch_name %s\n"
"\n"
msgstr ""
-"Wenn du diese durch einen neuen Zweig behalten möchtest, dann könnte jetzt\n"
+"Wenn Sie diese durch einen neuen Zweig behalten möchten, dann könnte jetzt\n"
"ein guter Zeitpunkt sein dies zu tun mit:\n"
"\n"
" git branch neuer_zweig_name %s\n"
@@ -2833,7 +2833,7 @@ msgstr "Vorherige Position der Zweigspitze (HEAD) war"
#: builtin/checkout.c:761 builtin/checkout.c:950
msgid "You are on a branch yet to be born"
-msgstr "du bist auf einem Zweig, der noch geboren wird"
+msgstr "Sie sind auf einem Zweig, der noch geboren wird"
#. case (1)
#: builtin/checkout.c:886
@@ -2946,7 +2946,7 @@ msgstr "--track benötigt einen Zweignamen"
#: builtin/checkout.c:1081
msgid "Missing branch name; try -b"
-msgstr "Vermisse Zweignamen; versuche -b"
+msgstr "Vermisse Zweignamen; versuchen Sie -b"
#: builtin/checkout.c:1116
msgid "invalid path specification"
@@ -2959,7 +2959,7 @@ msgid ""
"Did you intend to checkout '%s' which can not be resolved as commit?"
msgstr ""
"Kann nicht gleichzeitig Pfade aktualisieren und zu Zweig '%s' wechseln.\n"
-"Hast du beabsichtigt '%s' auszuchecken, welcher nicht als Version aufgelöst "
+"Haben Sie beabsichtigt '%s' auszuchecken, welcher nicht als Version aufgelöst "
"werden kann?"
#: builtin/checkout.c:1128
@@ -2973,7 +2973,7 @@ msgid ""
"checking out of the index."
msgstr ""
"git checkout: --ours/--theirs, --force und --merge sind inkompatibel wenn\n"
-"du aus der Bereitstellung auscheckst."
+"Sie aus der Bereitstellung auschecken."
#: builtin/clean.c:19
msgid "git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
@@ -3203,7 +3203,7 @@ msgstr "Zu viele Argumente."
#: builtin/clone.c:694
msgid "You must specify a repository to clone."
-msgstr "Du musst ein Projektarchiv zum Klonen angeben."
+msgstr "Sie müssen ein Projektarchiv zum Klonen angeben."
#: builtin/clone.c:705
#, c-format
@@ -3217,7 +3217,7 @@ msgstr "Projektarchiv '%s' existiert nicht."
#: builtin/clone.c:724
msgid "--depth is ignored in local clones; use file:// instead."
-msgstr "--depth wird in lokalen Klonen ignoriert; benutze stattdessen file://."
+msgstr "--depth wird in lokalen Klonen ignoriert; benutzen Sie stattdessen file://."
#: builtin/clone.c:734
#, c-format
@@ -3261,7 +3261,7 @@ msgstr "externer Zweig %s nicht im anderen Projektarchiv %s gefunden"
#: builtin/clone.c:879
msgid "You appear to have cloned an empty repository."
-msgstr "Du scheinst ein leeres Projektarchiv geklont zu haben."
+msgstr "Sie scheinen ein leeres Projektarchiv geklont zu haben."
#: builtin/column.c:9
msgid "git column [options]"
@@ -3316,15 +3316,15 @@ msgid ""
"\n"
" git commit --amend --reset-author\n"
msgstr ""
-"Dein Name und E-Mail Adresse wurden automatisch auf Basis\n"
-"deines Benutzer- und Rechnernamens konfiguriert. Bitte prüfe, dass diese\n"
-"zutreffend sind. Du kannst diese Meldung unterdrücken, indem du diese\n"
-"explizit setzt:\n"
+"Ihr Name und E-Mail Adresse wurden automatisch auf Basis\n"
+"Ihres Benutzer- und Rechnernamens konfiguriert. Bitte prüfen Sie, dass\n"
+"diese zutreffend sind. Sie können diese Meldung unterdrücken, indem Sie\n"
+"diese explizit setzen:\n"
"\n"
-" git config --global user.name \"Dein Name\"\n"
-" git config --global user.email deine@emailadresse.de\n"
+" git config --global user.name \"Ihr Name\"\n"
+" git config --global user.email ihre@emailadresse.de\n"
"\n"
-"Nachdem du das getan hast, kannst du deine Identität für diese Version "
+"Nachdem Sie das getan hast, können Sie Ihre Identität für diese Version "
"ändern mit:\n"
"\n"
" git commit --amend --reset-author\n"
@@ -3335,8 +3335,8 @@ msgid ""
"it empty. You can repeat your command with --allow-empty, or you can\n"
"remove the commit entirely with \"git reset HEAD^\".\n"
msgstr ""
-"Du fragtest die jüngste Version nachzubessern, aber das würde diese leer\n"
-"machen. Du kannst Dein Kommando mit --allow-empty wiederholen, oder die\n"
+"Sie fragten die jüngste Version nachzubessern, aber das würde diese leer\n"
+"machen. Sie können Ihr Kommando mit --allow-empty wiederholen, oder die\n"
"Version mit \"git reset HEAD^\" vollständig entfernen.\n"
#: builtin/commit.c:61
@@ -3350,11 +3350,11 @@ msgid ""
msgstr ""
"Der letzte \"cherry-pick\" ist jetzt leer, möglicherweise durch eine "
"Konfliktauflösung.\n"
-"Wenn du dies trotzdem eintragen willst, benutze:\n"
+"Wenn Sie dies trotzdem eintragen wollen, benutzen Sie:\n"
"\n"
" git commit --allow-empty\n"
"\n"
-"Andernfalls benutze bitte 'git reset'\n"
+"Andernfalls benutzen Sie bitte 'git reset'\n"
#: builtin/commit.c:258
msgid "failed to unpack HEAD tree object"
@@ -3456,10 +3456,10 @@ msgid ""
"and try again.\n"
msgstr ""
"\n"
-"Es sieht so aus, als trägst du eine Zusammenführung ein.\n"
-"Falls das nicht korrekt ist, lösche bitte die Datei\n"
+"Es sieht so aus, als tragen Sie eine Zusammenführung ein.\n"
+"Falls das nicht korrekt ist, löschen Sie bitte die Datei\n"
"\t%s\n"
-"und versuche es erneut.\n"
+"und versuchen Sie es erneut.\n"
#: builtin/commit.c:723
#, c-format
@@ -3471,17 +3471,17 @@ msgid ""
"and try again.\n"
msgstr ""
"\n"
-"Es sieht so aus, als trägst du ein \"cherry-pick\" ein.\n"
-"Falls das nicht korrekt ist, lösche bitte die Datei\n"
+"Es sieht so aus, als tragen Sie ein \"cherry-pick\" ein.\n"
+"Falls das nicht korrekt ist, löschen Sie bitte die Datei\n"
"\t%s\n"
-"und versuche es erneut.\n"
+"und versuchen Sie es erneut.\n"
#: builtin/commit.c:735
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
"with '#' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
-"Bitte gebe eine Versionsbeschreibung für deine Änderungen ein. Zeilen,\n"
+"Bitte geben Sie eine Versionsbeschreibung für Ihre Änderungen ein. Zeilen,\n"
"die mit '#' beginnen, werden ignoriert, und eine leere Versionsbeschreibung\n"
"bricht die Eintragung ab.\n"
@@ -3491,8 +3491,8 @@ msgid ""
"with '#' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
-"Bitte gebe eine Versionsbeschreibung für deine Änderungen ein. Zeilen, die\n"
-"mit '#' beginnen, werden beibehalten; wenn du möchtest, kannst du diese "
+"Bitte geben Sie eine Versionsbeschreibung für Ihre Änderungen ein. Zeilen, die\n"
+"mit '#' beginnen, werden beibehalten; wenn Sie möchten, können Sie diese "
"entfernen.\n"
"Eine leere Versionsbeschreibung bricht die Eintragung ab.\n"
@@ -3535,7 +3535,7 @@ msgstr "Verwendung von --reset-author und --author macht keinen Sinn."
#: builtin/commit.c:995
msgid "You have nothing to amend."
-msgstr "Du hast nichts zum nachbessern."
+msgstr "Sie haben nichts zum nachbessern."
#: builtin/commit.c:998
msgid "You are in the middle of a merge -- cannot amend."
@@ -3726,7 +3726,7 @@ msgstr ""
#: builtin/commit.c:1380
msgid "the commit is authored by me now (used with -C/-c/--amend)"
-msgstr "Setze mich als Autor der Version (benutzt mit -C/-c/--amend)"
+msgstr "Setzt Sie als Autor der Version (benutzt mit -C/-c/--amend)"
#: builtin/commit.c:1381 builtin/log.c:1073 builtin/revert.c:109
msgid "add Signed-off-by:"
@@ -3836,7 +3836,7 @@ msgstr "Konnte Versionsbeschreibung nicht lesen: %s"
#: builtin/commit.c:1534
#, c-format
msgid "Aborting commit; you did not edit the message.\n"
-msgstr "Eintragung abgebrochen; du hast die Beschreibung nicht editiert.\n"
+msgstr "Eintragung abgebrochen; Sie haben die Beschreibung nicht editiert.\n"
#: builtin/commit.c:1539
#, c-format
@@ -3862,8 +3862,8 @@ msgid ""
"not exceeded, and then \"git reset HEAD\" to recover."
msgstr ""
"Das Projektarchiv wurde aktualisiert, aber die \"new_index\"-Datei\n"
-"konnte nicht geschrieben werden. Prüfe, dass deine Festplatte nicht\n"
-"voll und Dein Kontingent nicht aufgebraucht ist und führe\n"
+"konnte nicht geschrieben werden. Prüfen Sie, dass Ihre Festplatte nicht\n"
+"voll und Ihr Kontingent nicht aufgebraucht ist und führen Sie\n"
"anschließend \"git reset HEAD\" zu Wiederherstellung aus."
#: builtin/config.c:7
@@ -4041,7 +4041,7 @@ msgid ""
"However, there were unannotated tags: try --tags."
msgstr ""
"Keine annotierten Markierungen können '%s' beschreiben.\n"
-"Jedoch gab es nicht annotierte Markierungen: versuche --tags."
+"Jedoch gab es nicht annotierte Markierungen: versuchen Sie --tags."
#: builtin/describe.c:357
#, c-format
@@ -4050,7 +4050,7 @@ msgid ""
"Try --always, or create some tags."
msgstr ""
"Keine Markierungen können '%s' beschreiben.\n"
-"Versuche --always oder erstelle einige Markierungen."
+"Versuchen Sie --always oder erstellen Sie einige Markierungen."
#: builtin/describe.c:378
#, c-format
@@ -4354,7 +4354,7 @@ msgid ""
"some local refs could not be updated; try running\n"
" 'git remote prune %s' to remove any old, conflicting branches"
msgstr ""
-"Einige lokale Referenzen konnten nicht aktualisiert werden; versuche\n"
+"Einige lokale Referenzen konnten nicht aktualisiert werden; versuchen Sie\n"
"'git remote prune %s' um jeden älteren, widersprüchlichen Zweig zu löschen."
#: builtin/fetch.c:549
@@ -4412,13 +4412,13 @@ msgid ""
"No remote repository specified. Please, specify either a URL or a\n"
"remote name from which new revisions should be fetched."
msgstr ""
-"Kein externes Projektarchiv angegeben. Bitte gebe entweder eine URL\n"
+"Kein externes Projektarchiv angegeben. Bitte geben Sie entweder eine URL\n"
"oder den Namen des externen Archivs an, von welchem neue\n"
"Versionen angefordert werden sollen."
#: builtin/fetch.c:932
msgid "You need to specify a tag name."
-msgstr "Du musst den Namen der Markierung angeben."
+msgstr "Sie müssen den Namen der Markierung angeben."
#: builtin/fetch.c:984
msgid "fetch --all does not take a repository argument"
@@ -4587,15 +4587,15 @@ msgid ""
"run \"git gc\" manually. See \"git help gc\" for more information.\n"
msgstr ""
"Die Datenbank des Projektarchivs wird für eine optimale Performance\n"
-"komprimiert. Du kannst auch \"git gc\" manuell ausführen.\n"
+"komprimiert. Sie können auch \"git gc\" manuell ausführen.\n"
"Siehe \"git help gc\" für weitere Informationen.\n"
#: builtin/gc.c:249
msgid ""
"There are too many unreachable loose objects; run 'git prune' to remove them."
msgstr ""
-"Es gibt zu viele unerreichbare lose Objekte; führe 'git prune' aus, um diese "
-"zu löschen."
+"Es gibt zu viele unerreichbare lose Objekte; führen Sie 'git prune' aus, um "
+"diese zu löschen."
#: builtin/grep.c:22
msgid "git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]"
@@ -4918,7 +4918,7 @@ msgid ""
"Please consider using 'man.<tool>.cmd' instead."
msgstr ""
"'%s': Pfad für nicht unterstützten Handbuchbetrachter.\n"
-"Du könntest stattdessen 'man.<Werkzeug>.cmd' benutzen."
+"Sie könnten stattdessen 'man.<Werkzeug>.cmd' benutzen."
#: builtin/help.c:229
#, c-format
@@ -4927,7 +4927,7 @@ msgid ""
"Please consider using 'man.<tool>.path' instead."
msgstr ""
"'%s': Kommando für unterstützten Handbuchbetrachter.\n"
-"Du könntest stattdessen 'man.<Werkzeug>.path' benutzen."
+"Sie könnten stattdessen 'man.<Werkzeug>.path' benutzen."
#: builtin/help.c:299
msgid "The most commonly used git commands are:"
@@ -5636,8 +5636,8 @@ msgstr "git cherry [-v] [<Ãœbernahmezweig> [<Arbeitszweig> [<Limit>]]]"
msgid ""
"Could not find a tracked remote branch, please specify <upstream> manually.\n"
msgstr ""
-"Konnte gefolgten, externen Zweig nicht finden, bitte gebe <upstream> manuell "
-"an.\n"
+"Konnte gefolgten, externen Zweig nicht finden, bitte geben Sie <upstream> "
+"manuell an.\n"
#: builtin/log.c:1517 builtin/log.c:1519 builtin/log.c:1531
#, c-format
@@ -5956,7 +5956,7 @@ msgstr "konnte nicht von '%s' lesen"
#, c-format
msgid "Not committing merge; use 'git commit' to complete the merge.\n"
msgstr ""
-"Zusammenführung wurde nicht eingetragen; benutze 'git commit' um die "
+"Zusammenführung wurde nicht eingetragen; benutzen Sie 'git commit' um die "
"Zusammenführung abzuschließen.\n"
#: builtin/merge.c:788
@@ -5967,7 +5967,7 @@ msgid ""
"Lines starting with '#' will be ignored, and an empty message aborts\n"
"the commit.\n"
msgstr ""
-"Bitte gebe eine Versionsbeschreibung ein um zu erklären, warum diese "
+"Bitte geben Sie eine Versionsbeschreibung ein um zu erklären, warum diese "
"Zusammenführung erforderlich ist,\n"
"insbesondere wenn es einen aktualisierten, externen Zweig mit einem Thema-"
"Zweig zusammenführt.\n"
@@ -5988,8 +5988,8 @@ msgstr "Wunderbar.\n"
#, c-format
msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
msgstr ""
-"Automatische Zusammenführung fehlgeschlagen; behebe die Konflikte und trage "
-"dann das Ergebnis ein.\n"
+"Automatische Zusammenführung fehlgeschlagen; beheben Sie die Konflikte und tragen "
+"Sie dann das Ergebnis ein.\n"
#: builtin/merge.c:905
#, c-format
@@ -5998,7 +5998,7 @@ msgstr "'%s' ist keine Version"
#: builtin/merge.c:946
msgid "No current branch."
-msgstr "Du befindest dich auf keinem Zweig."
+msgstr "Sie befinden sich auf keinem Zweig."
#: builtin/merge.c:948
msgid "No remote for the current branch."
@@ -6029,34 +6029,34 @@ msgid ""
"You have not concluded your merge (MERGE_HEAD exists).\n"
"Please, commit your changes before you can merge."
msgstr ""
-"Du hast deine Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert).\n"
-"Bitte trage deine Änderungen ein, bevor du zusammenführen kannst."
+"Sie haben Ihre Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert).\n"
+"Bitte tragen Sie Ihre Änderungen ein, bevor Sie zusammenführen können."
#: builtin/merge.c:1129 git-pull.sh:34
msgid "You have not concluded your merge (MERGE_HEAD exists)."
msgstr ""
-"Du hast deine Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert)."
+"Sie haben Ihre Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert)."
#: builtin/merge.c:1133
msgid ""
"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
"Please, commit your changes before you can merge."
msgstr ""
-"Du hast \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert).\n"
-"Bitte trage deine Änderungen ein, bevor du zusammenführen kannst."
+"Sie haben \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert).\n"
+"Bitte tragen Sie Ihre Änderungen ein, bevor Sie zusammenführen können."
#: builtin/merge.c:1136
msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
msgstr ""
-"Du hast \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert)."
+"Sie haben \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert)."
#: builtin/merge.c:1145
msgid "You cannot combine --squash with --no-ff."
-msgstr "Du kannst --squash nicht mit --no-ff kombinieren."
+msgstr "Sie können --squash nicht mit --no-ff kombinieren."
#: builtin/merge.c:1150
msgid "You cannot combine --no-ff with --ff-only."
-msgstr "Du kannst --no-ff nicht mit --ff--only kombinieren."
+msgstr "Sie können --no-ff nicht mit --ff--only kombinieren."
#: builtin/merge.c:1157
msgid "No commit specified and merge.defaultToUpstream not set."
@@ -6116,7 +6116,7 @@ msgstr "Zusammenführung mit Strategie %s fehlgeschlagen.\n"
#: builtin/merge.c:1491
#, c-format
msgid "Using the %s to prepare resolving by hand.\n"
-msgstr "Benutze \"%s\" um die Auflösung per Hand vorzubereiten.\n"
+msgstr "Benutzen Sie \"%s\" um die Auflösung per Hand vorzubereiten.\n"
#: builtin/merge.c:1503
#, c-format
@@ -6461,7 +6461,7 @@ msgstr "konnte Datei '%s' nicht erstellen"
#: builtin/notes.c:192
msgid "Please supply the note contents using either -m or -F option"
-msgstr "Bitte liefere den Notiz-Inhalt unter Verwendung der Option -m oder -F."
+msgstr "Bitte liefern Sie den Notiz-Inhalt unter Verwendung der Option -m oder -F."
#: builtin/notes.c:213 builtin/notes.c:976
#, c-format
@@ -6575,7 +6575,7 @@ msgid ""
"existing notes"
msgstr ""
"Konnte Notizen nicht hinzufügen. Existierende Notizen für Objekt %s "
-"gefunden. Verwende '-f' um die existierenden Notizen zu überschreiben."
+"gefunden. Verwenden Sie '-f' um die existierenden Notizen zu überschreiben."
#: builtin/notes.c:588 builtin/notes.c:665
#, c-format
@@ -6603,7 +6603,7 @@ msgid ""
"existing notes"
msgstr ""
"Kann Notizen nicht kopieren. Existierende Notizen für Objekt %s gefunden. "
-"Verwende '-f' um die existierenden Notizen zu überschreiben."
+"Verwenden Sie '-f' um die existierenden Notizen zu überschreiben."
#: builtin/notes.c:671
#, c-format
@@ -6617,7 +6617,7 @@ msgid ""
"Please use 'git notes add -f -m/-F/-c/-C' instead.\n"
msgstr ""
"Die Optionen -m/-F/-c/-C sind für das Unterkommando 'edit' veraltet.\n"
-"Bitte benutze stattdessen 'git notes add -f -m/-F/-c/-C'.\n"
+"Bitte benutzen Sie stattdessen 'git notes add -f -m/-F/-c/-C'.\n"
#: builtin/notes.c:867
msgid "General options"
@@ -6908,14 +6908,14 @@ msgid ""
" git push %s %s\n"
"%s"
msgstr ""
-"Der Name des externen Ãœbernahmezweiges stimmt nicht mit dem Namen deines\n"
+"Der Name des externen Ãœbernahmezweiges stimmt nicht mit dem Namen Ihres\n"
"aktuellen Zweiges überein. Um auf den Übernahmezweig in dem externen\n"
-"Projektarchiv zu versenden, benutze:\n"
+"Projektarchiv zu versenden, benutzen Sie:\n"
"\n"
" git push %s HEAD:%s\n"
"\n"
"Um auf den Zweig mit dem selben Namen in dem externen Projekarchiv\n"
-"zu versenden, benutze:\n"
+"zu versenden, benutzen Sie:\n"
"\n"
" git push %s %s\n"
"%s"
@@ -6929,9 +6929,9 @@ msgid ""
"\n"
" git push %s HEAD:<name-of-remote-branch>\n"
msgstr ""
-"Du befindest dich sich im Moment auf keinem Zweig.\n"
+"Sie befinden sich im Moment auf keinem Zweig.\n"
"Um die Historie, führend zum aktuellen (freistehende Zweigspitze (HEAD))\n"
-"Status zu versenden, benutze\n"
+"Status zu versenden, benutzen Sie\n"
"\n"
" git push %s HEAD:<Name-des-externen-Zweiges>\n"
@@ -6945,7 +6945,7 @@ msgid ""
msgstr ""
"Der aktuelle Zweig %s hat keinen Zweig im externen Projektarchiv.\n"
"Um den aktuellen Zweig zu versenden und das Fernarchiv als externes\n"
-"Projektarchiv zu verwenden, benutze\n"
+"Projektarchiv zu verwenden, benutzen Sie\n"
"\n"
" git push --set-upstream %s %s\n"
@@ -6961,7 +6961,7 @@ msgid ""
"your current branch '%s', without telling me what to push\n"
"to update which remote branch."
msgstr ""
-"Du versendest nach '%s', welches kein externes Projektarchiv deines\n"
+"Sie versenden nach '%s', welches kein externes Projektarchiv Ihres\n"
"aktuellen Zweiges '%s' ist, ohne mir mitzuteilen, was ich versenden\n"
"soll, um welchen externen Zweig zu aktualisieren."
@@ -6985,26 +6985,25 @@ msgstr ""
"'push.default' ist nicht gesetzt; der implizit gesetzte Wert\n"
"wird in Git 2.0 von 'matching' nach 'simple' geändert. Um diese Meldung zu\n"
"unterdrücken und das aktuelle Verhalten nach Änderung des Standardwertes\n"
-"beizubehalten, benutze:\n"
+"beizubehalten, benutzen Sie:\n"
" git config --global push.default matching\n"
"\n"
"Um diese Meldung zu unterdrücken und das neue Verhalten jetzt zu "
-"übernehmen,\n"
-"benutze:\n"
+"übernehmen, benutzen Sie:\n"
"\n"
" git config --global push.default simple\n"
"\n"
-"Führe 'git help config' aus und suche nach 'push.default' für weitere "
-"Informationen.\n"
+"Führen Sie 'git help config' aus und suchen Sie nach 'push.default' für "
+"weitere Informationen.\n"
"(Der Modus 'simple' wurde in Git 1.7.11 eingeführt. Benutze den ähnlichen "
-"Modus 'current' anstatt 'simple', falls du gelegentlich ältere Versionen von "
-"Git benutzt.)"
+"Modus 'current' anstatt 'simple', falls Sie gelegentlich ältere Versionen von "
+"Git benutzen.)"
#: builtin/push.c:199
msgid ""
"You didn't specify any refspecs to push, and push.default is \"nothing\"."
msgstr ""
-"Du hast keine Referenzspezifikationen zum Versenden angegeben, und push."
+"Sie haben keine Referenzspezifikationen zum Versenden angegeben, und push."
"default ist \"nothing\"."
#: builtin/push.c:206
@@ -7014,9 +7013,10 @@ msgid ""
"before pushing again.\n"
"See the 'Note about fast-forwards' in 'git push --help' for details."
msgstr ""
-"Aktualisierungen wurden zurückgewiesen, weil die Spitze deines aktuellen\n"
-"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Führe die\n"
-"externen Änderungen zusammen (z.B. 'git pull') bevor du erneut versendest.\n"
+"Aktualisierungen wurden zurückgewiesen, weil die Spitze Ihres aktuellen\n"
+"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Führen Sie\n"
+"die externen Änderungen zusammen (z.B. 'git pull') bevor Sie erneut\n"
+"versenden.\n"
"Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n"
"für weitere Details."
@@ -7028,8 +7028,8 @@ msgid ""
"to 'simple', 'current' or 'upstream' to push only the current branch."
msgstr ""
"Aktualisierungen wurden zurückgewiesen, weil die Spitze eines versendeten\n"
-"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Wenn du nicht\n"
-"beabsichtigt hast, diesen Zweig zu versenden, kannst du auch den zu "
+"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Wenn Sie nicht\n"
+"beabsichtigt haben, diesen Zweig zu versenden, können Sie auch den zu "
"versendenden\n"
"Zweig spezifizieren oder die Konfigurationsvariable 'push.default' zu "
"'simple', 'current'\n"
@@ -7043,9 +7043,9 @@ msgid ""
"See the 'Note about fast-forwards' in 'git push --help' for details."
msgstr ""
"Aktualisierungen wurden zurückgewiesen, weil die Spitze eines versendeten\n"
-"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Checke diesen\n"
-"Zweig aus und führe die externen Änderungen zusammen (z.B. 'git pull')\n"
-"bevor du erneut versendest.\n"
+"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Checken Sie\n"
+"diesen Zweig aus und führen Sie die externen Änderungen zusammen\n"
+"(z.B. 'git pull') bevor Sie erneut versenden.\n"
"Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n"
"für weitere Details."
@@ -7077,12 +7077,12 @@ msgid ""
" git push <name>\n"
msgstr ""
"Kein Ziel zum Versenden konfiguriert.\n"
-"Entweder spezifizierst du die URL von der Kommandozeile oder konfigurierst "
+"Entweder spezifizieren Sie die URL von der Kommandozeile oder konfigurieren "
"ein externes Projektarchiv unter Benutzung von\n"
"\n"
" git remote add <Name> <URL>\n"
"\n"
-"und versendest dann unter Benutzung dieses Namens\n"
+"und versenden dann unter Benutzung dieses Namens\n"
"\n"
" git push <Name>\n"
@@ -7331,7 +7331,7 @@ msgid ""
"\t use --mirror=fetch or --mirror=push instead"
msgstr ""
"--mirror ist gefährlich und veraltet; bitte\n"
-"\t benutze stattdessen --mirror=fetch oder --mirror=push"
+"\t benutzen Sie stattdessen --mirror=fetch oder --mirror=push"
#: builtin/remote.c:147
#, c-format
@@ -7440,7 +7440,7 @@ msgstr ""
"Keine Aktualisierung der nicht standardmäßigen Referenzspezifikation zum "
"Abholen\n"
"\t%s\n"
-"\tBitte aktualisiere, falls notwendig, die Konfiguration manuell."
+"\tBitte aktualisieren Sie, falls notwendig, die Konfiguration manuell."
#: builtin/remote.c:683
#, c-format
@@ -7477,11 +7477,11 @@ msgid_plural ""
msgstr[0] ""
"Hinweis: Ein Zweig außerhalb der /refs/remotes/ Hierachie wurde nicht "
"gelöscht;\n"
-"um diesen zu löschen, benutze:"
+"um diesen zu löschen, benutzen Sie:"
msgstr[1] ""
"Hinweis: Einige Zweige außer der /refs/remotes/ Hierarchie wurden nicht "
"entfernt;\n"
-"um diese zu entfernen, benutze:"
+"um diese zu entfernen, benutzen Sie:"
#: builtin/remote.c:943
#, c-format
@@ -7494,7 +7494,7 @@ msgstr " gefolgt"
#: builtin/remote.c:948
msgid " stale (use 'git remote prune' to remove)"
-msgstr " veraltet (benutze 'git remote prune' zum Löschen)"
+msgstr " veraltet (benutzen Sie 'git remote prune' zum Löschen)"
#: builtin/remote.c:950
msgid " ???"
@@ -7647,8 +7647,8 @@ msgstr "Kann Hauptzweig des externen Projektarchivs nicht bestimmen"
#: builtin/remote.c:1218
msgid "Multiple remote HEAD branches. Please choose one explicitly with:"
msgstr ""
-"Mehrere Hauptzweige im externen Projektarchiv. Bitte wähle explizit einen "
-"aus mit:"
+"Mehrere Hauptzweige im externen Projektarchiv. Bitte wählen Sie explizit "
+"einen aus mit:"
#: builtin/remote.c:1228
#, c-format
@@ -7814,7 +7814,7 @@ msgstr "keep"
#: builtin/reset.c:77
msgid "You do not have a valid HEAD."
-msgstr "Du hast keine gültige Zweigspitze (HEAD)."
+msgstr "Sie haben keine gültige Zweigspitze (HEAD)."
#: builtin/reset.c:79
msgid "Failed to find tree of HEAD."
@@ -7881,7 +7881,8 @@ msgstr "--patch ist inkompatibel mit --{hard,mixed,soft}"
#: builtin/reset.c:317
msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
msgstr ""
-"--mixed mit Pfaden ist veraltet; benutze stattdessen 'git reset -- <Pfade>'."
+"--mixed mit Pfaden ist veraltet; benutzen Sie stattdessen "
+"'git reset -- <Pfade>'."
#: builtin/reset.c:319
#, c-format
@@ -7922,7 +7923,7 @@ msgstr ""
" oder: git rev-parse --sq-quote [<Argumente>...]\n"
" oder: git rev-parse [Optionen] [<Argumente>...]\n"
"\n"
-"Führe \"git rev-parse --parseopt -h\" für weitere Informationen bei erster "
+"Führen Sie \"git rev-parse --parseopt -h\" für weitere Informationen bei erster "
"Verwendung aus."
#: builtin/revert.c:22
@@ -8025,8 +8026,8 @@ msgid ""
"(use 'rm -rf' if you really want to remove it including all of its history)"
msgstr ""
"Unterprojekt '%s' (oder ein geschachteltes Unterprojekt hiervon) verwendet\n"
-"ein .git-Verzeichnis (benutze 'rm -rf' wenn du dieses wirklich mitsamt\n"
-"seiner Historie löschen möchtest)"
+"ein .git-Verzeichnis (benutzen Sie 'rm -rf' wenn Sie dieses wirklich mitsamt\n"
+"seiner Historie löschen möchten)"
#: builtin/rm.c:174
#, c-format
@@ -8035,7 +8036,7 @@ msgid ""
"(use -f to force removal)"
msgstr ""
"'%s' hat bereitgestellten Inhalt unterschiedlich zu der Datei und der\n"
-"Zweigspitze (HEAD) (benutze -f um die Entfernung zu erzwingen)"
+"Zweigspitze (HEAD) (benutzen Sie -f um die Entfernung zu erzwingen)"
#: builtin/rm.c:180
#, c-format
@@ -8044,7 +8045,7 @@ msgid ""
"(use --cached to keep the file, or -f to force removal)"
msgstr ""
"'%s' hat Änderungen in der Bereitstellung\n"
-"(benutze --cached um die Datei zu behalten, oder -f um die Entfernung zu "
+"(benutzen Sie --cached um die Datei zu behalten, oder -f um die Entfernung zu "
"erzwingen)"
#: builtin/rm.c:191
@@ -8054,7 +8055,7 @@ msgid ""
"(use --cached to keep the file, or -f to force removal)"
msgstr ""
"'%s' hat lokale Modifikationen\n"
-"(benutze --cached um die Datei zu behalten, oder -f um die Entfernung zu "
+"(benutzen Sie --cached um die Datei zu behalten, oder -f um die Entfernung zu "
"erzwingen)"
#: builtin/rm.c:207
@@ -8334,7 +8335,7 @@ msgid ""
msgstr ""
"\n"
"#\n"
-"# Gebe eine Markierungsbeschreibung ein\n"
+"# Geben Sie eine Markierungsbeschreibung ein.\n"
"# Zeilen, die mit '#' beginnen, werden ignoriert.\n"
"#\n"
@@ -8349,9 +8350,9 @@ msgid ""
msgstr ""
"\n"
"#\n"
-"# Gebe eine Markierungsbeschreibung ein\n"
-"# Zeilen, die mit '#' beginnen, werden behalten; du darfst diese\n"
-"# selbst entfernen wenn du möchtest.\n"
+"# Geben Sie eine Markierungsbeschreibung ein.\n"
+"# Zeilen, die mit '#' beginnen, werden behalten; Sie dürfen diese\n"
+"# selbst entfernen wenn Sie möchten.\n"
"#\n"
#: builtin/tag.c:298
@@ -8790,14 +8791,14 @@ msgstr ""
#: git-am.sh:50
msgid "You need to set your committer info first"
-msgstr "Du musst zuerst die Informationen des Eintragenden setzen."
+msgstr "Sie müssen zuerst die Informationen des Eintragenden setzen."
#: git-am.sh:95
msgid ""
"You seem to have moved HEAD since the last 'am' failure.\n"
"Not rewinding to ORIG_HEAD"
msgstr ""
-"Du scheinst seit dem letzten gescheiterten 'am' die Zweigspitze (HEAD)\n"
+"Sie scheinen seit dem letzten gescheiterten 'am' die Zweigspitze (HEAD)\n"
"geändert zu haben.\n"
"Keine Zurücksetzung zu ORIG_HEAD."
@@ -8808,12 +8809,11 @@ msgid ""
"If you prefer to skip this patch, run \"$cmdline --skip\" instead.\n"
"To restore the original branch and stop patching, run \"$cmdline --abort\"."
msgstr ""
-"Wenn du das Problem gelöst hast, führe \"$cmdline --resolved\" aus.\n"
-"Falls du diesen Patch auslassen möchtest, führe stattdessen \"$cmdline --skip"
-"\" aus.\n"
-"Um den ursprünglichen Zweig wiederherzustellen und die Anwendung der "
-"Patches\n"
-"abzubrechen, führe \"$cmdline --abort\" aus."
+"Wenn Sie das Problem gelöst haben, führen Sie \"$cmdline --resolved\" aus.\n"
+"Falls Sie diesen Patch auslassen möchten, führen Sie stattdessen\n"
+"\"$cmdline --skip\" aus.\n"
+"Um den ursprünglichen Zweig wiederherzustellen und die Anwendung der\n"
+"Patches abzubrechen, führen Sie \"$cmdline --abort\" aus."
#: git-am.sh:121
msgid "Cannot fall back to three-way merge."
@@ -8836,7 +8836,7 @@ msgid ""
"Did you hand edit your patch?\n"
"It does not apply to blobs recorded in its index."
msgstr ""
-"Hast du den Patch per Hand editiert?\n"
+"Haben Sie den Patch per Hand editiert?\n"
"Er kann nicht auf die Blobs in seiner 'index' Zeile angewendet werden."
#: git-am.sh:163
@@ -8877,7 +8877,7 @@ msgstr ""
#: git-am.sh:482
msgid "Please make up your mind. --skip or --abort?"
-msgstr "Bitte werde dir klar. --skip oder --abort?"
+msgstr "Bitte werden Sie sich klar. --skip oder --abort?"
#: git-am.sh:509
msgid "Resolve operation not in progress, we are not resuming."
@@ -8897,11 +8897,11 @@ msgid ""
"To restore the original branch and stop patching run \"$cmdline --abort\"."
msgstr ""
"Patch ist leer. Wurde er falsch aufgeteilt?\n"
-"Wenn du diesen Patch auslassen möchtest, führe stattdessen \"$cmdline --skip"
-"\" aus.\n"
+"Wenn Sie diesen Patch auslassen möchten, führen Sie stattdessen\n"
+"\"$cmdline --skip\" aus.\n"
"Um den ursprünglichen Zweig wiederherzustellen und die Anwendung der "
"Patches\n"
-"abzubrechen, führe \"$cmdline --abort\" aus."
+"abzubrechen, führen Sie \"$cmdline --abort\" aus."
#: git-am.sh:706
msgid "Patch does not have a valid e-mail address."
@@ -8935,9 +8935,9 @@ msgid ""
"If there is nothing left to stage, chances are that something else\n"
"already introduced the same changes; you might want to skip this patch."
msgstr ""
-"Keine Änderungen - hast du vergessen 'git add' zu benutzen?\n"
+"Keine Änderungen - haben Sie vergessen 'git add' zu benutzen?\n"
"Wenn keine Änderungen mehr zum Bereitstellen vorhanden sind, könnten\n"
-"diese bereits anderweitig eingefügt worden sein; du könntest diesen Patch\n"
+"diese bereits anderweitig eingefügt worden sein; Sie könnten diesen Patch\n"
"auslassen."
#: git-am.sh:829
@@ -8945,8 +8945,8 @@ msgid ""
"You still have unmerged paths in your index\n"
"did you forget to use 'git add'?"
msgstr ""
-"Du hast immer noch nicht zusammengeführte Pfade in der Bereitstellung.\n"
-"Hast du vergessen 'git add' zu benutzen?"
+"Sie haben immer noch nicht zusammengeführte Pfade in der Bereitstellung.\n"
+"Haben Sie vergessen 'git add' zu benutzen?"
#: git-am.sh:845
msgid "No changes -- Patch already applied."
@@ -8972,14 +8972,14 @@ msgstr "wende zu leerer Historie an"
#: git-bisect.sh:48
msgid "You need to start by \"git bisect start\""
-msgstr "Du musst mit \"git bisect start\" beginnen."
+msgstr "Sie müssen mit \"git bisect start\" beginnen."
#. TRANSLATORS: Make sure to include [Y] and [n] in your
#. translation. The program will only accept English input
#. at this point.
#: git-bisect.sh:54
msgid "Do you want me to do it for you [Y/n]? "
-msgstr "Willst du, dass ich es für dich mache [Y/n]? "
+msgstr "Wollen Sie, dass ich es für Sie mache [Y/n]? "
#: git-bisect.sh:95
#, sh-format
@@ -9000,7 +9000,7 @@ msgstr "Ungültige Zweigspitze (HEAD) - Zweigspitze (HEAD) wird benötigt"
msgid ""
"Checking out '$start_head' failed. Try 'git bisect reset <validbranch>'."
msgstr ""
-"Auschecken von '$start_head' fehlgeschlagen. Versuche 'git bisect reset "
+"Auschecken von '$start_head' fehlgeschlagen. Versuchen Sie 'git bisect reset "
"<gueltigerzweig>'."
#: git-bisect.sh:140
@@ -9023,7 +9023,7 @@ msgstr "Ungültige Referenz-Eingabe: $arg"
#: git-bisect.sh:232
msgid "Please call 'bisect_state' with at least one argument."
-msgstr "Bitte rufe 'bisect_state' mit mindestens einem Argument auf."
+msgstr "Bitte rufen Sie 'bisect_state' mit mindestens einem Argument auf."
#: git-bisect.sh:244
#, sh-format
@@ -9045,15 +9045,15 @@ msgstr "Warnung: halbiere nur mit einer fehlerhaften Version"
#. at this point.
#: git-bisect.sh:279
msgid "Are you sure [Y/n]? "
-msgstr "Bist du sicher [Y/n]? "
+msgstr "Sind Sie sicher [Y/n]? "
#: git-bisect.sh:289
msgid ""
"You need to give me at least one good and one bad revisions.\n"
"(You can use \"git bisect bad\" and \"git bisect good\" for that.)"
msgstr ""
-"Du musst mindestens eine korrekte und eine fehlerhafte Version angeben.\n"
-"(Du kannst dafür \"git bisect bad\" und \"git bisect good\" benutzen.)"
+"Sie müssen mindestens eine korrekte und eine fehlerhafte Version angeben.\n"
+"(Sie können dafür \"git bisect bad\" und \"git bisect good\" benutzen.)"
#: git-bisect.sh:292
msgid ""
@@ -9061,10 +9061,10 @@ msgid ""
"You then need to give me at least one good and one bad revisions.\n"
"(You can use \"git bisect bad\" and \"git bisect good\" for that.)"
msgstr ""
-"Du musst mit \"git bisect start\" beginnen.\n"
-"Danach musst du mindestens eine korrekte und eine fehlerhafte Version "
+"Sie müssen mit \"git bisect start\" beginnen.\n"
+"Danach müssen Sie mindestens eine korrekte und eine fehlerhafte Version "
"angeben.\n"
-"(Du kannst dafür \"git bisect bad\" und \"git bisect good\" benutzen.)"
+"(Sie können dafür \"git bisect bad\" und \"git bisect good\" benutzen.)"
#: git-bisect.sh:347 git-bisect.sh:474
msgid "We are not bisecting."
@@ -9082,7 +9082,7 @@ msgid ""
"Try 'git bisect reset <commit>'."
msgstr ""
"Konnte die ursprüngliche Zweigspitze (HEAD) '$branch' nicht auschecken.\n"
-"Versuche 'git bisect reset <Version>'."
+"Versuchen Sie 'git bisect reset <Version>'."
#: git-bisect.sh:390
msgid "No logfile given"
@@ -9095,7 +9095,7 @@ msgstr "kann $file nicht für das Abspielen lesen"
#: git-bisect.sh:408
msgid "?? what are you talking about?"
-msgstr "?? Was redest du da?"
+msgstr "?? Was reden Sie da?"
#: git-bisect.sh:420
#, sh-format
@@ -9134,14 +9134,14 @@ msgid ""
"Please, fix them up in the work tree, and then use 'git add/rm <file>'\n"
"as appropriate to mark resolution, or use 'git commit -a'."
msgstr ""
-"\"pull\" ist nicht möglich, weil du nicht zusammengeführte Dateien hast.\n"
-"Bitte korrigiere dies im Arbeitsbaum und benutze dann 'git add/rm <Datei>'\n"
-"um die Auflösung entsprechend zu markieren, oder benutze 'git commit -a'."
+"\"pull\" ist nicht möglich, weil Sie nicht zusammengeführte Dateien haben.\n"
+"Bitte korrigieren Sie dies im Arbeitsbaum und benutzen Sie dann 'git add/rm <Datei>'\n"
+"um die Auflösung entsprechend zu markieren, oder benutzen Sie 'git commit -a'."
#: git-pull.sh:25
msgid "Pull is not possible because you have unmerged files."
msgstr ""
-"\"pull\" ist nicht möglich, weil du nicht zusammengeführte Dateien hast."
+"\"pull\" ist nicht möglich, weil Sie nicht zusammengeführte Dateien haben."
#: git-pull.sh:197
msgid "updating an unborn branch with changes added to the index"
@@ -9161,7 +9161,7 @@ msgid ""
"Warning: commit $orig_head."
msgstr ""
"Warnung: Die Anforderung aktualisierte die Spitze des aktuellen Zweiges.\n"
-"Warnung: Spule deinen Arbeitszweig von Version $orig_head vor."
+"Warnung: Spule Ihren Arbeitszweig von Version $orig_head vor."
#: git-pull.sh:254
msgid "Cannot merge multiple branches into empty head"
@@ -9178,12 +9178,12 @@ msgid ""
"To check out the original branch and stop rebasing, run \"git rebase --abort"
"\"."
msgstr ""
-"Wenn du das Problem aufgelöst hast, führe \"git rebase --continue\" aus.\n"
-"Falls du diesen Patch auslassen möchtest, führe stattdessen \"git rebase --"
+"Wenn Sie das Problem aufgelöst haben, führen Sie \"git rebase --continue\" aus.\n"
+"Falls Sie diesen Patch auslassen möchten, führen Sie stattdessen \"git rebase --"
"skip\" aus.\n"
"Um den ursprünglichen Zweig wiederherzustellen und den Neuaufbau "
"abzubrechen,\n"
-"führe \"git rebase --abort\" aus."
+"führen Sie \"git rebase --abort\" aus."
#: git-rebase.sh:160
msgid "The pre-rebase hook refused to rebase."
@@ -9215,7 +9215,7 @@ msgid ""
"You must edit all merge conflicts and then\n"
"mark them as resolved using git add"
msgstr ""
-"Du musst alle Zusammenführungskonflikte editieren und diese dann\n"
+"Sie müssen alle Zusammenführungskonflikte editieren und diese dann\n"
"mittels \"git add\" als aufgelöst markieren"
#: git-rebase.sh:340
@@ -9237,11 +9237,11 @@ msgid ""
msgstr ""
"Es sieht so aus, als ob es das Verzeichnis $state_dir_base bereits gibt\n"
"und es könnte ein anderer Neuaufbau im Gange sein. Wenn das der Fall ist,\n"
-"probiere bitte\n"
+"probieren Sie bitte\n"
"\t$cmd_live_rebase\n"
-"Wenn das nicht der Fall ist, probiere bitte\n"
+"Wenn das nicht der Fall ist, probieren Sie bitte\n"
"\t$cmd_clear_stale_rebase\n"
-"und führe dieses Kommando nochmal aus. Es wird angehalten, falls noch\n"
+"und führen Sie dieses Kommando nochmal aus. Es wird angehalten, falls noch\n"
"etwas Schützenswertes vorhanden ist."
#: git-rebase.sh:404
@@ -9271,7 +9271,7 @@ msgstr "fatal: Zweig $branch_name nicht gefunden"
#: git-rebase.sh:483
msgid "Please commit or stash them."
-msgstr "Bitte trage die Änderungen ein oder benutze \"stash\"."
+msgstr "Bitte tragen Sie die Änderungen ein oder benutzen Sie \"stash\"."
#: git-rebase.sh:501
#, sh-format
@@ -9293,7 +9293,7 @@ msgstr "Änderungen von $mb zu $onto:"
#: git-rebase.sh:524
msgid "First, rewinding head to replay your work on top of it..."
msgstr ""
-"Zunächst wird die Zweigspitze zurückgespult, um deine Änderungen\n"
+"Zunächst wird die Zweigspitze zurückgespult, um Ihre Änderungen\n"
"darauf neu anzuwenden..."
#: git-rebase.sh:532
@@ -9307,7 +9307,7 @@ msgstr "git stash clear mit Parametern ist nicht implementiert"
#: git-stash.sh:74
msgid "You do not have the initial commit yet"
-msgstr "Du hast bisher noch keine initiale Version"
+msgstr "Sie haben bisher noch keine initiale Version"
#: git-stash.sh:89
msgid "Cannot save the current index state"
@@ -9346,7 +9346,7 @@ msgid ""
" To provide a message, use git stash save -- '$option'"
msgstr ""
"Fehler: unbekannte Option für 'stash save': $option\n"
-" Um eine Beschreibung anzugeben, benutze \"git stash save -- "
+" Um eine Beschreibung anzugeben, benutzen Sie \"git stash save -- "
"'$option'\""
#: git-stash.sh:223
@@ -9400,7 +9400,7 @@ msgstr ""
#: git-stash.sh:424
msgid "Conflicts in index. Try without --index."
-msgstr "Konflikte in der Bereitstellung. Versuche es ohne --index."
+msgstr "Konflikte in der Bereitstellung. Versuchen Sie es ohne --index."
#: git-stash.sh:426
msgid "Could not save index tree"
@@ -9430,7 +9430,7 @@ msgstr "Kein Zweigname spezifiziert"
#: git-stash.sh:571
msgid "(To restore them type \"git stash apply\")"
-msgstr "(Zur Wiederherstellung gebe \"git stash apply\" ein)"
+msgstr "(Zur Wiederherstellung geben Sie \"git stash apply\" ein)"
#: git-submodule.sh:89
#, sh-format
@@ -9471,9 +9471,9 @@ msgid ""
"$sm_path\n"
"Use -f if you really want to add it."
msgstr ""
-"Der folgende Pfad wird durch eine deiner \".gitignore\" Dateien ignoriert:\n"
+"Der folgende Pfad wird durch eine Ihrer \".gitignore\" Dateien ignoriert:\n"
"$sm_path\n"
-"Benutze -f wenn du diesen wirklich hinzufügen möchtest."
+"Benutzen Sie -f wenn Sie diesen wirklich hinzufügen möchten."
#: git-submodule.sh:355
#, sh-format
@@ -9497,7 +9497,7 @@ msgstr "Ein Git-Verzeichnis für '$sm_name' wurde lokal gefunden mit den "
msgid ""
"If you want to reuse this local git directory instead of cloning again from"
msgstr ""
-"Wenn du dieses lokale Git-Verzeichnis wiederverwenden möchtest, anstatt "
+"Wenn Sie dieses lokale Git-Verzeichnis wiederverwenden möchtest, anstatt "
"erneut zu klonen"
#: git-submodule.sh:369
@@ -9505,7 +9505,7 @@ msgstr ""
msgid ""
"use the '--force' option. If the local git directory is not the correct repo"
msgstr ""
-"benutze die Option '--force'. Wenn das lokale Git-Verzeichnis nicht das "
+"benutzen Sie die Option '--force'. Wenn das lokale Git-Verzeichnis nicht das "
"korrekte Projektarchiv ist"
#: git-submodule.sh:370
@@ -9514,8 +9514,8 @@ msgid ""
"or you are unsure what this means choose another name with the '--name' "
"option."
msgstr ""
-"oder du dir unsicher bist, was das bedeutet, wähle einen anderen Namen mit "
-"der Option '--name'."
+"oder Sie sich unsicher sind, was das bedeutet, wählen Sie einen anderen Namen"
+"mit der Option '--name'."
#: git-submodule.sh:372
#, sh-format
@@ -9576,7 +9576,7 @@ msgid ""
"Maybe you want to use 'update --init'?"
msgstr ""
"Unterprojekt-Pfad '$sm_path' ist nicht initialisiert\n"
-"Vielleicht möchtest du 'update --init' benutzen?"
+"Vielleicht möchten Sie 'update --init' benutzen?"
#: git-submodule.sh:627
#, sh-format
diff --git a/pretty.c b/pretty.c
index 91bb2d3ef6..07fc062865 100644
--- a/pretty.c
+++ b/pretty.c
@@ -387,56 +387,79 @@ void pp_user_info(const struct pretty_print_context *pp,
const char *what, struct strbuf *sb,
const char *line, const char *encoding)
{
+ struct strbuf name;
+ struct strbuf mail;
+ struct ident_split ident;
+ int linelen;
+ char *line_end, *date;
+ const char *mailbuf, *namebuf;
+ size_t namelen, maillen;
int max_length = 78; /* per rfc2822 */
- char *date;
- int namelen;
unsigned long time;
int tz;
if (pp->fmt == CMIT_FMT_ONELINE)
return;
- date = strchr(line, '>');
- if (!date)
+
+ line_end = strchr(line, '\n');
+ if (!line_end) {
+ line_end = strchr(line, '\0');
+ if (!line_end)
+ return;
+ }
+
+ linelen = ++line_end - line;
+ if (split_ident_line(&ident, line, linelen))
return;
- namelen = ++date - line;
- time = strtoul(date, &date, 10);
+
+
+ mailbuf = ident.mail_begin;
+ maillen = ident.mail_end - ident.mail_begin;
+ namebuf = ident.name_begin;
+ namelen = ident.name_end - ident.name_begin;
+
+ if (pp->mailmap)
+ map_user(pp->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
+
+ strbuf_init(&mail, 0);
+ strbuf_init(&name, 0);
+
+ strbuf_add(&mail, mailbuf, maillen);
+ strbuf_add(&name, namebuf, namelen);
+
+ namelen = name.len + mail.len + 3; /* ' ' + '<' + '>' */
+ time = strtoul(ident.date_begin, &date, 10);
tz = strtol(date, NULL, 10);
if (pp->fmt == CMIT_FMT_EMAIL) {
- char *name_tail = strchr(line, '<');
- int display_name_length;
- if (!name_tail)
- return;
- while (line < name_tail && isspace(name_tail[-1]))
- name_tail--;
- display_name_length = name_tail - line;
strbuf_addstr(sb, "From: ");
- if (needs_rfc2047_encoding(line, display_name_length, RFC2047_ADDRESS)) {
- add_rfc2047(sb, line, display_name_length,
- encoding, RFC2047_ADDRESS);
+ if (needs_rfc2047_encoding(name.buf, name.len, RFC2047_ADDRESS)) {
+ add_rfc2047(sb, name.buf, name.len,
+ encoding, RFC2047_ADDRESS);
max_length = 76; /* per rfc2047 */
- } else if (needs_rfc822_quoting(line, display_name_length)) {
+ } else if (needs_rfc822_quoting(name.buf, name.len)) {
struct strbuf quoted = STRBUF_INIT;
- add_rfc822_quoted(&quoted, line, display_name_length);
+ add_rfc822_quoted(&quoted, name.buf, name.len);
strbuf_add_wrapped_bytes(sb, quoted.buf, quoted.len,
-6, 1, max_length);
strbuf_release(&quoted);
} else {
- strbuf_add_wrapped_bytes(sb, line, display_name_length,
- -6, 1, max_length);
+ strbuf_add_wrapped_bytes(sb, name.buf, name.len,
+ -6, 1, max_length);
}
- if (namelen - display_name_length + last_line_length(sb) > max_length) {
+ if (namelen - name.len + last_line_length(sb) > max_length)
strbuf_addch(sb, '\n');
- if (!isspace(name_tail[0]))
- strbuf_addch(sb, ' ');
- }
- strbuf_add(sb, name_tail, namelen - display_name_length);
- strbuf_addch(sb, '\n');
+
+ strbuf_addf(sb, " <%s>\n", mail.buf);
} else {
- strbuf_addf(sb, "%s: %.*s%.*s\n", what,
+ strbuf_addf(sb, "%s: %.*s%s <%s>\n", what,
(pp->fmt == CMIT_FMT_FULLER) ? 4 : 0,
- " ", namelen, line);
+ " ", name.buf, mail.buf);
}
+
+ strbuf_release(&mail);
+ strbuf_release(&name);
+
switch (pp->fmt) {
case CMIT_FMT_MEDIUM:
strbuf_addf(sb, "Date: %s\n", show_date(time, tz, pp->date_mode));
@@ -586,7 +609,8 @@ char *logmsg_reencode(const struct commit *commit,
return out;
}
-static int mailmap_name(char *email, int email_len, char *name, int name_len)
+static int mailmap_name(const char **email, size_t *email_len,
+ const char **name, size_t *name_len)
{
static struct string_list *mail_map;
if (!mail_map) {
@@ -603,36 +627,26 @@ static size_t format_person_part(struct strbuf *sb, char part,
const int placeholder_len = 2;
int tz;
unsigned long date = 0;
- char person_name[1024];
- char person_mail[1024];
struct ident_split s;
- const char *name_start, *name_end, *mail_start, *mail_end;
+ const char *name, *mail;
+ size_t maillen, namelen;
if (split_ident_line(&s, msg, len) < 0)
goto skip;
- name_start = s.name_begin;
- name_end = s.name_end;
- mail_start = s.mail_begin;
- mail_end = s.mail_end;
-
- if (part == 'N' || part == 'E') { /* mailmap lookup */
- snprintf(person_name, sizeof(person_name), "%.*s",
- (int)(name_end - name_start), name_start);
- snprintf(person_mail, sizeof(person_mail), "%.*s",
- (int)(mail_end - mail_start), mail_start);
- mailmap_name(person_mail, sizeof(person_mail), person_name, sizeof(person_name));
- name_start = person_name;
- name_end = name_start + strlen(person_name);
- mail_start = person_mail;
- mail_end = mail_start + strlen(person_mail);
- }
+ name = s.name_begin;
+ namelen = s.name_end - s.name_begin;
+ mail = s.mail_begin;
+ maillen = s.mail_end - s.mail_begin;
+
+ if (part == 'N' || part == 'E') /* mailmap lookup */
+ mailmap_name(&mail, &maillen, &name, &namelen);
if (part == 'n' || part == 'N') { /* name */
- strbuf_add(sb, name_start, name_end-name_start);
+ strbuf_add(sb, name, namelen);
return placeholder_len;
}
if (part == 'e' || part == 'E') { /* email */
- strbuf_add(sb, mail_start, mail_end-mail_start);
+ strbuf_add(sb, mail, maillen);
return placeholder_len;
}
@@ -960,12 +974,19 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
switch (placeholder[0]) {
case 'C':
if (placeholder[1] == '(') {
- const char *end = strchr(placeholder + 2, ')');
+ const char *begin = placeholder + 2;
+ const char *end = strchr(begin, ')');
char color[COLOR_MAXLEN];
+
if (!end)
return 0;
- color_parse_mem(placeholder + 2,
- end - (placeholder + 2),
+ if (!prefixcmp(begin, "auto,")) {
+ if (!want_color(c->pretty_ctx->color))
+ return end - placeholder + 1;
+ begin += 5;
+ }
+ color_parse_mem(begin,
+ end - begin,
"--pretty format", color);
strbuf_addstr(sb, color);
return end - placeholder + 1;
@@ -1294,7 +1315,7 @@ static void pp_header(const struct pretty_print_context *pp,
continue;
}
- if (!memcmp(line, "parent ", 7)) {
+ if (!prefixcmp(line, "parent ")) {
if (linelen != 48)
die("bad parent line in commit");
continue;
@@ -1318,11 +1339,11 @@ static void pp_header(const struct pretty_print_context *pp,
* FULL shows both authors but not dates.
* FULLER shows both authors and dates.
*/
- if (!memcmp(line, "author ", 7)) {
+ if (!prefixcmp(line, "author ")) {
strbuf_grow(sb, linelen + 80);
pp_user_info(pp, "Author", sb, line + 7, encoding);
}
- if (!memcmp(line, "committer ", 10) &&
+ if (!prefixcmp(line, "committer ") &&
(pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {
strbuf_grow(sb, linelen + 80);
pp_user_info(pp, "Commit", sb, line + 10, encoding);
diff --git a/remote.c b/remote.c
index ca1f8f2eaf..4b1153f02c 100644
--- a/remote.c
+++ b/remote.c
@@ -1279,12 +1279,34 @@ int match_push_refs(struct ref *src, struct ref **dst,
return 0;
}
+static inline int is_forwardable(struct ref* ref)
+{
+ struct object *o;
+
+ if (!prefixcmp(ref->name, "refs/tags/"))
+ return 0;
+
+ /* old object must be a commit */
+ o = parse_object(ref->old_sha1);
+ if (!o || o->type != OBJ_COMMIT)
+ return 0;
+
+ /* new object must be commit-ish */
+ o = deref_tag(parse_object(ref->new_sha1), NULL, 0);
+ if (!o || o->type != OBJ_COMMIT)
+ return 0;
+
+ return 1;
+}
+
void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
int force_update)
{
struct ref *ref;
for (ref = remote_refs; ref; ref = ref->next) {
+ int force_ref_update = ref->force || force_update;
+
if (ref->peer_ref)
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
else if (!send_mirror)
@@ -1297,34 +1319,55 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
continue;
}
- /* This part determines what can overwrite what.
- * The rules are:
+ /*
+ * The below logic determines whether an individual
+ * refspec A:B can be pushed. The push will succeed
+ * if any of the following are true:
*
- * (0) you can always use --force or +A:B notation to
- * selectively force individual ref pairs.
+ * (1) the remote reference B does not exist
*
- * (1) if the old thing does not exist, it is OK.
+ * (2) the remote reference B is being removed (i.e.,
+ * pushing :B where no source is specified)
*
- * (2) if you do not have the old thing, you are not allowed
- * to overwrite it; you would not know what you are losing
- * otherwise.
+ * (3) the update meets all fast-forwarding criteria:
*
- * (3) if both new and old are commit-ish, and new is a
- * descendant of old, it is OK.
+ * (a) the destination is not under refs/tags/
+ * (b) the old is a commit
+ * (c) the new is a descendant of the old
*
- * (4) regardless of all of the above, removing :B is
- * always allowed.
+ * NOTE: We must actually have the old object in
+ * order to overwrite it in the remote reference,
+ * and the new object must be commit-ish. These are
+ * implied by (b) and (c) respectively.
+ *
+ * (4) it is forced using the +A:B notation, or by
+ * passing the --force argument
*/
- ref->nonfastforward =
- !ref->deletion &&
- !is_null_sha1(ref->old_sha1) &&
- (!has_sha1_file(ref->old_sha1)
- || !ref_newer(ref->new_sha1, ref->old_sha1));
+ ref->not_forwardable = !is_forwardable(ref);
- if (ref->nonfastforward && !ref->force && !force_update) {
- ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
- continue;
+ ref->update =
+ !ref->deletion &&
+ !is_null_sha1(ref->old_sha1);
+
+ if (ref->update) {
+ ref->nonfastforward =
+ !has_sha1_file(ref->old_sha1)
+ || !ref_newer(ref->new_sha1, ref->old_sha1);
+
+ if (ref->not_forwardable) {
+ ref->requires_force = 1;
+ if (!force_ref_update) {
+ ref->status = REF_STATUS_REJECT_ALREADY_EXISTS;
+ continue;
+ }
+ } else if (ref->nonfastforward) {
+ ref->requires_force = 1;
+ if (!force_ref_update) {
+ ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
+ continue;
+ }
+ }
}
}
}
diff --git a/revision.c b/revision.c
index 95d21e6472..d7562ee500 100644
--- a/revision.c
+++ b/revision.c
@@ -13,6 +13,7 @@
#include "decorate.h"
#include "log-tree.h"
#include "string-list.h"
+#include "mailmap.h"
volatile show_early_output_fn_t show_early_output;
@@ -2219,6 +2220,51 @@ static int rewrite_parents(struct rev_info *revs, struct commit *commit)
return 0;
}
+static int commit_rewrite_person(struct strbuf *buf, const char *what, struct string_list *mailmap)
+{
+ char *person, *endp;
+ size_t len, namelen, maillen;
+ const char *name;
+ const char *mail;
+ struct ident_split ident;
+
+ person = strstr(buf->buf, what);
+ if (!person)
+ return 0;
+
+ person += strlen(what);
+ endp = strchr(person, '\n');
+ if (!endp)
+ return 0;
+
+ len = endp - person;
+
+ if (split_ident_line(&ident, person, len))
+ return 0;
+
+ mail = ident.mail_begin;
+ maillen = ident.mail_end - ident.mail_begin;
+ name = ident.name_begin;
+ namelen = ident.name_end - ident.name_begin;
+
+ if (map_user(mailmap, &mail, &maillen, &name, &namelen)) {
+ struct strbuf namemail = STRBUF_INIT;
+
+ strbuf_addf(&namemail, "%.*s <%.*s>",
+ (int)namelen, name, (int)maillen, mail);
+
+ strbuf_splice(buf, ident.name_begin - buf->buf,
+ ident.mail_end - ident.name_begin + 1,
+ namemail.buf, namemail.len);
+
+ strbuf_release(&namemail);
+
+ return 1;
+ }
+
+ return 0;
+}
+
static int commit_match(struct commit *commit, struct rev_info *opt)
{
int retval;
@@ -2237,6 +2283,14 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
if (buf.len)
strbuf_addstr(&buf, commit->buffer);
+ if (opt->grep_filter.header_list && opt->mailmap) {
+ if (!buf.len)
+ strbuf_addstr(&buf, commit->buffer);
+
+ commit_rewrite_person(&buf, "\nauthor ", opt->mailmap);
+ commit_rewrite_person(&buf, "\ncommitter ", opt->mailmap);
+ }
+
/* Append "fake" message parts as needed */
if (opt->show_notes) {
if (!buf.len)
diff --git a/revision.h b/revision.h
index 059bfff812..5da09ee3ef 100644
--- a/revision.h
+++ b/revision.h
@@ -135,6 +135,7 @@ struct rev_info {
const char *mime_boundary;
const char *patch_suffix;
int numbered_files;
+ int reroll_count;
char *message_id;
struct string_list *ref_message_ids;
const char *add_signoff;
@@ -143,6 +144,7 @@ struct rev_info {
const char *subject_prefix;
int no_inline;
int show_log_size;
+ struct string_list *mailmap;
/* Filter by commit log message */
struct grep_opt grep_filter;
diff --git a/send-pack.c b/send-pack.c
index f50dfd9f48..1c375f0a28 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -229,6 +229,7 @@ int send_pack(struct send_pack_args *args,
/* Check for statuses set by set_ref_status_for_push() */
switch (ref->status) {
case REF_STATUS_REJECT_NONFASTFORWARD:
+ case REF_STATUS_REJECT_ALREADY_EXISTS:
case REF_STATUS_UPTODATE:
continue;
default:
diff --git a/sequencer.c b/sequencer.c
index 22604902aa..aef5e8a017 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -186,14 +186,15 @@ static int error_dirty_index(struct replay_opts *opts)
return -1;
}
-static int fast_forward_to(const unsigned char *to, const unsigned char *from)
+static int fast_forward_to(const unsigned char *to, const unsigned char *from,
+ int unborn)
{
struct ref_lock *ref_lock;
read_cache();
if (checkout_fast_forward(from, to, 1))
exit(1); /* the callee should have complained already */
- ref_lock = lock_any_ref_for_update("HEAD", from, 0);
+ ref_lock = lock_any_ref_for_update("HEAD", unborn ? null_sha1 : from, 0);
return write_ref_sha1(ref_lock, to, "cherry-pick");
}
@@ -390,7 +391,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
struct commit_message msg = { NULL, NULL, NULL, NULL, NULL };
char *defmsg = NULL;
struct strbuf msgbuf = STRBUF_INIT;
- int res;
+ int res, unborn = 0;
if (opts->no_commit) {
/*
@@ -402,9 +403,10 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
if (write_cache_as_tree(head, 0, NULL))
die (_("Your index file is unmerged."));
} else {
- if (get_sha1("HEAD", head))
- return error(_("You do not have a valid HEAD"));
- if (index_differs_from("HEAD", 0))
+ unborn = get_sha1("HEAD", head);
+ if (unborn)
+ hashcpy(head, EMPTY_TREE_SHA1_BIN);
+ if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0))
return error_dirty_index(opts);
}
discard_cache();
@@ -435,8 +437,10 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
else
parent = commit->parents->item;
- if (opts->allow_ff && parent && !hashcmp(parent->object.sha1, head))
- return fast_forward_to(commit->object.sha1, head);
+ if (opts->allow_ff &&
+ ((parent && !hashcmp(parent->object.sha1, head)) ||
+ (!parent && unborn)))
+ return fast_forward_to(commit->object.sha1, head, unborn);
if (parent && parse_commit(parent) < 0)
/* TRANSLATORS: The first %s will be "revert" or
diff --git a/setup.c b/setup.c
index 3a1b2fd455..f108c4b990 100644
--- a/setup.c
+++ b/setup.c
@@ -1,5 +1,6 @@
#include "cache.h"
#include "dir.h"
+#include "string-list.h"
static int inside_git_dir = -1;
static int inside_work_tree = -1;
@@ -621,16 +622,38 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_
}
/*
+ * A "string_list_each_func_t" function that canonicalizes an entry
+ * from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or
+ * discards it if unusable.
+ */
+static int canonicalize_ceiling_entry(struct string_list_item *item,
+ void *unused)
+{
+ char *ceil = item->string;
+ const char *real_path;
+
+ if (!*ceil || !is_absolute_path(ceil))
+ return 0;
+ real_path = real_path_if_valid(ceil);
+ if (!real_path)
+ return 0;
+ free(item->string);
+ item->string = xstrdup(real_path);
+ return 1;
+}
+
+/*
* We cannot decide in this function whether we are in the work tree or
* not, since the config can only be read _after_ this function was called.
*/
static const char *setup_git_directory_gently_1(int *nongit_ok)
{
const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
+ struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
static char cwd[PATH_MAX+1];
const char *gitdirenv, *ret;
char *gitfile;
- int len, offset, offset_parent, ceil_offset;
+ int len, offset, offset_parent, ceil_offset = -1;
dev_t current_device = 0;
int one_filesystem = 1;
@@ -655,7 +678,14 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
if (gitdirenv)
return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
- ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
+ if (env_ceiling_dirs) {
+ string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
+ filter_string_list(&ceiling_dirs, 0,
+ canonicalize_ceiling_entry, NULL);
+ ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs);
+ string_list_clear(&ceiling_dirs, 0);
+ }
+
if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
ceil_offset = 1;
diff --git a/strbuf.c b/strbuf.c
index 05d0693eba..9a373bef70 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -425,6 +425,32 @@ void strbuf_add_lines(struct strbuf *out, const char *prefix,
strbuf_complete_line(out);
}
+void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s)
+{
+ while (*s) {
+ size_t len = strcspn(s, "\"<>&");
+ strbuf_add(buf, s, len);
+ s += len;
+ switch (*s) {
+ case '"':
+ strbuf_addstr(buf, "&quot;");
+ break;
+ case '<':
+ strbuf_addstr(buf, "&lt;");
+ break;
+ case '>':
+ strbuf_addstr(buf, "&gt;");
+ break;
+ case '&':
+ strbuf_addstr(buf, "&amp;");
+ break;
+ case 0:
+ return;
+ }
+ s++;
+ }
+}
+
static int is_rfc3986_reserved(char ch)
{
switch (ch) {
diff --git a/strbuf.h b/strbuf.h
index aa386c6074..ecae4e215f 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -136,6 +136,12 @@ extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);
extern void strbuf_add_lines(struct strbuf *sb, const char *prefix, const char *buf, size_t size);
+/*
+ * Append s to sb, with the characters '<', '>', '&' and '"' converted
+ * into XML entities.
+ */
+extern void strbuf_addstr_xml_quoted(struct strbuf *sb, const char *s);
+
static inline void strbuf_complete_line(struct strbuf *sb)
{
if (sb->len && sb->buf[sb->len - 1] != '\n')
diff --git a/string-list.c b/string-list.c
index 397e6cfa7d..aabb25ef4c 100644
--- a/string-list.c
+++ b/string-list.c
@@ -7,10 +7,11 @@ static int get_entry_index(const struct string_list *list, const char *string,
int *exact_match)
{
int left = -1, right = list->nr;
+ compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
while (left + 1 < right) {
int middle = (left + right) / 2;
- int compare = strcmp(string, list->items[middle].string);
+ int compare = cmp(string, list->items[middle].string);
if (compare < 0)
right = middle;
else if (compare > 0)
@@ -96,8 +97,9 @@ void string_list_remove_duplicates(struct string_list *list, int free_util)
{
if (list->nr > 1) {
int src, dst;
+ compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
for (src = dst = 1; src < list->nr; src++) {
- if (!strcmp(list->items[dst - 1].string, list->items[src].string)) {
+ if (!cmp(list->items[dst - 1].string, list->items[src].string)) {
if (list->strdup_strings)
free(list->items[src].string);
if (free_util)
@@ -145,26 +147,6 @@ void string_list_remove_empty_items(struct string_list *list, int free_util) {
filter_string_list(list, free_util, item_is_not_empty, NULL);
}
-char *string_list_longest_prefix(const struct string_list *prefixes,
- const char *string)
-{
- int i, max_len = -1;
- char *retval = NULL;
-
- for (i = 0; i < prefixes->nr; i++) {
- char *prefix = prefixes->items[i].string;
- if (!prefixcmp(string, prefix)) {
- int len = strlen(prefix);
- if (len > max_len) {
- retval = prefix;
- max_len = len;
- }
- }
- }
-
- return retval;
-}
-
void string_list_clear(struct string_list *list, int free_util)
{
if (list->items) {
@@ -230,15 +212,20 @@ struct string_list_item *string_list_append(struct string_list *list,
list->strdup_strings ? xstrdup(string) : (char *)string);
}
+/* Yuck */
+static compare_strings_fn compare_for_qsort;
+
+/* Only call this from inside sort_string_list! */
static int cmp_items(const void *a, const void *b)
{
const struct string_list_item *one = a;
const struct string_list_item *two = b;
- return strcmp(one->string, two->string);
+ return compare_for_qsort(one->string, two->string);
}
void sort_string_list(struct string_list *list)
{
+ compare_for_qsort = list->cmp ? list->cmp : strcmp;
qsort(list->items, list->nr, sizeof(*list->items), cmp_items);
}
@@ -246,8 +233,10 @@ struct string_list_item *unsorted_string_list_lookup(struct string_list *list,
const char *string)
{
int i;
+ compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
+
for (i = 0; i < list->nr; i++)
- if (!strcmp(string, list->items[i].string))
+ if (!cmp(string, list->items[i].string))
return list->items + i;
return NULL;
}
diff --git a/string-list.h b/string-list.h
index c50b0d0dea..de6769c92d 100644
--- a/string-list.h
+++ b/string-list.h
@@ -5,10 +5,14 @@ struct string_list_item {
char *string;
void *util;
};
+
+typedef int (*compare_strings_fn)(const char *, const char *);
+
struct string_list {
struct string_list_item *items;
unsigned int nr, alloc;
unsigned int strdup_strings:1;
+ compare_strings_fn cmp; /* NULL uses strcmp() */
};
#define STRING_LIST_INIT_NODUP { NULL, 0, 0, 0 }
@@ -45,15 +49,6 @@ void filter_string_list(struct string_list *list, int free_util,
*/
void string_list_remove_empty_items(struct string_list *list, int free_util);
-/*
- * Return the longest string in prefixes that is a prefix (in the
- * sense of prefixcmp()) of string, or NULL if no such prefix exists.
- * This function does not require the string_list to be sorted (it
- * does a linear search).
- */
-char *string_list_longest_prefix(const struct string_list *prefixes, const char *string);
-
-
/* Use these functions only on sorted lists: */
int string_list_has_string(const struct string_list *list, const char *string);
int string_list_find_insert_index(const struct string_list *list, const char *string,
diff --git a/t/Makefile b/t/Makefile
index 5c6de8169b..1923cc104b 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -17,6 +17,7 @@ TEST_LINT ?= test-lint-duplicates test-lint-executable
# Shell quote;
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
+PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh))
@@ -44,7 +45,7 @@ clean-except-prove-cache:
clean: clean-except-prove-cache
$(RM) .prove
-test-lint: test-lint-duplicates test-lint-executable
+test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax
test-lint-duplicates:
@dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
@@ -56,6 +57,9 @@ test-lint-executable:
test -z "$$bad" || { \
echo >&2 "non-executable tests:" $$bad; exit 1; }
+test-lint-shell-syntax:
+ @'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T)
+
aggregate-results-and-cleanup: $(T)
$(MAKE) aggregate-results
$(MAKE) clean
@@ -88,7 +92,7 @@ test-results:
mkdir -p test-results
test-results/git-smoke.tar.gz: test-results
- $(PERL_PATH) ./harness \
+ '$(PERL_PATH_SQ)' ./harness \
--archive="test-results/git-smoke.tar.gz" \
$(T)
diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl
new file mode 100755
index 0000000000..8b5a71dc05
--- /dev/null
+++ b/t/check-non-portable-shell.pl
@@ -0,0 +1,27 @@
+#!/usr/bin/perl
+
+# Test t0000..t9999.sh for non portable shell scripts
+# This script can be called with one or more filenames as parameters
+
+use strict;
+use warnings;
+
+my $exit_code=0;
+
+sub err {
+ my $msg = shift;
+ print "$ARGV:$.: error: $msg: $_\n";
+ $exit_code = 1;
+}
+
+while (<>) {
+ chomp;
+ /^\s*sed\s+-i/ and err 'sed -i is not portable';
+ /^\s*echo\s+-n/ and err 'echo -n is not portable (please use printf)';
+ /^\s*declare\s+/ and err 'arrays/declare not portable';
+ /^\s*[^#]\s*which\s/ and err 'which is not portable (please use type)';
+ /test\s+[^=]*==/ and err '"test a == b" is not portable (please use =)';
+ # this resets our $. for each file
+ close ARGV if eof;
+}
+exit $exit_code;
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 562cf41cad..cefe33d6d1 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -45,39 +45,176 @@ test_expect_failure 'pretend we have a known breakage' '
false
'
-test_expect_success 'pretend we have fixed a known breakage (run in sub test-lib)' "
- mkdir passing-todo &&
- (cd passing-todo &&
- cat >passing-todo.sh <<-EOF &&
- #!$SHELL_PATH
-
- test_description='A passing TODO test
+run_sub_test_lib_test () {
+ name="$1" descr="$2" # stdin is the body of the test code
+ mkdir "$name" &&
+ (
+ cd "$name" &&
+ cat >"$name.sh" <<-EOF &&
+ #!$SHELL_PATH
+
+ test_description='$descr (run in sub test-lib)
+
+ This is run in a sub test-lib so that we do not get incorrect
+ passing metrics
+ '
+
+ # Point to the t/test-lib.sh, which isn't in ../ as usual
+ . "\$TEST_DIRECTORY"/test-lib.sh
+ EOF
+ cat >>"$name.sh" &&
+ chmod +x "$name.sh" &&
+ export TEST_DIRECTORY &&
+ ./"$name.sh" >out 2>err
+ )
+}
- This is run in a sub test-lib so that we do not get incorrect
- passing metrics
- '
+check_sub_test_lib_test () {
+ name="$1" # stdin is the expected output from the test
+ (
+ cd "$name" &&
+ ! test -s err &&
+ sed -e 's/^> //' -e 's/Z$//' >expect &&
+ test_cmp expect out
+ )
+}
+
+test_expect_success 'pretend we have a fully passing test suite' "
+ run_sub_test_lib_test full-pass '3 passing tests' <<-\\EOF &&
+ for i in 1 2 3
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test full-pass <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 - passing test #2
+ > ok 3 - passing test #3
+ > # passed all 3 test(s)
+ > 1..3
+ EOF
+"
- # Point to the t/test-lib.sh, which isn't in ../ as usual
- TEST_DIRECTORY=\"$TEST_DIRECTORY\"
- . \"\$TEST_DIRECTORY\"/test-lib.sh
+test_expect_success 'pretend we have a partially passing test suite' "
+ test_must_fail run_sub_test_lib_test \
+ partial-pass '2/3 tests passing' <<-\\EOF &&
+ test_expect_success 'passing test #1' 'true'
+ test_expect_success 'failing test #2' 'false'
+ test_expect_success 'passing test #3' 'true'
+ test_done
+ EOF
+ check_sub_test_lib_test partial-pass <<-\\EOF
+ > ok 1 - passing test #1
+ > not ok 2 - failing test #2
+ # false
+ > ok 3 - passing test #3
+ > # failed 1 among 3 test(s)
+ > 1..3
+ EOF
+"
- test_expect_failure 'pretend we have fixed a known breakage' '
- :
- '
+test_expect_success 'pretend we have a known breakage' "
+ run_sub_test_lib_test failing-todo 'A failing TODO test' <<-\\EOF &&
+ test_expect_success 'passing test' 'true'
+ test_expect_failure 'pretend we have a known breakage' 'false'
+ test_done
+ EOF
+ check_sub_test_lib_test failing-todo <<-\\EOF
+ > ok 1 - passing test
+ > not ok 2 - pretend we have a known breakage # TODO known breakage
+ > # still have 1 known breakage(s)
+ > # passed all remaining 1 test(s)
+ > 1..2
+ EOF
+"
+test_expect_success 'pretend we have fixed a known breakage' "
+ run_sub_test_lib_test passing-todo 'A passing TODO test' <<-\\EOF &&
+ test_expect_failure 'pretend we have fixed a known breakage' 'true'
test_done
EOF
- chmod +x passing-todo.sh &&
- ./passing-todo.sh >out 2>err &&
- ! test -s err &&
- sed -e 's/^> //' >expect <<-\\EOF &&
- > ok 1 - pretend we have fixed a known breakage # TODO known breakage
- > # fixed 1 known breakage(s)
- > # passed all 1 test(s)
+ check_sub_test_lib_test passing-todo <<-\\EOF
+ > ok 1 - pretend we have fixed a known breakage # TODO known breakage vanished
+ > # 1 known breakage(s) vanished; please update test(s)
> 1..1
EOF
- test_cmp expect out)
"
+
+test_expect_success 'pretend we have fixed one of two known breakages (run in sub test-lib)' "
+ run_sub_test_lib_test partially-passing-todos \
+ '2 TODO tests, one passing' <<-\\EOF &&
+ test_expect_failure 'pretend we have a known breakage' 'false'
+ test_expect_success 'pretend we have a passing test' 'true'
+ test_expect_failure 'pretend we have fixed another known breakage' 'true'
+ test_done
+ EOF
+ check_sub_test_lib_test partially-passing-todos <<-\\EOF
+ > not ok 1 - pretend we have a known breakage # TODO known breakage
+ > ok 2 - pretend we have a passing test
+ > ok 3 - pretend we have fixed another known breakage # TODO known breakage vanished
+ > # 1 known breakage(s) vanished; please update test(s)
+ > # still have 1 known breakage(s)
+ > # passed all remaining 1 test(s)
+ > 1..3
+ EOF
+"
+
+test_expect_success 'pretend we have a pass, fail, and known breakage' "
+ test_must_fail run_sub_test_lib_test \
+ mixed-results1 'mixed results #1' <<-\\EOF &&
+ test_expect_success 'passing test' 'true'
+ test_expect_success 'failing test' 'false'
+ test_expect_failure 'pretend we have a known breakage' 'false'
+ test_done
+ EOF
+ check_sub_test_lib_test mixed-results1 <<-\\EOF
+ > ok 1 - passing test
+ > not ok 2 - failing test
+ > # false
+ > not ok 3 - pretend we have a known breakage # TODO known breakage
+ > # still have 1 known breakage(s)
+ > # failed 1 among remaining 2 test(s)
+ > 1..3
+ EOF
+"
+
+test_expect_success 'pretend we have a mix of all possible results' "
+ test_must_fail run_sub_test_lib_test \
+ mixed-results2 'mixed results #2' <<-\\EOF &&
+ test_expect_success 'passing test' 'true'
+ test_expect_success 'passing test' 'true'
+ test_expect_success 'passing test' 'true'
+ test_expect_success 'passing test' 'true'
+ test_expect_success 'failing test' 'false'
+ test_expect_success 'failing test' 'false'
+ test_expect_success 'failing test' 'false'
+ test_expect_failure 'pretend we have a known breakage' 'false'
+ test_expect_failure 'pretend we have a known breakage' 'false'
+ test_expect_failure 'pretend we have fixed a known breakage' 'true'
+ test_done
+ EOF
+ check_sub_test_lib_test mixed-results2 <<-\\EOF
+ > ok 1 - passing test
+ > ok 2 - passing test
+ > ok 3 - passing test
+ > ok 4 - passing test
+ > not ok 5 - failing test
+ > # false
+ > not ok 6 - failing test
+ > # false
+ > not ok 7 - failing test
+ > # false
+ > not ok 8 - pretend we have a known breakage # TODO known breakage
+ > not ok 9 - pretend we have a known breakage # TODO known breakage
+ > ok 10 - pretend we have fixed a known breakage # TODO known breakage vanished
+ > # 1 known breakage(s) vanished; please update test(s)
+ > # still have 2 known breakage(s)
+ > # failed 3 among remaining 7 test(s)
+ > 1..10
+ EOF
+"
+
test_set_prereq HAVEIT
haveit=no
test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
@@ -159,19 +296,8 @@ then
fi
test_expect_success 'tests clean up even on failures' "
- mkdir failing-cleanup &&
- (
- cd failing-cleanup &&
-
- cat >failing-cleanup.sh <<-EOF &&
- #!$SHELL_PATH
-
- test_description='Failing tests with cleanup commands'
-
- # Point to the t/test-lib.sh, which isn't in ../ as usual
- TEST_DIRECTORY=\"$TEST_DIRECTORY\"
- . \"\$TEST_DIRECTORY\"/test-lib.sh
-
+ test_must_fail run_sub_test_lib_test \
+ failing-cleanup 'Failing tests with cleanup commands' <<-\\EOF &&
test_expect_success 'tests clean up even after a failure' '
touch clean-after-failure &&
test_when_finished rm clean-after-failure &&
@@ -181,29 +307,21 @@ test_expect_success 'tests clean up even on failures' "
test_when_finished \"(exit 2)\"
'
test_done
-
EOF
-
- chmod +x failing-cleanup.sh &&
- test_must_fail ./failing-cleanup.sh >out 2>err &&
- ! test -s err &&
- ! test -f \"trash directory.failing-cleanup/clean-after-failure\" &&
- sed -e 's/Z$//' -e 's/^> //' >expect <<-\\EOF &&
- > not ok - 1 tests clean up even after a failure
+ check_sub_test_lib_test failing-cleanup <<-\\EOF
+ > not ok 1 - tests clean up even after a failure
> # Z
> # touch clean-after-failure &&
> # test_when_finished rm clean-after-failure &&
> # (exit 1)
> # Z
- > not ok - 2 failure to clean up causes the test to fail
+ > not ok 2 - failure to clean up causes the test to fail
> # Z
> # test_when_finished \"(exit 2)\"
> # Z
> # failed 2 among 2 test(s)
> 1..2
EOF
- test_cmp expect out
- )
"
################################################################
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index 807b8b88e2..43b25137e9 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -206,6 +206,43 @@ test_expect_success 'patterns starting with exclamation' '
attr_check "!f" foo
'
+test_expect_success '"**" test' '
+ echo "**/f foo=bar" >.gitattributes &&
+ cat <<\EOF >expect &&
+f: foo: bar
+a/f: foo: bar
+a/b/f: foo: bar
+a/b/c/f: foo: bar
+EOF
+ git check-attr foo -- "f" >actual 2>err &&
+ git check-attr foo -- "a/f" >>actual 2>>err &&
+ git check-attr foo -- "a/b/f" >>actual 2>>err &&
+ git check-attr foo -- "a/b/c/f" >>actual 2>>err &&
+ test_cmp expect actual &&
+ test_line_count = 0 err
+'
+
+test_expect_success '"**" with no slashes test' '
+ echo "a**f foo=bar" >.gitattributes &&
+ git check-attr foo -- "f" >actual &&
+ cat <<\EOF >expect &&
+f: foo: unspecified
+af: foo: bar
+axf: foo: bar
+a/f: foo: unspecified
+a/b/f: foo: unspecified
+a/b/c/f: foo: unspecified
+EOF
+ git check-attr foo -- "f" >actual 2>err &&
+ git check-attr foo -- "af" >>actual 2>err &&
+ git check-attr foo -- "axf" >>actual 2>err &&
+ git check-attr foo -- "a/f" >>actual 2>>err &&
+ git check-attr foo -- "a/b/f" >>actual 2>>err &&
+ git check-attr foo -- "a/b/c/f" >>actual 2>>err &&
+ test_cmp expect actual &&
+ test_line_count = 0 err
+'
+
test_expect_success 'setup bare' '
git clone --bare . bare.git &&
cd bare.git
diff --git a/t/t0024-crlf-archive.sh b/t/t0024-crlf-archive.sh
index ec6c1b3f8a..5378787e1b 100755
--- a/t/t0024-crlf-archive.sh
+++ b/t/t0024-crlf-archive.sh
@@ -3,7 +3,12 @@
test_description='respect crlf in git archive'
. ./test-lib.sh
-UNZIP=${UNZIP:-unzip}
+GIT_UNZIP=${GIT_UNZIP:-unzip}
+
+test_lazy_prereq UNZIP '
+ "$GIT_UNZIP" -v
+ test $? -ne 127
+'
test_expect_success setup '
@@ -26,18 +31,11 @@ test_expect_success 'tar archive' '
'
-"$UNZIP" -v >/dev/null 2>&1
-if [ $? -eq 127 ]; then
- say "Skipping ZIP test, because unzip was not found"
-else
- test_set_prereq UNZIP
-fi
-
test_expect_success UNZIP 'zip archive' '
git archive --format=zip HEAD >test.zip &&
- ( mkdir unzipped && cd unzipped && unzip ../test.zip ) &&
+ ( mkdir unzipped && cd unzipped && "$GIT_UNZIP" ../test.zip ) &&
test_cmp sample unzipped/sample
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 4ef2345982..09a42a428e 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -93,47 +93,32 @@ norm_path /d1/s1//../s2/../../d2 /d2 POSIX
norm_path /d1/.../d2 /d1/.../d2 POSIX
norm_path /d1/..././../d2 /d1/d2 POSIX
-ancestor / "" -1
ancestor / / -1
-ancestor /foo "" -1
-ancestor /foo : -1
-ancestor /foo ::. -1
-ancestor /foo ::..:: -1
ancestor /foo / 0
ancestor /foo /fo -1
ancestor /foo /foo -1
-ancestor /foo /foo/ -1
ancestor /foo /bar -1
-ancestor /foo /bar/ -1
ancestor /foo /foo/bar -1
-ancestor /foo /foo:/bar/ -1
-ancestor /foo /foo/:/bar/ -1
-ancestor /foo /foo::/bar/ -1
-ancestor /foo /:/foo:/bar/ 0
-ancestor /foo /foo:/:/bar/ 0
-ancestor /foo /:/bar/:/foo 0
-ancestor /foo/bar "" -1
+ancestor /foo /foo:/bar -1
+ancestor /foo /:/foo:/bar 0
+ancestor /foo /foo:/:/bar 0
+ancestor /foo /:/bar:/foo 0
ancestor /foo/bar / 0
ancestor /foo/bar /fo -1
-ancestor /foo/bar foo -1
ancestor /foo/bar /foo 4
-ancestor /foo/bar /foo/ 4
ancestor /foo/bar /foo/ba -1
ancestor /foo/bar /:/fo 0
ancestor /foo/bar /foo:/foo/ba 4
ancestor /foo/bar /bar -1
-ancestor /foo/bar /bar/ -1
-ancestor /foo/bar /fo: -1
-ancestor /foo/bar :/fo -1
-ancestor /foo/bar /foo:/bar/ 4
-ancestor /foo/bar /:/foo:/bar/ 4
-ancestor /foo/bar /foo:/:/bar/ 4
-ancestor /foo/bar /:/bar/:/fo 0
-ancestor /foo/bar /:/bar/ 0
-ancestor /foo/bar .:/foo/. 4
-ancestor /foo/bar .:/foo/.:.: 4
-ancestor /foo/bar /foo/./:.:/bar 4
-ancestor /foo/bar .:/bar -1
+ancestor /foo/bar /fo -1
+ancestor /foo/bar /foo:/bar 4
+ancestor /foo/bar /:/foo:/bar 4
+ancestor /foo/bar /foo:/:/bar 4
+ancestor /foo/bar /:/bar:/fo 0
+ancestor /foo/bar /:/bar 0
+ancestor /foo/bar /foo 4
+ancestor /foo/bar /foo:/bar 4
+ancestor /foo/bar /bar -1
test_expect_success 'strip_path_suffix' '
test c:/msysgit = $(test-path-utils strip_path_suffix \
diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh
index 41c8826a74..dbfc05ebdc 100755
--- a/t/t0063-string-list.sh
+++ b/t/t0063-string-list.sh
@@ -17,14 +17,6 @@ test_split () {
"
}
-test_longest_prefix () {
- test "$(test-string-list longest_prefix "$1" "$2")" = "$3"
-}
-
-test_no_longest_prefix () {
- test_must_fail test-string-list longest_prefix "$1" "$2"
-}
-
test_split "foo:bar:baz" ":" "-1" <<EOF
3
[0]: "foo"
@@ -96,26 +88,4 @@ test_expect_success "test remove_duplicates" '
test a:b:c = "$(test-string-list remove_duplicates a:a:a:b:b:b:c:c:c)"
'
-test_expect_success "test longest_prefix" '
- test_no_longest_prefix - '' &&
- test_no_longest_prefix - x &&
- test_longest_prefix "" x "" &&
- test_longest_prefix x x x &&
- test_longest_prefix "" foo "" &&
- test_longest_prefix : foo "" &&
- test_longest_prefix f foo f &&
- test_longest_prefix foo foobar foo &&
- test_longest_prefix foo foo foo &&
- test_no_longest_prefix bar foo &&
- test_no_longest_prefix bar:bar foo &&
- test_no_longest_prefix foobar foo &&
- test_longest_prefix foo:bar foo foo &&
- test_longest_prefix foo:bar bar bar &&
- test_longest_prefix foo::bar foo foo &&
- test_longest_prefix foo:foobar foo foo &&
- test_longest_prefix foobar:foo foo foo &&
- test_longest_prefix foo: bar "" &&
- test_longest_prefix :foo bar ""
-'
-
test_done
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 08aa24ca15..d730734fde 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -237,4 +237,35 @@ test_expect_success 'fsck notices submodule entry pointing to null sha1' '
)
'
+test_expect_success 'fsck notices "." and ".." in trees' '
+ (
+ git init dots &&
+ cd dots &&
+ blob=$(echo foo | git hash-object -w --stdin) &&
+ tab=$(printf "\\t") &&
+ git mktree <<-EOF &&
+ 100644 blob $blob$tab.
+ 100644 blob $blob$tab..
+ EOF
+ git fsck 2>out &&
+ cat out &&
+ grep "warning.*\\." out
+ )
+'
+
+test_expect_success 'fsck notices ".git" in trees' '
+ (
+ git init dotgit &&
+ cd dotgit &&
+ blob=$(echo foo | git hash-object -w --stdin) &&
+ tab=$(printf "\\t") &&
+ git mktree <<-EOF &&
+ 100644 blob $blob$tab.git
+ EOF
+ git fsck 2>out &&
+ cat out &&
+ grep "warning.*\\.git" out
+ )
+'
+
test_done
diff --git a/t/t1505-rev-parse-last.sh b/t/t1505-rev-parse-last.sh
index d709ecf8df..4969edb314 100755
--- a/t/t1505-rev-parse-last.sh
+++ b/t/t1505-rev-parse-last.sh
@@ -32,32 +32,24 @@ test_expect_success 'setup' '
#
# and 'side' should be the last branch
-test_rev_equivalent () {
-
- git rev-parse "$1" > expect &&
- git rev-parse "$2" > output &&
- test_cmp expect output
-
-}
-
test_expect_success '@{-1} works' '
- test_rev_equivalent side @{-1}
+ test_cmp_rev side @{-1}
'
test_expect_success '@{-1}~2 works' '
- test_rev_equivalent side~2 @{-1}~2
+ test_cmp_rev side~2 @{-1}~2
'
test_expect_success '@{-1}^2 works' '
- test_rev_equivalent side^2 @{-1}^2
+ test_cmp_rev side^2 @{-1}^2
'
test_expect_success '@{-1}@{1} works' '
- test_rev_equivalent side@{1} @{-1}@{1}
+ test_cmp_rev side@{1} @{-1}@{1}
'
test_expect_success '@{-2} works' '
- test_rev_equivalent master @{-2}
+ test_cmp_rev master @{-2}
'
test_expect_success '@{-3} fails' '
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index dc2f0458fd..efb7ebc91f 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -220,4 +220,22 @@ test_expect_success 'pattern matches prefix completely' '
test_cmp expect actual
'
+test_expect_success 'ls-files with "**" patterns' '
+ cat <<\EOF >expect &&
+a.1
+one/a.1
+one/two/a.1
+three/a.1
+EOF
+ git ls-files -o -i --exclude "**/a.1" >actual
+ test_cmp expect actual
+'
+
+
+test_expect_success 'ls-files with "**" patterns and no slashes' '
+ : >expect &&
+ git ls-files -o -i --exclude "one**a.1" >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
new file mode 100755
index 0000000000..af54c83111
--- /dev/null
+++ b/t/t3070-wildmatch.sh
@@ -0,0 +1,195 @@
+#!/bin/sh
+
+test_description='wildmatch tests'
+
+. ./test-lib.sh
+
+match() {
+ if [ $1 = 1 ]; then
+ test_expect_success "wildmatch: match '$3' '$4'" "
+ test-wildmatch wildmatch '$3' '$4'
+ "
+ else
+ test_expect_success "wildmatch: no match '$3' '$4'" "
+ ! test-wildmatch wildmatch '$3' '$4'
+ "
+ fi
+ if [ $2 = 1 ]; then
+ test_expect_success "fnmatch: match '$3' '$4'" "
+ test-wildmatch fnmatch '$3' '$4'
+ "
+ elif [ $2 = 0 ]; then
+ test_expect_success "fnmatch: no match '$3' '$4'" "
+ ! test-wildmatch fnmatch '$3' '$4'
+ "
+# else
+# test_expect_success BROKEN_FNMATCH "fnmatch: '$3' '$4'" "
+# ! test-wildmatch fnmatch '$3' '$4'
+# "
+ fi
+}
+
+# Basic wildmat features
+match 1 1 foo foo
+match 0 0 foo bar
+match 1 1 '' ""
+match 1 1 foo '???'
+match 0 0 foo '??'
+match 1 1 foo '*'
+match 1 1 foo 'f*'
+match 0 0 foo '*f'
+match 1 1 foo '*foo*'
+match 1 1 foobar '*ob*a*r*'
+match 1 1 aaaaaaabababab '*ab'
+match 1 1 'foo*' 'foo\*'
+match 0 0 foobar 'foo\*bar'
+match 1 1 'f\oo' 'f\\oo'
+match 1 1 ball '*[al]?'
+match 0 0 ten '[ten]'
+match 0 1 ten '**[!te]'
+match 0 0 ten '**[!ten]'
+match 1 1 ten 't[a-g]n'
+match 0 0 ten 't[!a-g]n'
+match 1 1 ton 't[!a-g]n'
+match 1 1 ton 't[^a-g]n'
+match 1 x 'a]b' 'a[]]b'
+match 1 x a-b 'a[]-]b'
+match 1 x 'a]b' 'a[]-]b'
+match 0 x aab 'a[]-]b'
+match 1 x aab 'a[]a-]b'
+match 1 1 ']' ']'
+
+# Extended slash-matching features
+match 0 0 'foo/baz/bar' 'foo*bar'
+match 0 0 'foo/baz/bar' 'foo**bar'
+match 0 1 'foobazbar' 'foo**bar'
+match 1 1 'foo/baz/bar' 'foo/**/bar'
+match 1 0 'foo/baz/bar' 'foo/**/**/bar'
+match 1 0 'foo/b/a/z/bar' 'foo/**/bar'
+match 1 0 'foo/b/a/z/bar' 'foo/**/**/bar'
+match 1 0 'foo/bar' 'foo/**/bar'
+match 1 0 'foo/bar' 'foo/**/**/bar'
+match 0 0 'foo/bar' 'foo?bar'
+match 0 0 'foo/bar' 'foo[/]bar'
+match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 0 'foo' '**/foo'
+match 1 x 'XXX/foo' '**/foo'
+match 1 0 'bar/baz/foo' '**/foo'
+match 0 0 'bar/baz/foo' '*/foo'
+match 0 0 'foo/bar/baz' '**/bar*'
+match 1 0 'deep/foo/bar/baz' '**/bar/*'
+match 0 0 'deep/foo/bar/baz/' '**/bar/*'
+match 1 0 'deep/foo/bar/baz/' '**/bar/**'
+match 0 0 'deep/foo/bar' '**/bar/*'
+match 1 0 'deep/foo/bar/' '**/bar/**'
+match 0 0 'foo/bar/baz' '**/bar**'
+match 1 0 'foo/bar/baz/x' '*/bar/**'
+match 0 0 'deep/foo/bar/baz/x' '*/bar/**'
+match 1 0 'deep/foo/bar/baz/x' '**/bar/*/*'
+
+# Various additional tests
+match 0 0 'acrt' 'a[c-c]st'
+match 1 1 'acrt' 'a[c-c]rt'
+match 0 0 ']' '[!]-]'
+match 1 x 'a' '[!]-]'
+match 0 0 '' '\'
+match 0 x '\' '\'
+match 0 x 'XXX/\' '*/\'
+match 1 x 'XXX/\' '*/\\'
+match 1 1 'foo' 'foo'
+match 1 1 '@foo' '@foo'
+match 0 0 'foo' '@foo'
+match 1 1 '[ab]' '\[ab]'
+match 1 1 '[ab]' '[[]ab]'
+match 1 x '[ab]' '[[:]ab]'
+match 0 x '[ab]' '[[::]ab]'
+match 1 x '[ab]' '[[:digit]ab]'
+match 1 x '[ab]' '[\[:]ab]'
+match 1 1 '?a?b' '\??\?b'
+match 1 1 'abc' '\a\b\c'
+match 0 0 'foo' ''
+match 1 0 'foo/bar/baz/to' '**/t[o]'
+
+# Character class tests
+match 1 x 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+match 0 x 'a' '[[:digit:][:upper:][:space:]]'
+match 1 x 'A' '[[:digit:][:upper:][:space:]]'
+match 1 x '1' '[[:digit:][:upper:][:space:]]'
+match 0 x '1' '[[:digit:][:upper:][:spaci:]]'
+match 1 x ' ' '[[:digit:][:upper:][:space:]]'
+match 0 x '.' '[[:digit:][:upper:][:space:]]'
+match 1 x '.' '[[:digit:][:punct:][:space:]]'
+match 1 x '5' '[[:xdigit:]]'
+match 1 x 'f' '[[:xdigit:]]'
+match 1 x 'D' '[[:xdigit:]]'
+match 1 x '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+match 1 x '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+match 1 x '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+match 1 x '5' '[a-c[:digit:]x-z]'
+match 1 x 'b' '[a-c[:digit:]x-z]'
+match 1 x 'y' '[a-c[:digit:]x-z]'
+match 0 x 'q' '[a-c[:digit:]x-z]'
+
+# Additional tests, including some malformed wildmats
+match 1 x ']' '[\\-^]'
+match 0 0 '[' '[\\-^]'
+match 1 x '-' '[\-_]'
+match 1 x ']' '[\]]'
+match 0 0 '\]' '[\]]'
+match 0 0 '\' '[\]]'
+match 0 0 'ab' 'a[]b'
+match 0 x 'a[]b' 'a[]b'
+match 0 x 'ab[' 'ab['
+match 0 0 'ab' '[!'
+match 0 0 'ab' '[-'
+match 1 1 '-' '[-]'
+match 0 0 '-' '[a-'
+match 0 0 '-' '[!a-'
+match 1 x '-' '[--A]'
+match 1 x '5' '[--A]'
+match 1 1 ' ' '[ --]'
+match 1 1 '$' '[ --]'
+match 1 1 '-' '[ --]'
+match 0 0 '0' '[ --]'
+match 1 x '-' '[---]'
+match 1 x '-' '[------]'
+match 0 0 'j' '[a-e-n]'
+match 1 x '-' '[a-e-n]'
+match 1 x 'a' '[!------]'
+match 0 0 '[' '[]-a]'
+match 1 x '^' '[]-a]'
+match 0 0 '^' '[!]-a]'
+match 1 x '[' '[!]-a]'
+match 1 1 '^' '[a^bc]'
+match 1 x '-b]' '[a-]b]'
+match 0 0 '\' '[\]'
+match 1 1 '\' '[\\]'
+match 0 0 '\' '[!\\]'
+match 1 1 'G' '[A-\\]'
+match 0 0 'aaabbb' 'b*a'
+match 0 0 'aabcaa' '*ba*'
+match 1 1 ',' '[,]'
+match 1 1 ',' '[\\,]'
+match 1 1 '\' '[\\,]'
+match 1 1 '-' '[,-.]'
+match 0 0 '+' '[,-.]'
+match 0 0 '-.]' '[,-.]'
+match 1 1 '2' '[\1-\3]'
+match 1 1 '3' '[\1-\3]'
+match 0 0 '4' '[\1-\3]'
+match 1 1 '\' '[[-\]]'
+match 1 1 '[' '[[-\]]'
+match 1 1 ']' '[[-\]]'
+match 0 0 '-' '[[-\]]'
+
+# Test recursion and the abort code (use "wildtest -i" to see iteration counts)
+match 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+
+test_done
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 32fdc9938e..8462be1db6 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -29,12 +29,6 @@ Initial setup:
. "$TEST_DIRECTORY"/lib-rebase.sh
-test_cmp_rev () {
- git rev-parse --verify "$1" >expect.rev &&
- git rev-parse --verify "$2" >actual.rev &&
- test_cmp expect.rev actual.rev
-}
-
set_fake_editor
# WARNING: Modifications to the initial repository can change the SHA ID used
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 34c86e5de6..6f489e20ee 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -100,4 +100,13 @@ test_expect_success 'revert forbidden on dirty working tree' '
'
+test_expect_success 'chery-pick on unborn branch' '
+ git checkout --orphan unborn &&
+ git rm --cached -r . &&
+ rm -rf * &&
+ git cherry-pick initial &&
+ git diff --quiet initial &&
+ ! test_cmp_rev initial HEAD
+'
+
test_done
diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh
index 51ca391e47..373aad623c 100755
--- a/t/t3506-cherry-pick-ff.sh
+++ b/t/t3506-cherry-pick-ff.sh
@@ -105,4 +105,12 @@ test_expect_success 'cherry pick a root commit with --ff' '
test "$(git rev-parse --verify HEAD)" = "1df192cd8bc58a2b275d842cede4d221ad9000d1"
'
+test_expect_success 'chery-pick --ff on unborn branch' '
+ git checkout --orphan unborn &&
+ git rm --cached -r . &&
+ rm -rf * &&
+ git cherry-pick --ff first &&
+ test_cmp_rev first HEAD
+'
+
test_done
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index c82f7210c4..223b98433c 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -11,12 +11,6 @@ test_description='test cherry-pick and revert with conflicts
. ./test-lib.sh
-test_cmp_rev () {
- git rev-parse --verify "$1" >expect.rev &&
- git rev-parse --verify "$2" >actual.rev &&
- test_cmp expect.rev actual.rev
-}
-
pristine_detach () {
git checkout -f "$1^0" &&
git read-tree -u --reset HEAD &&
diff --git a/t/t3508-cherry-pick-many-commits.sh b/t/t3508-cherry-pick-many-commits.sh
index 340afc760d..4e7136b837 100755
--- a/t/t3508-cherry-pick-many-commits.sh
+++ b/t/t3508-cherry-pick-many-commits.sh
@@ -5,15 +5,11 @@ test_description='test cherry-picking many commits'
. ./test-lib.sh
check_head_differs_from() {
- head=$(git rev-parse --verify HEAD) &&
- arg=$(git rev-parse --verify "$1") &&
- test "$head" != "$arg"
+ ! test_cmp_rev HEAD "$1"
}
check_head_equals() {
- head=$(git rev-parse --verify HEAD) &&
- arg=$(git rev-parse --verify "$1") &&
- test "$head" = "$arg"
+ test_cmp_rev HEAD "$1"
}
test_expect_success setup '
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index b5fb527b2e..7b7a89dbd5 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -24,12 +24,6 @@ pristine_detach () {
git clean -d -f -f -q -x
}
-test_cmp_rev () {
- git rev-parse --verify "$1" >expect.rev &&
- git rev-parse --verify "$2" >actual.rev &&
- test_cmp expect.rev actual.rev
-}
-
test_expect_success setup '
git config advice.detachedhead false &&
echo unrelated >unrelated &&
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 90fd598c74..7fa3647514 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -271,6 +271,22 @@ test_expect_success 'multiple files' '
ls patches/0001-Side-changes-1.patch patches/0002-Side-changes-2.patch patches/0003-Side-changes-3-with-n-backslash-n-in-it.patch
'
+test_expect_success 'reroll count' '
+ rm -fr patches &&
+ git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
+ ! grep -v "^patches/v4-000[0-3]-" list &&
+ sed -n -e "/^Subject: /p" $(cat list) >subjects &&
+ ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
+'
+
+test_expect_success 'reroll count (-v)' '
+ rm -fr patches &&
+ git format-patch -o patches --cover-letter -v4 master..side >list &&
+ ! grep -v "^patches/v4-000[0-3]-" list &&
+ sed -n -e "/^Subject: /p" $(cat list) >subjects &&
+ ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
+'
+
check_threading () {
expect="$1" &&
shift &&
@@ -963,4 +979,46 @@ test_expect_success 'format patch ignores color.ui' '
test_cmp expect actual
'
+test_expect_success 'cover letter using branch description (1)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter master >actual &&
+ grep hello actual >/dev/null
+'
+
+test_expect_success 'cover letter using branch description (2)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
+ grep hello actual >/dev/null
+'
+
+test_expect_success 'cover letter using branch description (3)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
+ grep hello actual >/dev/null
+'
+
+test_expect_success 'cover letter using branch description (4)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter master.. >actual &&
+ grep hello actual >/dev/null
+'
+
+test_expect_success 'cover letter using branch description (5)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter -2 HEAD >actual &&
+ grep hello actual >/dev/null
+'
+
+test_expect_success 'cover letter using branch description (6)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter -2 >actual &&
+ grep hello actual >/dev/null
+'
+
test_done
diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh
index 1f182f612c..842b7549ec 100755
--- a/t/t4203-mailmap.sh
+++ b/t/t4203-mailmap.sh
@@ -149,6 +149,104 @@ test_expect_success 'No mailmap files, but configured' '
test_cmp expect actual
'
+test_expect_success 'setup mailmap blob tests' '
+ git checkout -b map &&
+ test_when_finished "git checkout master" &&
+ cat >just-bugs <<-\EOF &&
+ Blob Guy <bugs@company.xx>
+ EOF
+ cat >both <<-\EOF &&
+ Blob Guy <author@example.com>
+ Blob Guy <bugs@company.xx>
+ EOF
+ git add just-bugs both &&
+ git commit -m "my mailmaps" &&
+ echo "Repo Guy <author@example.com>" >.mailmap &&
+ echo "Internal Guy <author@example.com>" >internal.map
+'
+
+test_expect_success 'mailmap.blob set' '
+ cat >expect <<-\EOF &&
+ Blob Guy (1):
+ second
+
+ Repo Guy (1):
+ initial
+
+ EOF
+ git -c mailmap.blob=map:just-bugs shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'mailmap.blob overrides .mailmap' '
+ cat >expect <<-\EOF &&
+ Blob Guy (2):
+ initial
+ second
+
+ EOF
+ git -c mailmap.blob=map:both shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'mailmap.file overrides mailmap.blob' '
+ cat >expect <<-\EOF &&
+ Blob Guy (1):
+ second
+
+ Internal Guy (1):
+ initial
+
+ EOF
+ git \
+ -c mailmap.blob=map:both \
+ -c mailmap.file=internal.map \
+ shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'mailmap.blob can be missing' '
+ cat >expect <<-\EOF &&
+ Repo Guy (1):
+ initial
+
+ nick1 (1):
+ second
+
+ EOF
+ git -c mailmap.blob=map:nonexistent shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'mailmap.blob defaults to off in non-bare repo' '
+ git init non-bare &&
+ (
+ cd non-bare &&
+ test_commit one .mailmap "Fake Name <author@example.com>" &&
+ echo " 1 Fake Name" >expect &&
+ git shortlog -ns HEAD >actual &&
+ test_cmp expect actual &&
+ rm .mailmap &&
+ echo " 1 A U Thor" >expect &&
+ git shortlog -ns HEAD >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'mailmap.blob defaults to HEAD:.mailmap in bare repo' '
+ git clone --bare non-bare bare &&
+ (
+ cd bare &&
+ echo " 1 Fake Name" >expect &&
+ git shortlog -ns HEAD >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'cleanup after mailmap.blob tests' '
+ rm -f .mailmap
+'
+
# Extended mailmap configurations should give us the following output for shortlog
cat >expect <<\EOF
A U Thor <author@example.com> (1):
@@ -239,6 +337,62 @@ test_expect_success 'Log output (complex mapping)' '
test_cmp expect actual
'
+cat >expect <<\EOF
+Author: CTO <cto@company.xx>
+Author: Santa Claus <santa.claus@northpole.xx>
+Author: Santa Claus <santa.claus@northpole.xx>
+Author: Other Author <other@author.xx>
+Author: Other Author <other@author.xx>
+Author: Some Dude <some@dude.xx>
+Author: A U Thor <author@example.com>
+EOF
+
+test_expect_success 'Log output with --use-mailmap' '
+ git log --use-mailmap | grep Author >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<\EOF
+Author: CTO <cto@company.xx>
+Author: Santa Claus <santa.claus@northpole.xx>
+Author: Santa Claus <santa.claus@northpole.xx>
+Author: Other Author <other@author.xx>
+Author: Other Author <other@author.xx>
+Author: Some Dude <some@dude.xx>
+Author: A U Thor <author@example.com>
+EOF
+
+test_expect_success 'Log output with log.mailmap' '
+ git -c log.mailmap=True log | grep Author >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<\EOF
+Author: Santa Claus <santa.claus@northpole.xx>
+Author: Santa Claus <santa.claus@northpole.xx>
+EOF
+
+test_expect_success 'Grep author with --use-mailmap' '
+ git log --use-mailmap --author Santa | grep Author >actual &&
+ test_cmp expect actual
+'
+cat >expect <<\EOF
+Author: Santa Claus <santa.claus@northpole.xx>
+Author: Santa Claus <santa.claus@northpole.xx>
+EOF
+
+test_expect_success 'Grep author with log.mailmap' '
+ git -c log.mailmap=True log --author Santa | grep Author >actual &&
+ test_cmp expect actual
+'
+
+>expect
+
+test_expect_success 'Only grep replaced author with --use-mailmap' '
+ git log --use-mailmap --author "<cto@coompany.xx>" >actual &&
+ test_cmp expect actual
+'
+
# git blame
cat >expect <<\EOF
^OBJI (A U Thor DATE 1) one
diff --git a/t/t4300-merge-tree.sh b/t/t4300-merge-tree.sh
index 46c3fe76d3..d0b2a457b8 100755
--- a/t/t4300-merge-tree.sh
+++ b/t/t4300-merge-tree.sh
@@ -254,4 +254,48 @@ EXPECTED
test_cmp expected actual
'
+test_expect_success 'turn file to tree' '
+ git reset --hard initial &&
+ rm initial-file &&
+ mkdir initial-file &&
+ test_commit "turn-file-to-tree" "initial-file/ONE" "CCC" &&
+ git merge-tree initial initial turn-file-to-tree >actual &&
+ cat >expect <<-\EOF &&
+ added in remote
+ their 100644 43aa4fdec31eb92e1fdc2f0ce6ea9ddb7c32bcf7 initial-file/ONE
+ @@ -0,0 +1 @@
+ +CCC
+ removed in remote
+ base 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file
+ our 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file
+ @@ -1 +0,0 @@
+ -initial
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'turn tree to file' '
+ git reset --hard initial &&
+ mkdir dir &&
+ test_commit "add-tree" "dir/path" "AAA" &&
+ test_commit "add-another-tree" "dir/another" "BBB" &&
+ rm -fr dir &&
+ test_commit "make-file" "dir" "CCC" &&
+ git merge-tree add-tree add-another-tree make-file >actual &&
+ cat >expect <<-\EOF &&
+ added in local
+ our 100644 ba629238ca89489f2b350e196ca445e09d8bb834 dir/another
+ removed in remote
+ base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d dir/path
+ our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d dir/path
+ @@ -1 +0,0 @@
+ -AAA
+ added in remote
+ their 100644 43aa4fdec31eb92e1fdc2f0ce6ea9ddb7c32bcf7 dir
+ @@ -0,0 +1 @@
+ +CCC
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index ecf00edab2..e7c240fc1f 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -25,32 +25,11 @@ commit id embedding:
'
. ./test-lib.sh
-UNZIP=${UNZIP:-unzip}
GZIP=${GZIP:-gzip}
GUNZIP=${GUNZIP:-gzip -d}
SUBSTFORMAT=%H%n
-check_zip() {
- zipfile=$1.zip
- listfile=$1.lst
- dir=$1
- dir_with_prefix=$dir/$2
-
- test_expect_success UNZIP " extract ZIP archive" "
- (mkdir $dir && cd $dir && $UNZIP ../$zipfile)
- "
-
- test_expect_success UNZIP " validate filenames" "
- (cd ${dir_with_prefix}a && find .) | sort >$listfile &&
- test_cmp a.lst $listfile
- "
-
- test_expect_success UNZIP " validate file contents" "
- diff -r a ${dir_with_prefix}a
- "
-}
-
test_expect_success \
'populate workdir' \
'mkdir a b c &&
@@ -201,62 +180,12 @@ test_expect_success \
test_cmp a/substfile2 g/prefix/a/substfile2
'
-$UNZIP -v >/dev/null 2>&1
-if [ $? -eq 127 ]; then
- say "Skipping ZIP tests, because unzip was not found"
-else
- test_set_prereq UNZIP
-fi
-
-test_expect_success \
- 'git archive --format=zip' \
- 'git archive --format=zip HEAD >d.zip'
-
-check_zip d
-
-test_expect_success \
- 'git archive --format=zip in a bare repo' \
- '(cd bare.git && git archive --format=zip HEAD) >d1.zip'
-
-test_expect_success \
- 'git archive --format=zip vs. the same in a bare repo' \
- 'test_cmp d.zip d1.zip'
-
-test_expect_success 'git archive --format=zip with --output' \
- 'git archive --format=zip --output=d2.zip HEAD &&
- test_cmp d.zip d2.zip'
-
-test_expect_success 'git archive with --output, inferring format' '
- git archive --output=d3.zip HEAD &&
- test_cmp d.zip d3.zip
-'
-
test_expect_success 'git archive with --output, override inferred format' '
git archive --format=tar --output=d4.zip HEAD &&
test_cmp b.tar d4.zip
'
test_expect_success \
- 'git archive --format=zip with prefix' \
- 'git archive --format=zip --prefix=prefix/ HEAD >e.zip'
-
-check_zip e prefix/
-
-test_expect_success 'git archive -0 --format=zip on large files' '
- test_config core.bigfilethreshold 1 &&
- git archive -0 --format=zip HEAD >large.zip
-'
-
-check_zip large
-
-test_expect_success 'git archive --format=zip on large files' '
- test_config core.bigfilethreshold 1 &&
- git archive --format=zip HEAD >large-compressed.zip
-'
-
-check_zip large-compressed
-
-test_expect_success \
'git archive --list outside of a git repo' \
'GIT_DIR=some/non-existing/directory git archive --list'
diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh
new file mode 100755
index 0000000000..7cfe9ca3da
--- /dev/null
+++ b/t/t5003-archive-zip.sh
@@ -0,0 +1,131 @@
+#!/bin/sh
+
+test_description='git archive --format=zip test'
+
+. ./test-lib.sh
+GIT_UNZIP=${GIT_UNZIP:-unzip}
+
+SUBSTFORMAT=%H%n
+
+test_lazy_prereq UNZIP '
+ "$GIT_UNZIP" -v
+ test $? -ne 127
+'
+
+test_lazy_prereq UNZIP_SYMLINKS '
+ (
+ mkdir unzip-symlinks &&
+ cd unzip-symlinks &&
+ "$GIT_UNZIP" "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip &&
+ test -h symlink
+ )
+'
+
+check_zip() {
+ zipfile=$1.zip
+ listfile=$1.lst
+ dir=$1
+ dir_with_prefix=$dir/$2
+
+ test_expect_success UNZIP " extract ZIP archive" '
+ (mkdir $dir && cd $dir && "$GIT_UNZIP" ../$zipfile)
+ '
+
+ test_expect_success UNZIP " validate filenames" "
+ (cd ${dir_with_prefix}a && find .) | sort >$listfile &&
+ test_cmp a.lst $listfile
+ "
+
+ test_expect_success UNZIP " validate file contents" "
+ diff -r a ${dir_with_prefix}a
+ "
+}
+
+test_expect_success \
+ 'populate workdir' \
+ 'mkdir a b c &&
+ echo simple textfile >a/a &&
+ mkdir a/bin &&
+ cp /bin/sh a/bin &&
+ printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
+ printf "A not substituted O" >a/substfile2 &&
+ (p=long_path_to_a_file && cd a &&
+ for depth in 1 2 3 4 5; do mkdir $p && cd $p; done &&
+ echo text >file_with_long_path)
+'
+
+test_expect_success SYMLINKS,UNZIP_SYMLINKS 'add symlink' '
+ ln -s a a/symlink_to_a
+'
+
+test_expect_success 'prepare file list' '
+ (cd a && find .) | sort >a.lst
+'
+
+test_expect_success \
+ 'add ignored file' \
+ 'echo ignore me >a/ignored &&
+ echo ignored export-ignore >.git/info/attributes'
+
+test_expect_success \
+ 'add files to repository' \
+ 'find a -type f | xargs git update-index --add &&
+ find a -type l | xargs git update-index --add &&
+ treeid=`git write-tree` &&
+ echo $treeid >treeid &&
+ git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \
+ git commit-tree $treeid </dev/null)'
+
+test_expect_success \
+ 'create bare clone' \
+ 'git clone --bare . bare.git &&
+ cp .git/info/attributes bare.git/info/attributes'
+
+test_expect_success \
+ 'remove ignored file' \
+ 'rm a/ignored'
+
+test_expect_success \
+ 'git archive --format=zip' \
+ 'git archive --format=zip HEAD >d.zip'
+
+check_zip d
+
+test_expect_success \
+ 'git archive --format=zip in a bare repo' \
+ '(cd bare.git && git archive --format=zip HEAD) >d1.zip'
+
+test_expect_success \
+ 'git archive --format=zip vs. the same in a bare repo' \
+ 'test_cmp d.zip d1.zip'
+
+test_expect_success 'git archive --format=zip with --output' \
+ 'git archive --format=zip --output=d2.zip HEAD &&
+ test_cmp d.zip d2.zip'
+
+test_expect_success 'git archive with --output, inferring format' '
+ git archive --output=d3.zip HEAD &&
+ test_cmp d.zip d3.zip
+'
+
+test_expect_success \
+ 'git archive --format=zip with prefix' \
+ 'git archive --format=zip --prefix=prefix/ HEAD >e.zip'
+
+check_zip e prefix/
+
+test_expect_success 'git archive -0 --format=zip on large files' '
+ test_config core.bigfilethreshold 1 &&
+ git archive -0 --format=zip HEAD >large.zip
+'
+
+check_zip large
+
+test_expect_success 'git archive --format=zip on large files' '
+ test_config core.bigfilethreshold 1 &&
+ git archive --format=zip HEAD >large-compressed.zip
+'
+
+check_zip large-compressed
+
+test_done
diff --git a/t/t5003/infozip-symlinks.zip b/t/t5003/infozip-symlinks.zip
new file mode 100644
index 0000000000..065728c631
--- /dev/null
+++ b/t/t5003/infozip-symlinks.zip
Binary files differ
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index b5417cc951..60093728fe 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -368,7 +368,7 @@ test_expect_success 'push with colon-less refspec (2)' '
git branch -D frotz
fi &&
git tag -f frotz &&
- git push testrepo frotz &&
+ git push -f testrepo frotz &&
check_push_result $the_commit tags/frotz &&
check_push_result $the_first_commit heads/frotz
@@ -929,6 +929,48 @@ test_expect_success 'push into aliased refs (inconsistent)' '
)
'
+test_expect_success 'push requires --force to update lightweight tag' '
+ mk_test heads/master &&
+ mk_child child1 &&
+ mk_child child2 &&
+ (
+ cd child1 &&
+ git tag Tag &&
+ git push ../child2 Tag &&
+ git push ../child2 Tag &&
+ >file1 &&
+ git add file1 &&
+ git commit -m "file1" &&
+ git tag -f Tag &&
+ test_must_fail git push ../child2 Tag &&
+ git push --force ../child2 Tag &&
+ git tag -f Tag &&
+ test_must_fail git push ../child2 Tag HEAD~ &&
+ git push --force ../child2 Tag
+ )
+'
+
+test_expect_success 'push requires --force to update annotated tag' '
+ mk_test heads/master &&
+ mk_child child1 &&
+ mk_child child2 &&
+ (
+ cd child1 &&
+ git tag -a -m "message 1" Tag &&
+ git push ../child2 Tag:refs/tmp/Tag &&
+ git push ../child2 Tag:refs/tmp/Tag &&
+ >file1 &&
+ git add file1 &&
+ git commit -m "file1" &&
+ git tag -f -a -m "message 2" Tag &&
+ test_must_fail git push ../child2 Tag:refs/tmp/Tag &&
+ git push --force ../child2 Tag:refs/tmp/Tag &&
+ git tag -f -a -m "message 3" Tag HEAD~ &&
+ test_must_fail git push ../child2 Tag:refs/tmp/Tag &&
+ git push --force ../child2 Tag:refs/tmp/Tag
+ )
+'
+
test_expect_success 'push --porcelain' '
mk_empty &&
echo >.git/foo "To testrepo" &&
diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-testpy.sh
index e7dc668cef..1e683d4220 100755
--- a/t/t5800-remote-helpers.sh
+++ b/t/t5800-remote-testpy.sh
@@ -3,12 +3,12 @@
# Copyright (c) 2010 Sverre Rabbelier
#
-test_description='Test remote-helper import and export commands'
+test_description='Test python remote-helper framework'
. ./test-lib.sh
if ! test_have_prereq PYTHON ; then
- skip_all='skipping git-remote-hg tests, python not available'
+ skip_all='skipping python remote-helper tests, python not available'
test_done
fi
@@ -17,7 +17,7 @@ import sys
if sys.hexversion < 0x02040000:
sys.exit(1)
' || {
- skip_all='skipping git-remote-hg tests, python version < 2.4'
+ skip_all='skipping python remote-helper tests, python version < 2.4'
test_done
}
@@ -38,12 +38,12 @@ test_expect_success 'setup repository' '
'
test_expect_success 'cloning from local repo' '
- git clone "testgit::${PWD}/server" localclone &&
+ git clone "testpy::${PWD}/server" localclone &&
test_cmp public/file localclone/file
'
test_expect_success 'cloning from remote repo' '
- git clone "testgit::file://${PWD}/server" clone &&
+ git clone "testpy::file://${PWD}/server" clone &&
test_cmp public/file clone/file
'
@@ -73,11 +73,11 @@ test_expect_success 'pushing to local repo' '
'
# Generally, skip this test. It demonstrates a now-fixed race in
-# git-remote-testgit, but is too slow to leave in for general use.
+# git-remote-testpy, but is too slow to leave in for general use.
: test_expect_success 'racily pushing to local repo' '
test_when_finished "rm -rf server2 localclone2" &&
cp -R server server2 &&
- git clone "testgit::${PWD}/server2" localclone2 &&
+ git clone "testpy::${PWD}/server2" localclone2 &&
(cd localclone2 &&
echo content >>file &&
git commit -a -m three &&
@@ -145,4 +145,25 @@ test_expect_failure 'push new branch with old:new refspec' '
compare_refs clone HEAD server refs/heads/new-refspec
'
+test_expect_success 'proper failure checks for fetching' '
+ (GIT_REMOTE_TESTGIT_FAILURE=1 &&
+ export GIT_REMOTE_TESTGIT_FAILURE &&
+ cd localclone &&
+ test_must_fail git fetch 2>&1 | \
+ grep "Error while running fast-import"
+ )
+'
+
+# We sleep to give fast-export a chance to catch the SIGPIPE
+test_expect_failure 'proper failure checks for pushing' '
+ (GIT_REMOTE_TESTGIT_FAILURE=1 &&
+ export GIT_REMOTE_TESTGIT_FAILURE &&
+ GIT_REMOTE_TESTGIT_SLEEPY=1 &&
+ export GIT_REMOTE_TESTGIT_SLEEPY &&
+ cd localclone &&
+ test_must_fail git push --all 2>&1 | \
+ grep "Error while running fast-export"
+ )
+'
+
test_done
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
new file mode 100755
index 0000000000..f387027c05
--- /dev/null
+++ b/t/t5801-remote-helpers.sh
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Sverre Rabbelier
+#
+
+test_description='Test remote-helper import and export commands'
+
+. ./test-lib.sh
+
+if ! type "${BASH-bash}" >/dev/null 2>&1; then
+ skip_all='skipping remote-testgit tests, bash not available'
+ test_done
+fi
+
+compare_refs() {
+ git --git-dir="$1/.git" rev-parse --verify $2 >expect &&
+ git --git-dir="$3/.git" rev-parse --verify $4 >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'setup repository' '
+ git init server &&
+ (cd server &&
+ echo content >file &&
+ git add file &&
+ git commit -m one)
+'
+
+test_expect_success 'cloning from local repo' '
+ git clone "testgit::${PWD}/server" local &&
+ test_cmp server/file local/file
+'
+
+test_expect_success 'create new commit on remote' '
+ (cd server &&
+ echo content >>file &&
+ git commit -a -m two)
+'
+
+test_expect_success 'pulling from local repo' '
+ (cd local && git pull) &&
+ test_cmp server/file local/file
+'
+
+test_expect_success 'pushing to local repo' '
+ (cd local &&
+ echo content >>file &&
+ git commit -a -m three &&
+ git push) &&
+ compare_refs local HEAD server HEAD
+'
+
+test_expect_success 'fetch new branch' '
+ (cd server &&
+ git reset --hard &&
+ git checkout -b new &&
+ echo content >>file &&
+ git commit -a -m five
+ ) &&
+ (cd local &&
+ git fetch origin new
+ ) &&
+ compare_refs server HEAD local FETCH_HEAD
+'
+
+test_expect_success 'fetch multiple branches' '
+ (cd local &&
+ git fetch
+ ) &&
+ compare_refs server master local refs/remotes/origin/master &&
+ compare_refs server new local refs/remotes/origin/new
+'
+
+test_expect_success 'push when remote has extra refs' '
+ (cd local &&
+ git reset --hard origin/master &&
+ echo content >>file &&
+ git commit -a -m six &&
+ git push
+ ) &&
+ compare_refs local master server master
+'
+
+test_expect_success 'push new branch by name' '
+ (cd local &&
+ git checkout -b new-name &&
+ echo content >>file &&
+ git commit -a -m seven &&
+ git push origin new-name
+ ) &&
+ compare_refs local HEAD server refs/heads/new-name
+'
+
+test_expect_failure 'push new branch with old:new refspec' '
+ (cd local &&
+ git push origin new-name:new-refspec
+ ) &&
+ compare_refs local HEAD server refs/heads/new-refspec
+'
+
+test_expect_success 'cloning without refspec' '
+ GIT_REMOTE_TESTGIT_REFSPEC="" \
+ git clone "testgit::${PWD}/server" local2 &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'pulling without refspecs' '
+ (cd local2 &&
+ git reset --hard &&
+ GIT_REMOTE_TESTGIT_REFSPEC="" git pull) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_failure 'pushing without refspecs' '
+ test_when_finished "(cd local2 && git reset --hard origin)" &&
+ (cd local2 &&
+ echo content >>file &&
+ git commit -a -m ten &&
+ GIT_REMOTE_TESTGIT_REFSPEC="" git push) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'pulling with straight refspec' '
+ (cd local2 &&
+ GIT_REMOTE_TESTGIT_REFSPEC="*:*" git pull) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_failure 'pushing with straight refspec' '
+ test_when_finished "(cd local2 && git reset --hard origin)" &&
+ (cd local2 &&
+ echo content >>file &&
+ git commit -a -m eleven &&
+ GIT_REMOTE_TESTGIT_REFSPEC="*:*" git push) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'pulling without marks' '
+ (cd local2 &&
+ GIT_REMOTE_TESTGIT_NO_MARKS=1 git pull) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_failure 'pushing without marks' '
+ test_when_finished "(cd local2 && git reset --hard origin)" &&
+ (cd local2 &&
+ echo content >>file &&
+ git commit -a -m twelve &&
+ GIT_REMOTE_TESTGIT_NO_MARKS=1 git push) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'push all with existing object' '
+ (cd local &&
+ git branch dup2 master &&
+ git push origin --all
+ ) &&
+ compare_refs local dup2 server dup2
+'
+
+test_expect_success 'push ref with existing object' '
+ (cd local &&
+ git branch dup master &&
+ git push origin dup
+ ) &&
+ compare_refs local dup server dup
+'
+
+test_done
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index f94f0c48e6..3fc3b74c8e 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -3,6 +3,7 @@
test_description='git rev-list --pretty=format test'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
test_tick
test_expect_success 'setup' '
@@ -11,12 +12,24 @@ touch foo && git add foo && git commit -m "added foo" &&
'
# usage: test_format name format_string <expected_output
-test_format() {
+test_format () {
cat >expect.$1
test_expect_success "format $1" "
-git rev-list --pretty=format:'$2' master >output.$1 &&
-test_cmp expect.$1 output.$1
-"
+ git rev-list --pretty=format:'$2' master >output.$1 &&
+ test_cmp expect.$1 output.$1
+ "
+}
+
+# Feed to --format to provide predictable colored sequences.
+AUTO_COLOR='%C(auto,red)foo%C(auto,reset)'
+has_color () {
+ printf '\033[31mfoo\033[m\n' >expect &&
+ test_cmp expect "$1"
+}
+
+has_no_color () {
+ echo foo >expect &&
+ test_cmp expect "$1"
}
test_format percent %%h <<'EOF'
@@ -124,6 +137,48 @@ commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
foo
EOF
+test_expect_success '%C(auto) does not enable color by default' '
+ git log --format=$AUTO_COLOR -1 >actual &&
+ has_no_color actual
+'
+
+test_expect_success '%C(auto) enables colors for color.diff' '
+ git -c color.diff=always log --format=$AUTO_COLOR -1 >actual &&
+ has_color actual
+'
+
+test_expect_success '%C(auto) enables colors for color.ui' '
+ git -c color.ui=always log --format=$AUTO_COLOR -1 >actual &&
+ has_color actual
+'
+
+test_expect_success '%C(auto) respects --color' '
+ git log --format=$AUTO_COLOR -1 --color >actual &&
+ has_color actual
+'
+
+test_expect_success '%C(auto) respects --no-color' '
+ git -c color.ui=always log --format=$AUTO_COLOR -1 --no-color >actual &&
+ has_no_color actual
+'
+
+test_expect_success TTY '%C(auto) respects --color=auto (stdout is tty)' '
+ (
+ TERM=vt100 && export TERM &&
+ test_terminal \
+ git log --format=$AUTO_COLOR -1 --color=auto >actual &&
+ has_color actual
+ )
+'
+
+test_expect_success '%C(auto) respects --color=auto (stdout not tty)' '
+ (
+ TERM=vt100 && export TERM &&
+ git log --format=$AUTO_COLOR -1 --color=auto >actual &&
+ has_no_color actual
+ )
+'
+
cat >commit-msg <<'EOF'
Test printing of complex bodies
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 72e28ee535..3e0e15fb3e 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -676,9 +676,7 @@ test_expect_success 'bisect fails if tree is broken on trial commit' '
check_same()
{
echo "Checking $1 is the same as $2" &&
- git rev-parse "$1" > expected.same &&
- git rev-parse "$2" > expected.actual &&
- test_cmp expected.same expected.actual
+ test_cmp_rev "$1" "$2"
}
test_expect_success 'bisect: --no-checkout - start commit bad' '
diff --git a/t/t6130-pathspec-noglob.sh b/t/t6130-pathspec-noglob.sh
new file mode 100755
index 0000000000..39ef61994f
--- /dev/null
+++ b/t/t6130-pathspec-noglob.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+test_description='test globbing (and noglob) of pathspec limiting'
+. ./test-lib.sh
+
+test_expect_success 'create commits with glob characters' '
+ test_commit unrelated bar &&
+ test_commit vanilla foo &&
+ # insert file "f*" in the commit, but in a way that avoids
+ # the name "f*" in the worktree, because it is not allowed
+ # on Windows (the tests below do not depend on the presence
+ # of the file in the worktree)
+ git update-index --add --cacheinfo 100644 "$(git rev-parse HEAD:foo)" "f*" &&
+ test_tick &&
+ git commit -m star &&
+ test_commit bracket "f[o][o]"
+'
+
+test_expect_success 'vanilla pathspec matches literally' '
+ echo vanilla >expect &&
+ git log --format=%s -- foo >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'star pathspec globs' '
+ cat >expect <<-\EOF &&
+ bracket
+ star
+ vanilla
+ EOF
+ git log --format=%s -- "f*" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'bracket pathspec globs and matches literal brackets' '
+ cat >expect <<-\EOF &&
+ bracket
+ vanilla
+ EOF
+ git log --format=%s -- "f[o][o]" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'no-glob option matches literally (vanilla)' '
+ echo vanilla >expect &&
+ git --literal-pathspecs log --format=%s -- foo >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'no-glob option matches literally (star)' '
+ echo star >expect &&
+ git --literal-pathspecs log --format=%s -- "f*" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'no-glob option matches literally (bracket)' '
+ echo bracket >expect &&
+ git --literal-pathspecs log --format=%s -- "f[o][o]" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'no-glob environment variable works' '
+ echo star >expect &&
+ GIT_LITERAL_PATHSPECS=1 git log --format=%s -- "f*" >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t7061-wtstatus-ignore.sh b/t/t7061-wtstatus-ignore.sh
new file mode 100755
index 0000000000..0da1214bcc
--- /dev/null
+++ b/t/t7061-wtstatus-ignore.sh
@@ -0,0 +1,146 @@
+#!/bin/sh
+
+test_description='git-status ignored files'
+
+. ./test-lib.sh
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+?? untracked/
+EOF
+
+test_expect_success 'status untracked directory with --ignored' '
+ echo "ignored" >.gitignore &&
+ mkdir untracked &&
+ : >untracked/ignored &&
+ : >untracked/uncommitted &&
+ git status --porcelain --ignored >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+?? untracked/uncommitted
+!! untracked/ignored
+EOF
+
+test_expect_success 'status untracked directory with --ignored -u' '
+ git status --porcelain --ignored -u >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! ignored/
+EOF
+
+test_expect_success 'status ignored directory with --ignore' '
+ rm -rf untracked &&
+ mkdir ignored &&
+ : >ignored/uncommitted &&
+ git status --porcelain --ignored >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! ignored/uncommitted
+EOF
+
+test_expect_success 'status ignored directory with --ignore -u' '
+ git status --porcelain --ignored -u >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! untracked-ignored/
+EOF
+
+test_expect_success 'status untracked directory with ignored files with --ignore' '
+ rm -rf ignored &&
+ mkdir untracked-ignored &&
+ mkdir untracked-ignored/test &&
+ : >untracked-ignored/ignored &&
+ : >untracked-ignored/test/ignored &&
+ git status --porcelain --ignored >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! untracked-ignored/ignored
+!! untracked-ignored/test/ignored
+EOF
+
+test_expect_success 'status untracked directory with ignored files with --ignore -u' '
+ git status --porcelain --ignored -u >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+EOF
+
+test_expect_success 'status ignored tracked directory with --ignore' '
+ rm -rf untracked-ignored &&
+ mkdir tracked &&
+ : >tracked/committed &&
+ git add tracked/committed &&
+ git commit -m. &&
+ echo "tracked" >.gitignore &&
+ git status --porcelain --ignored >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+EOF
+
+test_expect_success 'status ignored tracked directory with --ignore -u' '
+ git status --porcelain --ignored -u >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! tracked/
+EOF
+
+test_expect_success 'status ignored tracked directory and uncommitted file with --ignore' '
+ : >tracked/uncommitted &&
+ git status --porcelain --ignored >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! tracked/uncommitted
+EOF
+
+test_expect_success 'status ignored tracked directory and uncommitted file with --ignore -u' '
+ git status --porcelain --ignored -u >actual &&
+ test_cmp expected actual
+'
+
+test_done
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index de7d45352e..2683cba7e3 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -133,6 +133,7 @@ test_expect_success 'submodule add --branch' '
(
cd addtest &&
git submodule add -b initial "$submodurl" submod-branch &&
+ test "initial" = "$(git config -f .gitmodules submodule.submod-branch.branch)" &&
git submodule init
) &&
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index feaec6cdf4..4975ec07ce 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -135,6 +135,37 @@ test_expect_success 'submodule update --force forcibly checks out submodules' '
)
'
+test_expect_success 'submodule update --remote should fetch upstream changes' '
+ (cd submodule &&
+ echo line4 >> file &&
+ git add file &&
+ test_tick &&
+ git commit -m "upstream line4"
+ ) &&
+ (cd super &&
+ git submodule update --remote --force submodule &&
+ cd submodule &&
+ test "$(git log -1 --oneline)" = "$(GIT_DIR=../../submodule/.git git log -1 --oneline)"
+ )
+'
+
+test_expect_success 'local config should override .gitmodules branch' '
+ (cd submodule &&
+ git checkout -b test-branch &&
+ echo line5 >> file &&
+ git add file &&
+ test_tick &&
+ git commit -m "upstream line5" &&
+ git checkout master
+ ) &&
+ (cd super &&
+ git config submodule.submodule.branch test-branch &&
+ git submodule update --remote --force submodule &&
+ cd submodule &&
+ test "$(git log -1 --oneline)" = "$(GIT_DIR=../../submodule/.git git log -1 --oneline test-branch)"
+ )
+'
+
test_expect_success 'submodule update --rebase staying on master' '
(cd super/submodule &&
git checkout master
diff --git a/t/t7500/add-content-and-comment b/t/t7500/add-content-and-comment
new file mode 100755
index 0000000000..c4dccff13a
--- /dev/null
+++ b/t/t7500/add-content-and-comment
@@ -0,0 +1,5 @@
+#!/bin/sh
+echo "commit message" >> "$1"
+echo "# comment" >> "$1"
+exit 0
+
diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh
index 1a5cb6983c..b1c7648386 100755
--- a/t/t7502-commit.sh
+++ b/t/t7502-commit.sh
@@ -4,6 +4,15 @@ test_description='git commit porcelain-ish'
. ./test-lib.sh
+commit_msg_is () {
+ expect=commit_msg_is.expect
+ actual=commit_msg_is.actual
+
+ printf "%s" "$(git log --pretty=format:%s%b -1)" >$actual &&
+ printf "%s" "$1" >$expect &&
+ test_i18ncmp $expect $actual
+}
+
# Arguments: [<prefix] [<commit message>] [<commit options>]
check_summary_oneline() {
test_tick &&
@@ -168,7 +177,7 @@ test_expect_success 'verbose respects diff config' '
git config --unset color.diff
'
-test_expect_success 'cleanup commit messages (verbatim,-t)' '
+test_expect_success 'cleanup commit messages (verbatim option,-t)' '
echo >>negative &&
{ echo;echo "# text";echo; } >expect &&
@@ -178,7 +187,7 @@ test_expect_success 'cleanup commit messages (verbatim,-t)' '
'
-test_expect_success 'cleanup commit messages (verbatim,-F)' '
+test_expect_success 'cleanup commit messages (verbatim option,-F)' '
echo >>negative &&
git commit --cleanup=verbatim -F expect -a &&
@@ -187,7 +196,7 @@ test_expect_success 'cleanup commit messages (verbatim,-F)' '
'
-test_expect_success 'cleanup commit messages (verbatim,-m)' '
+test_expect_success 'cleanup commit messages (verbatim option,-m)' '
echo >>negative &&
git commit --cleanup=verbatim -m "$(cat expect)" -a &&
@@ -196,7 +205,7 @@ test_expect_success 'cleanup commit messages (verbatim,-m)' '
'
-test_expect_success 'cleanup commit messages (whitespace,-F)' '
+test_expect_success 'cleanup commit messages (whitespace option,-F)' '
echo >>negative &&
{ echo;echo "# text";echo; } >text &&
@@ -207,7 +216,7 @@ test_expect_success 'cleanup commit messages (whitespace,-F)' '
'
-test_expect_success 'cleanup commit messages (strip,-F)' '
+test_expect_success 'cleanup commit messages (strip option,-F)' '
echo >>negative &&
{ echo;echo "# text";echo sample;echo; } >text &&
@@ -218,7 +227,7 @@ test_expect_success 'cleanup commit messages (strip,-F)' '
'
-test_expect_success 'cleanup commit messages (strip,-F,-e)' '
+test_expect_success 'cleanup commit messages (strip option,-F,-e)' '
echo >>negative &&
{ echo;echo sample;echo; } >text &&
@@ -231,10 +240,71 @@ echo "sample
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit." >expect
-test_expect_success 'cleanup commit messages (strip,-F,-e): output' '
+test_expect_success 'cleanup commit messages (strip option,-F,-e): output' '
test_i18ncmp expect actual
'
+test_expect_success 'cleanup commit message (fail on invalid cleanup mode option)' '
+ test_must_fail git commit --cleanup=non-existent
+'
+
+test_expect_success 'cleanup commit message (fail on invalid cleanup mode configuration)' '
+ test_must_fail git -c commit.cleanup=non-existent commit
+'
+
+test_expect_success 'cleanup commit message (no config and no option uses default)' '
+ echo content >>file &&
+ git add file &&
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
+ git commit --no-status &&
+ commit_msg_is "commit message"
+'
+
+test_expect_success 'cleanup commit message (option overrides default)' '
+ echo content >>file &&
+ git add file &&
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
+ git commit --cleanup=whitespace --no-status &&
+ commit_msg_is "commit message # comment"
+'
+
+test_expect_success 'cleanup commit message (config overrides default)' '
+ echo content >>file &&
+ git add file &&
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
+ git -c commit.cleanup=whitespace commit --no-status &&
+ commit_msg_is "commit message # comment"
+'
+
+test_expect_success 'cleanup commit message (option overrides config)' '
+ echo content >>file &&
+ git add file &&
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
+ git -c commit.cleanup=whitespace commit --cleanup=default &&
+ commit_msg_is "commit message"
+'
+
+test_expect_success 'cleanup commit message (default, -m)' '
+ echo content >>file &&
+ git add file &&
+ git commit -m "message #comment " &&
+ commit_msg_is "message #comment"
+'
+
+test_expect_success 'cleanup commit message (whitespace option, -m)' '
+ echo content >>file &&
+ git add file &&
+ git commit --cleanup=whitespace --no-status -m "message #comment " &&
+ commit_msg_is "message #comment"
+'
+
+test_expect_success 'cleanup commit message (whitespace config, -m)' '
+ echo content >>file &&
+ git add file &&
+ git -c commit.cleanup=whitespace commit --no-status -m "message #comment " &&
+ commit_msg_is "message #comment"
+'
+
test_expect_success 'message shows author when it is not equal to committer' '
echo >>negative &&
git commit -e -m "sample" -a &&
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 3e821f958b..9320b4f94c 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -303,7 +303,7 @@ test_expect_success 'dropping tag of filtered out object' '
(
cd limit-by-paths &&
git fast-export --tag-of-filtered-object=drop mytag -- there > output &&
- test_cmp output expected
+ test_cmp expected output
)
'
@@ -320,7 +320,7 @@ test_expect_success 'rewriting tag of filtered out object' '
(
cd limit-by-paths &&
git fast-export --tag-of-filtered-object=rewrite mytag -- there > output &&
- test_cmp output expected
+ test_cmp expected output
)
'
@@ -351,7 +351,7 @@ test_expect_failure 'no exact-ref revisions included' '
(
cd limit-by-paths &&
git fast-export master~2..master~1 > output &&
- test_cmp output expected
+ test_cmp expected output
)
'
@@ -440,4 +440,63 @@ test_expect_success 'fast-export quotes pathnames' '
)
'
+test_expect_success 'test bidirectionality' '
+ >marks-cur &&
+ >marks-new &&
+ git init marks-test &&
+ git fast-export --export-marks=marks-cur --import-marks=marks-cur --branches | \
+ git --git-dir=marks-test/.git fast-import --export-marks=marks-new --import-marks=marks-new &&
+ (cd marks-test &&
+ git reset --hard &&
+ echo Wohlauf > file &&
+ git commit -a -m "back in time") &&
+ git --git-dir=marks-test/.git fast-export --export-marks=marks-new --import-marks=marks-new --branches | \
+ git fast-import --export-marks=marks-cur --import-marks=marks-cur
+'
+
+cat > expected << EOF
+blob
+mark :13
+data 5
+bump
+
+commit refs/heads/master
+mark :14
+author A U Thor <author@example.com> 1112912773 -0700
+committer C O Mitter <committer@example.com> 1112912773 -0700
+data 5
+bump
+from :12
+M 100644 :13 file
+
+EOF
+
+test_expect_success 'avoid uninteresting refs' '
+ > tmp-marks &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks master > /dev/null &&
+ git tag v1.0 &&
+ git branch uninteresting &&
+ echo bump > file &&
+ git commit -a -m bump &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks ^uninteresting ^v1.0 master > actual &&
+ test_cmp expected actual
+'
+
+cat > expected << EOF
+reset refs/heads/master
+from :14
+
+EOF
+
+test_expect_success 'refs are updated even if no commits need to be exported' '
+ > tmp-marks &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks master > /dev/null &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks master > actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 22a4f8fb64..fa62d010f6 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -602,6 +602,13 @@ test_cmp() {
$GIT_TEST_CMP "$@"
}
+# Tests that its two parameters refer to the same revision
+test_cmp_rev () {
+ git rev-parse --verify "$1" >expect.rev &&
+ git rev-parse --verify "$2" >actual.rev &&
+ test_cmp expect.rev actual.rev
+}
+
# Print a sequence of numbers or letters in increasing order. This is
# similar to GNU seq(1), but the latter might not be available
# everywhere (and does not do letters). It may be used like:
diff --git a/t/test-lib.sh b/t/test-lib.sh
index f50f8341d4..1a6c4ab08c 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -85,7 +85,8 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e '
.*_TEST
PROVE
VALGRIND
- PERF_AGGREGATING_LATER
+ UNZIP
+ PERF_
));
my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env);
print join("\n", @vars);
@@ -128,6 +129,7 @@ fi
unset CDPATH
unset GREP_OPTIONS
+unset UNZIP
case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
1|2|true)
@@ -212,11 +214,13 @@ then
error)
tput bold; tput setaf 1;; # bold red
skip)
- tput bold; tput setaf 2;; # bold green
+ tput setaf 4;; # blue
+ warn)
+ tput setaf 3;; # brown/yellow
pass)
- tput setaf 2;; # green
+ tput setaf 2;; # green
info)
- tput setaf 3;; # brown
+ tput setaf 6;; # cyan
*)
test -n "$quiet" && return;;
esac
@@ -298,7 +302,7 @@ test_ok_ () {
test_failure_ () {
test_failure=$(($test_failure + 1))
- say_color error "not ok - $test_count $1"
+ say_color error "not ok $test_count - $1"
shift
echo "$@" | sed -e 's/^/# /'
test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
@@ -306,12 +310,12 @@ test_failure_ () {
test_known_broken_ok_ () {
test_fixed=$(($test_fixed+1))
- say_color "" "ok $test_count - $@ # TODO known breakage"
+ say_color error "ok $test_count - $@ # TODO known breakage vanished"
}
test_known_broken_failure_ () {
test_broken=$(($test_broken+1))
- say_color skip "not ok $test_count - $@ # TODO known breakage"
+ say_color warn "not ok $test_count - $@ # TODO known breakage"
}
test_debug () {
@@ -404,13 +408,18 @@ test_done () {
if test "$test_fixed" != 0
then
- say_color pass "# fixed $test_fixed known breakage(s)"
+ say_color error "# $test_fixed known breakage(s) vanished; please update test(s)"
fi
if test "$test_broken" != 0
then
- say_color error "# still have $test_broken known breakage(s)"
- msg="remaining $(($test_count-$test_broken)) test(s)"
+ say_color warn "# still have $test_broken known breakage(s)"
+ fi
+ if test "$test_broken" != 0 || test "$test_fixed" != 0
+ then
+ test_remaining=$(( $test_count - $test_broken - $test_fixed ))
+ msg="remaining $test_remaining test(s)"
else
+ test_remaining=$test_count
msg="$test_count test(s)"
fi
case "$test_failure" in
@@ -424,7 +433,7 @@ test_done () {
if test $test_external_has_tap -eq 0
then
- if test $test_count -gt 0
+ if test $test_remaining -gt 0
then
say_color pass "# passed all $msg"
fi
@@ -615,7 +624,7 @@ for skp in $GIT_SKIP_TESTS
do
case "$this_test" in
$skp)
- say_color skip >&3 "skipping test $this_test altogether"
+ say_color info >&3 "skipping test $this_test altogether"
skip_all="skip all tests in $this_test"
test_done
esac
diff --git a/test-path-utils.c b/test-path-utils.c
index 3bc20e91da..0092cbf354 100644
--- a/test-path-utils.c
+++ b/test-path-utils.c
@@ -1,4 +1,32 @@
#include "cache.h"
+#include "string-list.h"
+
+/*
+ * A "string_list_each_func_t" function that normalizes an entry from
+ * GIT_CEILING_DIRECTORIES. If the path is unusable for some reason,
+ * die with an explanation.
+ */
+static int normalize_ceiling_entry(struct string_list_item *item, void *unused)
+{
+ const char *ceil = item->string;
+ int len = strlen(ceil);
+ char buf[PATH_MAX+1];
+
+ if (len == 0)
+ die("Empty path is not supported");
+ if (len > PATH_MAX)
+ die("Path \"%s\" is too long", ceil);
+ if (!is_absolute_path(ceil))
+ die("Path \"%s\" is not absolute", ceil);
+ if (normalize_path_copy(buf, ceil) < 0)
+ die("Path \"%s\" could not be normalized", ceil);
+ len = strlen(buf);
+ if (len > 1 && buf[len-1] == '/')
+ die("Normalized path \"%s\" ended with slash", buf);
+ free(item->string);
+ item->string = xstrdup(buf);
+ return 1;
+}
int main(int argc, char **argv)
{
@@ -30,7 +58,28 @@ int main(int argc, char **argv)
}
if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
- int len = longest_ancestor_length(argv[2], argv[3]);
+ int len;
+ struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
+ char *path = xstrdup(argv[2]);
+
+ /*
+ * We have to normalize the arguments because under
+ * Windows, bash mangles arguments that look like
+ * absolute POSIX paths or colon-separate lists of
+ * absolute POSIX paths into DOS paths (e.g.,
+ * "/foo:/foo/bar" might be converted to
+ * "D:\Src\msysgit\foo;D:\Src\msysgit\foo\bar"),
+ * whereas longest_ancestor_length() requires paths
+ * that use forward slashes.
+ */
+ if (normalize_path_copy(path, path))
+ die("Path \"%s\" could not be normalized", argv[2]);
+ string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1);
+ filter_string_list(&ceiling_dirs, 0,
+ normalize_ceiling_entry, NULL);
+ len = longest_ancestor_length(path, &ceiling_dirs);
+ string_list_clear(&ceiling_dirs, 0);
+ free(path);
printf("%d\n", len);
return 0;
}
diff --git a/test-string-list.c b/test-string-list.c
index 4693295a98..00ce6c9a12 100644
--- a/test-string-list.c
+++ b/test-string-list.c
@@ -97,26 +97,6 @@ int main(int argc, char **argv)
return 0;
}
- if (argc == 4 && !strcmp(argv[1], "longest_prefix")) {
- /* arguments: <colon-separated-prefixes>|- <string> */
- struct string_list prefixes = STRING_LIST_INIT_DUP;
- int retval;
- const char *prefix_string = argv[2];
- const char *string = argv[3];
- const char *match;
-
- parse_string_list(&prefixes, prefix_string);
- match = string_list_longest_prefix(&prefixes, string);
- if (match) {
- printf("%s\n", match);
- retval = 0;
- }
- else
- retval = 1;
- string_list_clear(&prefixes, 0);
- return retval;
- }
-
fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
argv[1] ? argv[1] : "(there was none)");
return 1;
diff --git a/test-wildmatch.c b/test-wildmatch.c
new file mode 100644
index 0000000000..e384c8edb1
--- /dev/null
+++ b/test-wildmatch.c
@@ -0,0 +1,22 @@
+#include "cache.h"
+#include "wildmatch.h"
+
+int main(int argc, char **argv)
+{
+ int i;
+ for (i = 2; i < argc; i++) {
+ if (argv[i][0] == '/')
+ die("Forward slash is not allowed at the beginning of the\n"
+ "pattern because Windows does not like it. Use `XXX/' instead.");
+ else if (!strncmp(argv[i], "XXX/", 4))
+ argv[i] += 3;
+ }
+ if (!strcmp(argv[1], "wildmatch"))
+ return !!wildmatch(argv[3], argv[2], 0);
+ else if (!strcmp(argv[1], "iwildmatch"))
+ return !!wildmatch(argv[3], argv[2], FNM_CASEFOLD);
+ else if (!strcmp(argv[1], "fnmatch"))
+ return !!fnmatch(argv[3], argv[2], FNM_PATHNAME);
+ else
+ return 1;
+}
diff --git a/transport-helper.c b/transport-helper.c
index 4713b69302..965b778cb3 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -661,6 +661,11 @@ static void push_update_ref_status(struct strbuf *buf,
free(msg);
msg = NULL;
}
+ else if (!strcmp(msg, "already exists")) {
+ status = REF_STATUS_REJECT_ALREADY_EXISTS;
+ free(msg);
+ msg = NULL;
+ }
}
if (*ref)
@@ -720,6 +725,7 @@ static int push_refs_with_push(struct transport *transport,
/* Check for statuses set by set_ref_status_for_push() */
switch (ref->status) {
case REF_STATUS_REJECT_NONFASTFORWARD:
+ case REF_STATUS_REJECT_ALREADY_EXISTS:
case REF_STATUS_UPTODATE:
continue;
default:
diff --git a/transport.c b/transport.c
index 9932f402df..2673d273ff 100644
--- a/transport.c
+++ b/transport.c
@@ -659,7 +659,7 @@ static void print_ok_ref_status(struct ref *ref, int porcelain)
const char *msg;
strcpy(quickref, status_abbrev(ref->old_sha1));
- if (ref->nonfastforward) {
+ if (ref->requires_force) {
strcat(quickref, "...");
type = '+';
msg = "forced update";
@@ -695,6 +695,10 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
print_ref_status('!', "[rejected]", ref, ref->peer_ref,
"non-fast-forward", porcelain);
break;
+ case REF_STATUS_REJECT_ALREADY_EXISTS:
+ print_ref_status('!', "[rejected]", ref, ref->peer_ref,
+ "already exists", porcelain);
+ break;
case REF_STATUS_REMOTE_REJECT:
print_ref_status('!', "[remote rejected]", ref,
ref->deletion ? NULL : ref->peer_ref,
@@ -714,7 +718,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
}
void transport_print_push_status(const char *dest, struct ref *refs,
- int verbose, int porcelain, int *nonfastforward)
+ int verbose, int porcelain, unsigned int *reject_reasons)
{
struct ref *ref;
int n = 0;
@@ -733,18 +737,19 @@ void transport_print_push_status(const char *dest, struct ref *refs,
if (ref->status == REF_STATUS_OK)
n += print_one_push_status(ref, dest, n, porcelain);
- *nonfastforward = 0;
+ *reject_reasons = 0;
for (ref = refs; ref; ref = ref->next) {
if (ref->status != REF_STATUS_NONE &&
ref->status != REF_STATUS_UPTODATE &&
ref->status != REF_STATUS_OK)
n += print_one_push_status(ref, dest, n, porcelain);
- if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD &&
- *nonfastforward != NON_FF_HEAD) {
+ if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD) {
if (!strcmp(head, ref->name))
- *nonfastforward = NON_FF_HEAD;
+ *reject_reasons |= REJECT_NON_FF_HEAD;
else
- *nonfastforward = NON_FF_OTHER;
+ *reject_reasons |= REJECT_NON_FF_OTHER;
+ } else if (ref->status == REF_STATUS_REJECT_ALREADY_EXISTS) {
+ *reject_reasons |= REJECT_ALREADY_EXISTS;
}
}
}
@@ -1031,9 +1036,9 @@ static void die_with_unpushed_submodules(struct string_list *needs_pushing)
int transport_push(struct transport *transport,
int refspec_nr, const char **refspec, int flags,
- int *nonfastforward)
+ unsigned int *reject_reasons)
{
- *nonfastforward = 0;
+ *reject_reasons = 0;
transport_verify_remote_names(refspec_nr, refspec);
if (transport->push) {
@@ -1099,7 +1104,7 @@ int transport_push(struct transport *transport,
if (!quiet || err)
transport_print_push_status(transport->url, remote_refs,
verbose | porcelain, porcelain,
- nonfastforward);
+ reject_reasons);
if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
set_upstreams(transport, remote_refs, pretend);
diff --git a/transport.h b/transport.h
index 4a61c0c3f2..bfd2df5823 100644
--- a/transport.h
+++ b/transport.h
@@ -140,11 +140,13 @@ int transport_set_option(struct transport *transport, const char *name,
void transport_set_verbosity(struct transport *transport, int verbosity,
int force_progress);
-#define NON_FF_HEAD 1
-#define NON_FF_OTHER 2
+#define REJECT_NON_FF_HEAD 0x01
+#define REJECT_NON_FF_OTHER 0x02
+#define REJECT_ALREADY_EXISTS 0x04
+
int transport_push(struct transport *connection,
int refspec_nr, const char **refspec, int flags,
- int * nonfastforward);
+ unsigned int * reject_reasons);
const struct ref *transport_get_remote_refs(struct transport *transport);
@@ -170,7 +172,7 @@ void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int v
int transport_refs_pushed(struct ref *ref);
void transport_print_push_status(const char *dest, struct ref *refs,
- int verbose, int porcelain, int *nonfastforward);
+ int verbose, int porcelain, unsigned int *reject_reasons);
typedef void alternate_ref_fn(const struct ref *, void *);
extern void for_each_alternate_ref(alternate_ref_fn, void *);
diff --git a/tree-walk.c b/tree-walk.c
index 3f54c02d76..6e30ef9d04 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -573,6 +573,54 @@ static int match_dir_prefix(const char *base,
}
/*
+ * Perform matching on the leading non-wildcard part of
+ * pathspec. item->nowildcard_len must be greater than zero. Return
+ * non-zero if base is matched.
+ */
+static int match_wildcard_base(const struct pathspec_item *item,
+ const char *base, int baselen,
+ int *matched)
+{
+ const char *match = item->match;
+ /* the wildcard part is not considered in this function */
+ int matchlen = item->nowildcard_len;
+
+ if (baselen) {
+ int dirlen;
+ /*
+ * Return early if base is longer than the
+ * non-wildcard part but it does not match.
+ */
+ if (baselen >= matchlen) {
+ *matched = matchlen;
+ return !strncmp(base, match, matchlen);
+ }
+
+ dirlen = matchlen;
+ while (dirlen && match[dirlen - 1] != '/')
+ dirlen--;
+
+ /*
+ * Return early if base is shorter than the
+ * non-wildcard part but it does not match. Note that
+ * base ends with '/' so we are sure it really matches
+ * directory
+ */
+ if (strncmp(base, match, baselen))
+ return 0;
+ *matched = baselen;
+ } else
+ *matched = 0;
+ /*
+ * we could have checked entry against the non-wildcard part
+ * that is not in base and does similar never_interesting
+ * optimization as in match_entry. For now just be happy with
+ * base comparison.
+ */
+ return entry_interesting;
+}
+
+/*
* Is a tree entry interesting given the pathspec we have?
*
* Pre-condition: either baselen == base_offset (i.e. empty path)
@@ -602,7 +650,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
const struct pathspec_item *item = ps->items+i;
const char *match = item->match;
const char *base_str = base->buf + base_offset;
- int matchlen = item->len;
+ int matchlen = item->len, matched = 0;
if (baselen >= matchlen) {
/* If it doesn't match, move along... */
@@ -626,8 +674,10 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
&never_interesting))
return entry_interesting;
- if (item->use_wildcard) {
- if (!fnmatch(match + baselen, entry->path, 0))
+ if (item->nowildcard_len < item->len) {
+ if (!git_fnmatch(match + baselen, entry->path,
+ item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+ item->nowildcard_len - baselen))
return entry_interesting;
/*
@@ -642,17 +692,34 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
}
match_wildcards:
- if (!item->use_wildcard)
+ if (item->nowildcard_len == item->len)
continue;
+ if (item->nowildcard_len &&
+ !match_wildcard_base(item, base_str, baselen, &matched))
+ return entry_not_interesting;
+
/*
* Concatenate base and entry->path into one and do
* fnmatch() on it.
+ *
+ * While we could avoid concatenation in certain cases
+ * [1], which saves a memcpy and potentially a
+ * realloc, it turns out not worth it. Measurement on
+ * linux-2.6 does not show any clear improvements,
+ * partly because of the nowildcard_len optimization
+ * in git_fnmatch(). Avoid micro-optimizations here.
+ *
+ * [1] if match_wildcard_base() says the base
+ * directory is already matched, we only need to match
+ * the rest, which is shorter so _in theory_ faster.
*/
strbuf_add(base, entry->path, pathlen);
- if (!fnmatch(match, base->buf + base_offset, 0)) {
+ if (!git_fnmatch(match, base->buf + base_offset,
+ item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+ item->nowildcard_len)) {
strbuf_setlen(base, base_offset + baselen);
return entry_interesting;
}
diff --git a/unpack-trees.c b/unpack-trees.c
index 6d9636623a..0e1a196ace 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -837,7 +837,8 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
{
struct cache_entry **cache_end;
int dtype = DT_DIR;
- int ret = excluded_from_list(prefix, prefix_len, basename, &dtype, el);
+ int ret = is_excluded_from_list(prefix, prefix_len,
+ basename, &dtype, el);
prefix[prefix_len++] = '/';
@@ -856,7 +857,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
* with ret (iow, we know in advance the incl/excl
* decision for the entire directory), clear flag here without
* calling clear_ce_flags_1(). That function will call
- * the expensive excluded_from_list() on every entry.
+ * the expensive is_excluded_from_list() on every entry.
*/
return clear_ce_flags_1(cache, cache_end - cache,
prefix, prefix_len,
@@ -939,7 +940,8 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr,
/* Non-directory */
dtype = ce_to_dtype(ce);
- ret = excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el);
+ ret = is_excluded_from_list(ce->name, ce_namelen(ce),
+ name, &dtype, el);
if (ret < 0)
ret = defval;
if (ret > 0)
@@ -1152,7 +1154,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
*o->dst_index = o->result;
done:
- free_excludes(&el);
+ clear_exclude_list(&el);
if (o->path_exclude_check) {
path_exclude_check_clear(o->path_exclude_check);
free(o->path_exclude_check);
@@ -1373,7 +1375,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
return 0;
if (o->dir &&
- path_excluded(o->path_exclude_check, name, -1, &dtype))
+ is_path_excluded(o->path_exclude_check, name, -1, &dtype))
/*
* ce->name is explicitly excluded, so it is Ok to
* overwrite it.
@@ -1834,7 +1836,7 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
if (old && same(old, a)) {
int update = 0;
- if (o->reset && !ce_uptodate(old) && !ce_skip_worktree(old)) {
+ if (o->reset && o->update && !ce_uptodate(old) && !ce_skip_worktree(old)) {
struct stat st;
if (lstat(old->name, &st) ||
ie_match_stat(o->src_index, old, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE))
diff --git a/upload-pack.c b/upload-pack.c
index 6142421ea1..95d83135ae 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -603,6 +603,8 @@ static void receive_needs(void)
object = parse_object(sha1);
if (!object)
die("did not find object for %s", line);
+ if (object->type != OBJ_COMMIT)
+ die("invalid shallow object %s", sha1_to_hex(sha1));
object->flags |= CLIENT_SHALLOW;
add_object_array(object, NULL, &shallows);
continue;
diff --git a/usage.c b/usage.c
index 8eab28113a..40b3de51c7 100644
--- a/usage.c
+++ b/usage.c
@@ -130,6 +130,7 @@ void NORETURN die_errno(const char *fmt, ...)
va_end(params);
}
+#undef error
int error(const char *err, ...)
{
va_list params;
diff --git a/wildmatch.c b/wildmatch.c
new file mode 100644
index 0000000000..2d3ed84364
--- /dev/null
+++ b/wildmatch.c
@@ -0,0 +1,235 @@
+/*
+** Do shell-style pattern matching for ?, \, [], and * characters.
+** It is 8bit clean.
+**
+** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
+** Rich $alz is now <rsalz@bbn.com>.
+**
+** Modified by Wayne Davison to special-case '/' matching, to make '**'
+** work differently than '*', and to fix the character-class code.
+*/
+
+#include "cache.h"
+#include "wildmatch.h"
+
+typedef unsigned char uchar;
+
+/* What character marks an inverted character class? */
+#define NEGATE_CLASS '!'
+#define NEGATE_CLASS2 '^'
+
+#define FALSE 0
+#define TRUE 1
+
+#define CC_EQ(class, len, litmatch) ((len) == sizeof (litmatch)-1 \
+ && *(class) == *(litmatch) \
+ && strncmp((char*)class, litmatch, len) == 0)
+
+#if defined STDC_HEADERS || !defined isascii
+# define ISASCII(c) 1
+#else
+# define ISASCII(c) isascii(c)
+#endif
+
+#ifdef isblank
+# define ISBLANK(c) (ISASCII(c) && isblank(c))
+#else
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+
+#ifdef isgraph
+# define ISGRAPH(c) (ISASCII(c) && isgraph(c))
+#else
+# define ISGRAPH(c) (ISASCII(c) && isprint(c) && !isspace(c))
+#endif
+
+#define ISPRINT(c) (ISASCII(c) && isprint(c))
+#define ISDIGIT(c) (ISASCII(c) && isdigit(c))
+#define ISALNUM(c) (ISASCII(c) && isalnum(c))
+#define ISALPHA(c) (ISASCII(c) && isalpha(c))
+#define ISCNTRL(c) (ISASCII(c) && iscntrl(c))
+#define ISLOWER(c) (ISASCII(c) && islower(c))
+#define ISPUNCT(c) (ISASCII(c) && ispunct(c))
+#define ISSPACE(c) (ISASCII(c) && isspace(c))
+#define ISUPPER(c) (ISASCII(c) && isupper(c))
+#define ISXDIGIT(c) (ISASCII(c) && isxdigit(c))
+
+/* Match pattern "p" against "text" */
+static int dowild(const uchar *p, const uchar *text, int force_lower_case)
+{
+ uchar p_ch;
+ const uchar *pattern = p;
+
+ for ( ; (p_ch = *p) != '\0'; text++, p++) {
+ int matched, match_slash, negated;
+ uchar t_ch, prev_ch;
+ if ((t_ch = *text) == '\0' && p_ch != '*')
+ return ABORT_ALL;
+ if (force_lower_case && ISUPPER(t_ch))
+ t_ch = tolower(t_ch);
+ if (force_lower_case && ISUPPER(p_ch))
+ p_ch = tolower(p_ch);
+ switch (p_ch) {
+ case '\\':
+ /* Literal match with following character. Note that the test
+ * in "default" handles the p[1] == '\0' failure case. */
+ p_ch = *++p;
+ /* FALLTHROUGH */
+ default:
+ if (t_ch != p_ch)
+ return NOMATCH;
+ continue;
+ case '?':
+ /* Match anything but '/'. */
+ if (t_ch == '/')
+ return NOMATCH;
+ continue;
+ case '*':
+ if (*++p == '*') {
+ const uchar *prev_p = p - 2;
+ while (*++p == '*') {}
+ if ((prev_p < pattern || *prev_p == '/') &&
+ (*p == '\0' || *p == '/' ||
+ (p[0] == '\\' && p[1] == '/'))) {
+ /*
+ * Assuming we already match 'foo/' and are at
+ * <star star slash>, just assume it matches
+ * nothing and go ahead match the rest of the
+ * pattern with the remaining string. This
+ * helps make foo/<*><*>/bar (<> because
+ * otherwise it breaks C comment syntax) match
+ * both foo/bar and foo/a/bar.
+ */
+ if (p[0] == '/' &&
+ dowild(p + 1, text, force_lower_case) == MATCH)
+ return MATCH;
+ match_slash = TRUE;
+ } else
+ return ABORT_MALFORMED;
+ } else
+ match_slash = FALSE;
+ if (*p == '\0') {
+ /* Trailing "**" matches everything. Trailing "*" matches
+ * only if there are no more slash characters. */
+ if (!match_slash) {
+ if (strchr((char*)text, '/') != NULL)
+ return NOMATCH;
+ }
+ return MATCH;
+ }
+ while (1) {
+ if (t_ch == '\0')
+ break;
+ if ((matched = dowild(p, text, force_lower_case)) != NOMATCH) {
+ if (!match_slash || matched != ABORT_TO_STARSTAR)
+ return matched;
+ } else if (!match_slash && t_ch == '/')
+ return ABORT_TO_STARSTAR;
+ t_ch = *++text;
+ }
+ return ABORT_ALL;
+ case '[':
+ p_ch = *++p;
+#ifdef NEGATE_CLASS2
+ if (p_ch == NEGATE_CLASS2)
+ p_ch = NEGATE_CLASS;
+#endif
+ /* Assign literal TRUE/FALSE because of "matched" comparison. */
+ negated = p_ch == NEGATE_CLASS? TRUE : FALSE;
+ if (negated) {
+ /* Inverted character class. */
+ p_ch = *++p;
+ }
+ prev_ch = 0;
+ matched = FALSE;
+ do {
+ if (!p_ch)
+ return ABORT_ALL;
+ if (p_ch == '\\') {
+ p_ch = *++p;
+ if (!p_ch)
+ return ABORT_ALL;
+ if (t_ch == p_ch)
+ matched = TRUE;
+ } else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
+ p_ch = *++p;
+ if (p_ch == '\\') {
+ p_ch = *++p;
+ if (!p_ch)
+ return ABORT_ALL;
+ }
+ if (t_ch <= p_ch && t_ch >= prev_ch)
+ matched = TRUE;
+ p_ch = 0; /* This makes "prev_ch" get set to 0. */
+ } else if (p_ch == '[' && p[1] == ':') {
+ const uchar *s;
+ int i;
+ for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {} /*SHARED ITERATOR*/
+ if (!p_ch)
+ return ABORT_ALL;
+ i = p - s - 1;
+ if (i < 0 || p[-1] != ':') {
+ /* Didn't find ":]", so treat like a normal set. */
+ p = s - 2;
+ p_ch = '[';
+ if (t_ch == p_ch)
+ matched = TRUE;
+ continue;
+ }
+ if (CC_EQ(s,i, "alnum")) {
+ if (ISALNUM(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "alpha")) {
+ if (ISALPHA(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "blank")) {
+ if (ISBLANK(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "cntrl")) {
+ if (ISCNTRL(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "digit")) {
+ if (ISDIGIT(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "graph")) {
+ if (ISGRAPH(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "lower")) {
+ if (ISLOWER(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "print")) {
+ if (ISPRINT(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "punct")) {
+ if (ISPUNCT(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "space")) {
+ if (ISSPACE(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "upper")) {
+ if (ISUPPER(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "xdigit")) {
+ if (ISXDIGIT(t_ch))
+ matched = TRUE;
+ } else /* malformed [:class:] string */
+ return ABORT_ALL;
+ p_ch = 0; /* This makes "prev_ch" get set to 0. */
+ } else if (t_ch == p_ch)
+ matched = TRUE;
+ } while (prev_ch = p_ch, (p_ch = *++p) != ']');
+ if (matched == negated || t_ch == '/')
+ return NOMATCH;
+ continue;
+ }
+ }
+
+ return *text ? NOMATCH : MATCH;
+}
+
+/* Match the "pattern" against the "text" string. */
+int wildmatch(const char *pattern, const char *text, int flags)
+{
+ return dowild((const uchar*)pattern, (const uchar*)text,
+ flags & FNM_CASEFOLD ? 1 :0);
+}
diff --git a/wildmatch.h b/wildmatch.h
new file mode 100644
index 0000000000..984a38cdc2
--- /dev/null
+++ b/wildmatch.h
@@ -0,0 +1,9 @@
+/* wildmatch.h */
+
+#define ABORT_MALFORMED 2
+#define NOMATCH 1
+#define MATCH 0
+#define ABORT_ALL -1
+#define ABORT_TO_STARSTAR -2
+
+int wildmatch(const char *pattern, const char *text, int flags);
diff --git a/wt-status.c b/wt-status.c
index 2a9658bad4..d7cfe8f31c 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -516,7 +516,9 @@ static void wt_status_collect_untracked(struct wt_status *s)
if (s->show_ignored_files) {
dir.nr = 0;
- dir.flags = DIR_SHOW_IGNORED | DIR_SHOW_OTHER_DIRECTORIES;
+ dir.flags = DIR_SHOW_IGNORED;
+ if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
+ dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
fill_directory(&dir, s->pathspec);
for (i = 0; i < dir.nr; i++) {
struct dir_entry *ent = dir.entries[i];