Merge branch 'vr/msvc'
authorJunio C Hamano <gitster@pobox.com>
Mon, 5 Dec 2011 23:12:54 +0000 (15:12 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 5 Dec 2011 23:12:54 +0000 (15:12 -0800)
* vr/msvc:
MSVC: Remove unneeded header stubs
Compile fix for MSVC: Include <io.h>
Compile fix for MSVC: Do not include sys/resources.h

83 files changed:
Documentation/Makefile
Documentation/RelNotes/1.7.7.2.txt [new file with mode: 0644]
Documentation/RelNotes/1.7.7.3.txt [new file with mode: 0644]
Documentation/RelNotes/1.7.7.4.txt [new file with mode: 0644]
Documentation/RelNotes/1.7.8.txt
Documentation/diff-options.txt
Documentation/git-cherry-pick.txt
Documentation/git-difftool.txt
Documentation/git-fsck.txt
Documentation/git-reset.txt
Documentation/git-revert.txt
Documentation/git.txt
Documentation/install-doc-quick.sh
Documentation/merge-options.txt
Documentation/sequencer.txt
GIT-VERSION-GEN
INSTALL
Makefile
branch.c
builtin/apply.c
builtin/blame.c
builtin/branch.c
builtin/commit.c
builtin/diff.c
builtin/fsck.c
builtin/gc.c
builtin/grep.c
builtin/merge.c
builtin/mktree.c
builtin/name-rev.c
builtin/pack-objects.c
builtin/prune.c
builtin/receive-pack.c
builtin/reflog.c
builtin/remote.c
builtin/revert.c
builtin/stripspace.c
compat/strtoimax.c [new file with mode: 0644]
compat/win32/poll.c [new file with mode: 0644]
compat/win32/poll.h [new file with mode: 0644]
compat/win32/sys/poll.c [deleted file]
compat/win32/sys/poll.h [deleted file]
config.c
contrib/completion/git-completion.bash
contrib/fast-import/git-p4
contrib/fast-import/git-p4.txt
convert.c
dir.c
git-compat-util.h
git-svn.perl
http.c
http.h
list-objects.c
mailmap.c
name-hash.c
notes-merge.c
pack-check.c
pack.h
perl/.gitignore
pretty.c
reachable.c
reachable.h
refs.c
sequencer.h
sha1_file.c
submodule.c
t/t3200-branch.sh
t/t3507-cherry-pick-conflict.sh
t/t3510-cherry-pick-sequence.sh
t/t5501-fetch-push-alternates.sh
t/t5700-clone-reference.sh
t/t6030-bisect-porcelain.sh
t/t7106-reset-sequence.sh
t/t7508-status.sh
t/t7511-status-index.sh
t/t8006-blame-textconv.sh
t/t9802-git-p4-filetype.sh
t/t9805-skip-submit-edit.sh [new file with mode: 0755]
tree-diff.c
tree-walk.c
tree-walk.h
tree.c
unpack-trees.c
index 551325604e84713c87e2e95105861626e09fbef5..304b31edee2e5c4e998c48cc571c66e8264cc581 100644 (file)
@@ -46,8 +46,8 @@ MANPAGE_XSL = manpage-normal.xsl
 XMLTO_EXTRA =
 INSTALL?=install
 RM ?= rm -f
-DOC_REF = origin/man
-HTML_REF = origin/html
+MAN_REPO = ../../git-manpages
+HTML_REPO = ../../git-htmldocs
 
 infodir?=$(prefix)/share/info
 MAKEINFO=makeinfo
@@ -327,12 +327,23 @@ $(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
 install-webdoc : html
        '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(WEBDOC_DEST)
 
+# You must have a clone of git-htmldocs and git-manpages repositories
+# next to the git repository itself for the following to work.
+
 quick-install: quick-install-man
 
-quick-install-man:
-       '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(DOC_REF) $(DESTDIR)$(mandir)
+require-manrepo::
+       @if test ! -d $(MAN_REPO); \
+       then echo "git-manpages repository must exist at $(MAN_REPO)"; exit 1; fi
+
+quick-install-man: require-manrepo
+       '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(MAN_REPO) $(DESTDIR)$(mandir)
+
+require-htmlrepo::
+       @if test ! -d $(HTML_REPO); \
+       then echo "git-htmldocs repository must exist at $(HTML_REPO)"; exit 1; fi
 
-quick-install-html:
-       '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir)
+quick-install-html: require-htmlrepo
+       '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REPO) $(DESTDIR)$(htmldir)
 
 .PHONY: FORCE
diff --git a/Documentation/RelNotes/1.7.7.2.txt b/Documentation/RelNotes/1.7.7.2.txt
new file mode 100644 (file)
index 0000000..e6bbef2
--- /dev/null
@@ -0,0 +1,44 @@
+Git v1.7.7.2 Release Notes
+==========================
+
+Fixes since v1.7.7.1
+--------------------
+
+ * We used to drop error messages from libcurl on certain kinds of
+   errors.
+
+ * Error report from smart HTTP transport, when the connection was
+   broken in the middle of a transfer, showed a useless message on
+   a corrupt packet.
+
+ * "git fetch --prune" was unsafe when used with refspecs from the
+   command line.
+
+ * The attribute mechanism did not use case insensitive match when
+   core.ignorecase was set.
+
+ * "git bisect" did not notice when it failed to update the working tree
+   to the next commit to be tested.
+
+ * "git config --bool --get-regexp" failed to separate the variable name
+   and its value "true" when the variable is defined without "= true".
+
+ * "git remote rename $a $b" were not careful to match the remote name
+   against $a (i.e. source side of the remote nickname).
+
+ * "git mergetool" did not use its arguments as pathspec, but as a path to
+   the file that may not even have any conflict.
+
+ * "git diff --[num]stat" used to use the number of lines of context
+   different from the default, potentially giving different results from
+   "git diff | diffstat" and confusing the users.
+
+ * "git pull" and "git rebase" did not work well even when GIT_WORK_TREE is
+   set correctly with GIT_DIR if the current directory is outside the working
+   tree.
+
+ * "git send-email" did not honor the configured hostname when restarting
+   the HELO/EHLO exchange after switching TLS on.
+
+ * "gitweb" used to produce a non-working link while showing the contents
+   of a blob, when JavaScript actions are enabled.
diff --git a/Documentation/RelNotes/1.7.7.3.txt b/Documentation/RelNotes/1.7.7.3.txt
new file mode 100644 (file)
index 0000000..09301f0
--- /dev/null
@@ -0,0 +1,19 @@
+Git v1.7.7.3 Release Notes
+==========================
+
+Fixes since v1.7.7.2
+--------------------
+
+ * Adjust the "quick-install-doc" procedures as preformatted
+   html/manpage are no longer in the source repository.
+
+ * The logic to optimize the locality of the data in a pack introduced in
+   1.7.7 was grossly inefficient.
+
+ * The logic to filter out forked projects in the project list in
+   "gitweb" was broken for some time.
+
+ * "git branch -m/-M" advertised to update RENAME_REF ref in the
+   commit log message that introduced the feature but not anywhere in
+   the documentation, and never did update such a ref anyway. This
+   undocumented misfeature that did not exist has been excised.
diff --git a/Documentation/RelNotes/1.7.7.4.txt b/Documentation/RelNotes/1.7.7.4.txt
new file mode 100644 (file)
index 0000000..e523448
--- /dev/null
@@ -0,0 +1,14 @@
+Git v1.7.7.4 Release Notes
+==========================
+
+Fixes since v1.7.7.3
+--------------------
+
+ * A few header dependencies were missing from the Makefile.
+
+ * Some newer parts of the code used C99 __VA_ARGS__ while we still
+   try to cater to older compilers.
+
+ * "git name-rev --all" tried to name all _objects_, naturally failing to
+   describe many blobs and trees, instead of showing only commits as
+   advertised in its documentation.
index 5645fa20bf98bb2be2862bf734baf7aa1e226816..b4d90bba0f6c761e61321bb9df8b7a8b3f725272 100644 (file)
@@ -1,5 +1,5 @@
-Git v1.7.8 Release Notes (draft)
-================================
+Git v1.7.8 Release Notes
+========================
 
 Updates since v1.7.7
 --------------------
@@ -29,7 +29,7 @@ Updates since v1.7.7
    files from the index, not from the working tree.
 
  * Variants of "git cherry-pick" and "git revert" that take multiple
-   commits learned to "--continue".
+   commits learned to "--continue" and "--abort".
 
  * "git daemon" gives more human readble error messages to clients
    using ERR packets when appropriate.
@@ -79,6 +79,9 @@ Updates since v1.7.7
 
  * "git ls-remote" learned to respond to "-h"(elp) requests.
 
+ * "mediawiki" remote helper can interact with (surprise!) MediaWiki
+   with "git fetch" & "git push".
+
  * "git merge" learned the "--edit" option to allow users to edit the
    merge commit log message.
 
@@ -110,9 +113,6 @@ Updates since v1.7.7
    between commits in the superproject that has and does not have the
    submodule in the tree without re-cloning.
 
- * "mediawiki" remote helper can interact with (surprise!) MediaWiki
-   with "git fetch" & "git push".
-
  * "gitweb" leaked unescaped control characters from syntax hiliter
    outputs.
 
@@ -131,91 +131,31 @@ Fixes since v1.7.7
 Unless otherwise noted, all fixes in the 1.7.7.X maintenance track are
 included in this release.
 
- * We used to drop error messages from libcurl on certain kinds of
-   errors.
-   (merge be22d92eac8 jn/maint-http-error-message later to maint).
-
- * Error report from smart HTTP transport, when the connection was
-   broken in the middle of a transfer, showed a useless message on
-   a corrupt packet.
-   (merge 6cdf022 sp/smart-http-failure later to maint).
-
  * HTTP transport did not use pushurl correctly, and also did not tell
    what host it is trying to authenticate with when asking for
    credentials.
    (merge deba493 jk/http-auth later to maint).
 
- * "git branch -m/-M" advertised to update RENAME_REF ref in the
-   commit log message that introduced the feature but not anywhere in
-   the documentation, and never did update such a ref anyway. This
-   undocumented misfeature that did not exist has been excised.
-   (merge b0eab01 jc/maint-remove-renamed-ref later to maint).
+ * "git blame" was aborted if started from an uncommitted content and
+   the path had the textconv filter in effect.
+   (merge 8518088 ss/blame-textconv-fake-working-tree later to maint).
 
  * Adding many refs to the local repository in one go (e.g. "git fetch"
    that fetches many tags) and looking up a ref by name in a repository
    with too many refs were unnecessarily slow.
    (merge 17d68a54d jp/get-ref-dir-unsorted later to maint).
 
- * "git fetch --prune" was unsafe when used with refspecs from the
-   command line.
-   (merge e8c1e6c cn/fetch-prune later to maint).
-
  * Report from "git commit" on untracked files was confused under
    core.ignorecase option.
-   (merge 2548183b jk/name-hash-dirent later to maint).
-
- * The attribute mechanism did not use case insensitive match when
-   core.ignorecase was set.
-   (merge 6eba621 bc/attr-ignore-case later to maint).
-
- * "git bisect" did not notice when it failed to update the working tree
-   to the next commit to be tested.
-   (merge 1acf11717 js/bisect-no-checkout later to maint).
-
- * "git config --bool --get-regexp" failed to separate the variable name
-   and its value "true" when the variable is defined without "= true".
-   (merge 880e3cc mm/maint-config-explicit-bool-display later to maint).
-
- * "git remote rename $a $b" were not careful to match the remote name
-   against $a (i.e. source side of the remote nickname).
-   (merge b52d00aed mz/remote-rename later to maint).
-
- * "git diff --[num]stat" used to use the number of lines of context
-   different from the default, potentially giving different results from
-   "git diff | diffstat" and confusing the users.
-   (merge f01cae918 jc/maint-diffstat-numstat-context later to maint).
+   (merge 395c7356 jk/name-hash-dirent later to maint).
 
  * "git merge" did not understand ":/<pattern>" as a way to name a commit.
 
- * "git mergetool" learned to use its arguments as pathspec, not a path to
-   the file that may not even have any conflict.
-   (merge 6d9990a jm/mergetool-pathspec later to maint).
-
- * "git pull" and "git rebase" did not work well even when GIT_WORK_TREE is
-   set correctly with GIT_DIR if the current directory is outside the working
-   tree.
-   (merge 035b5bf jk/pull-rebase-with-work-tree later to maint).
-
  " "git push" on the receiving end used to call post-receive and post-update
    hooks for attempted removal of non-existing refs.
    (merge 160b81ed ph/push-to-delete-nothing later to maint).
 
- * "git send-email" did not honor the configured hostname when restarting
-   the HELO/EHLO exchange after switching TLS on.
-   (merge 155b940 md/smtp-tls-hello-again later to maint).
-
- * "gitweb" used to produce a non-working link while showing the contents
-   of a blob, when JavaScript actions are enabled.
-   (merge 2b07ff3ff ps/gitweb-js-with-lineno later to maint).
-
- * The logic to filter out forked projects in the project list in
-   "gitweb" was broken for some time.
-   (merge 53c632f jm/maint-gitweb-filter-forks-fix later to maint).
-
----
-exec >/var/tmp/1
-O=v1.7.7.1-492-g324bc2a
-echo O=$(git describe --always master)
-git log --first-parent --oneline --reverse ^$O master
-echo
-git shortlog --no-merges ^$O master
+ * Help text for "git remote set-url" and "git remote set-branches"
+   were misspelled.
+   (merge c49904e fc/remote-seturl-usage-fix later to maint).
+   (merge 656cdf0 jc/remote-setbranches-usage-fix later to maint).
index 08b581f040859d39aeaad8294bc7a3e7760ab0b9..9f7cba2be6a97cb85072d22b3317d37d1afe80bf 100644 (file)
@@ -413,6 +413,7 @@ endif::git-format-patch[]
        Show whole surrounding functions of changes.
 
 ifndef::git-format-patch[]
+ifndef::git-log[]
 --exit-code::
        Make the program exit with codes similar to diff(1).
        That is, it exits with 1 if there were differences and
@@ -420,6 +421,7 @@ ifndef::git-format-patch[]
 
 --quiet::
        Disable all output of the program. Implies `--exit-code`.
+endif::git-log[]
 endif::git-format-patch[]
 
 --ext-diff::
index 2660a842fc2ac76660963bc65c95ca47cb0e97cb..fed5097e00b4a031c2992ac3d421f6df975e6152 100644 (file)
@@ -9,8 +9,9 @@ SYNOPSIS
 --------
 [verse]
 'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>...
-'git cherry-pick' --reset
 'git cherry-pick' --continue
+'git cherry-pick' --quit
+'git cherry-pick' --abort
 
 DESCRIPTION
 -----------
index a03515f1eccddded2efbd46ca522f3bac8896d90..19d473c070c4f82dc4b7f04f784bcae835dca6a2 100644 (file)
@@ -31,7 +31,7 @@ OPTIONS
 -t <tool>::
 --tool=<tool>::
        Use the diff tool specified by <tool>.
-       Valid merge tools are:
+       Valid diff tools are:
        araxis, bc3, diffuse, emerge, ecmerge, gvimdiff, kdiff3,
        kompare, meld, opendiff, p4merge, tkdiff, vimdiff and xxdiff.
 +
index a2a508dc2829b88e143ceb5c8e5edf0880263b2b..0a17b4258e2a69a1d2a5e931dd14ac1869876f33 100644 (file)
@@ -10,7 +10,8 @@ SYNOPSIS
 --------
 [verse]
 'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
-        [--[no-]full] [--strict] [--verbose] [--lost-found] [<object>*]
+        [--[no-]full] [--strict] [--verbose] [--lost-found]
+        [--[no-]progress] [<object>*]
 
 DESCRIPTION
 -----------
@@ -72,6 +73,14 @@ index file, all SHA1 references in .git/refs/*, and all reflogs (unless
        a blob, the contents are written into the file, rather than
        its object name.
 
+--progress::
+--no-progress::
+       Progress status is reported on the standard error stream by
+       default when it is attached to a terminal, unless
+       --no-progress or --verbose is specified. --progress forces
+       progress status even if the standard error stream is not
+       directed to a terminal.
+
 It tests SHA1 and general object sanity, and it does full tracking of
 the resulting reachability and everything else. It prints out any
 corruption it finds (missing or bad objects), and if you use the
index b2832fc7eb809af9865d83cdb20829354165f62e..b674866e6d166ccce096b58f7cecdbdb183c0194 100644 (file)
@@ -9,8 +9,8 @@ SYNOPSIS
 --------
 [verse]
 'git reset' [-q] [<commit>] [--] <paths>...
-'git reset' [--patch|-p] [<commit>] [--] [<paths>...]
-'git reset' [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]
+'git reset' (--patch | -p) [<commit>] [--] [<paths>...]
+'git reset' (--soft | --mixed | --hard | --merge | --keep) [-q] [<commit>]
 
 DESCRIPTION
 -----------
@@ -34,7 +34,7 @@ Alternatively, using linkgit:git-checkout[1] and specifying a commit, you
 can copy the contents of a path out of a commit to the index and to the
 working tree in one go.
 
-'git reset' --patch|-p [<commit>] [--] [<paths>...]::
+'git reset' (--patch | -p) [<commit>] [--] [<paths>...]::
        Interactively select hunks in the difference between the index
        and <commit> (defaults to HEAD).  The chosen hunks are applied
        in reverse to the index.
@@ -43,7 +43,7 @@ This means that `git reset -p` is the opposite of `git add -p`, i.e.
 you can use it to selectively reset hunks. See the ``Interactive Mode''
 section of linkgit:git-add[1] to learn how to operate the `\--patch` mode.
 
-'git reset' [--<mode>] [<commit>]::
+'git reset' --<mode> [<commit>]::
        This form resets the current branch head to <commit> and
        possibly updates the index (resetting it to the tree of <commit>) and
        the working tree depending on <mode>, which
index f3519413e7e8704deee0197df6876eaed97e28b0..b699a3458eff439b05049dab94610a57ac62fc0a 100644 (file)
@@ -9,8 +9,9 @@ SYNOPSIS
 --------
 [verse]
 'git revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>...
-'git revert' --reset
 'git revert' --continue
+'git revert' --quit
+'git revert' --abort
 
 DESCRIPTION
 -----------
index 5e80cfd71a5529225b607bd3f1732d19f05d0c1d..e869032fc0703aed18d3cb1417eda4341c29e093 100644 (file)
@@ -44,6 +44,11 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
+* link:v1.7.8/git.html[documentation for release 1.7.8]
+
+* release notes for
+  link:RelNotes/1.7.8.txt[1.7.8].
+
 * link:v1.7.7.1/git.html[documentation for release 1.7.7.1]
 
 * release notes for
index 35f440876ed182de319b6d3f0b8296b1a1ede29d..327f69bcf5a20c7cf33a712b08bed9d4ccfe9d2e 100755 (executable)
@@ -1,31 +1,39 @@
 #!/bin/sh
-# This requires a branch named in $head
-# (usually 'man' or 'html', provided by the git.git repository)
-set -e
-head="$1"
-mandir="$2"
-SUBDIRECTORY_OK=t
-USAGE='<refname> <target directory>'
-. "$(git --exec-path)"/git-sh-setup
-cd_to_toplevel
+# This requires git-manpages and/or git-htmldocs repositories
 
-test -z "$mandir" && usage
-if ! git rev-parse --verify "$head^0" >/dev/null; then
-       echo >&2 "head: $head does not exist in the current repository"
-       usage
+repository=${1?repository}
+destdir=${2?destination}
+
+head=master GIT_DIR=
+for d in "$repository/.git" "$repository"
+do
+       if GIT_DIR="$d" git rev-parse refs/heads/master >/dev/null 2>&1
+       then
+               GIT_DIR="$d"
+               export GIT_DIR
+               break
+       fi
+done
+
+if test -z "$GIT_DIR"
+then
+       echo >&2 "Neither $repository nor $repository/.git is a repository"
+       exit 1
 fi
 
-GIT_INDEX_FILE=`pwd`/.quick-doc.index
-export GIT_INDEX_FILE
+GIT_WORK_TREE=$(pwd)
+GIT_INDEX_FILE=$(pwd)/.quick-doc.$$
+export GIT_INDEX_FILE GIT_WORK_TREE
 rm -f "$GIT_INDEX_FILE"
 trap 'rm -f "$GIT_INDEX_FILE"' 0
 
 git read-tree $head
-git checkout-index -a -f --prefix="$mandir"/
+git checkout-index -a -f --prefix="$destdir"/
 
-if test -n "$GZ"; then
+if test -n "$GZ"
+then
        git ls-tree -r --name-only $head |
-       xargs printf "$mandir/%s\n" |
+       xargs printf "$destdir/%s\n" |
        xargs gzip -f
 fi
 rm -f "$GIT_INDEX_FILE"
index 6bd0b041c3c1c0af5d03fce43d8016706e9256b1..1a5c12e3171ab82f489bcd53657c8a89741a3dab 100644 (file)
@@ -9,7 +9,6 @@ inspect and further tweak the merge result before committing.
 
 --edit::
 -e::
-+
        Invoke editor before committing successful merge to further
        edit the default merge message.
 
index 3e6df338bed519eb74cf233f40589ddbfb0da57b..5747f442f25e6271c7464db78496b85ee058d05f 100644 (file)
@@ -1,9 +1,12 @@
---reset::
-       Forget about the current operation in progress.  Can be used
-       to clear the sequencer state after a failed cherry-pick or
-       revert.
-
 --continue::
        Continue the operation in progress using the information in
        '.git/sequencer'.  Can be used to continue after resolving
        conflicts in a failed cherry-pick or revert.
+
+--quit::
+       Forget about the current operation in progress.  Can be used
+       to clear the sequencer state after a failed cherry-pick or
+       revert.
+
+--abort::
+       Cancel the operation and return to the pre-sequence state.
index 56dc9d66838c3767852da420b1eeaf6ee4ceb1c4..a04c8f32b767d757066526fc4f4685df812f3825 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.8-rc0
+DEF_VER=v1.7.8
 
 LF='
 '
diff --git a/INSTALL b/INSTALL
index bbb9d4dc9ab37a242d8accb86fa8a0d35d677ab8..bf0d97ef769adda0066578c7823a124385785e94 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -139,34 +139,11 @@ Issues of note:
    uses some compatibility wrappers to work on AsciiDoc 8. If you have
    AsciiDoc 7, try "make ASCIIDOC7=YesPlease".
 
-   Alternatively, pre-formatted documentation is available in
-   "html" and "man" branches of the git repository itself.  For
-   example, you could:
-
-       $ mkdir manual && cd manual
-       $ git init
-       $ git fetch-pack git://git.kernel.org/pub/scm/git/git.git man html |
-         while read a b
-         do
-           echo $a >.git/$b
-         done
-       $ cp .git/refs/heads/man .git/refs/heads/master
-       $ git checkout
-
-   to checkout the pre-built man pages.  Also in this repository:
-
-       $ git checkout html
-
-   would instead give you a copy of what you see at:
-
-       http://www.kernel.org/pub/software/scm/git/docs/
-
    There are also "make quick-install-doc", "make quick-install-man"
    and "make quick-install-html" which install preformatted man pages
-   and html documentation.
-   This does not require asciidoc/xmlto, but it only works from within
-   a cloned checkout of git.git with these two extra branches, and will
-   not work for the maintainer for obvious chicken-and-egg reasons.
+   and html documentation. To use these build targets, you need to
+   clone two separate git-htmldocs and git-manpages repositories next
+   to the clone of git itself.
 
    It has been reported that docbook-xsl version 1.72 and 1.73 are
    buggy; 1.72 misformats manual pages for callouts, and 1.73 needs
index 3139c19b10898d735b0d684c269454bc3fd84b68..b21d2f14176d08011cea79790eb2246d50787ec9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -57,8 +57,8 @@ all::
 #
 # Define NO_STRLCPY if you don't have strlcpy.
 #
-# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
-# If your compiler also does not support long long or does not have
+# Define NO_STRTOUMAX if you don't have both strtoimax and strtoumax in the
+# C library. If your compiler also does not support long long or does not have
 # strtoull, define NO_STRTOULL.
 #
 # Define NO_SETENV if you don't have setenv in the C library.
@@ -250,6 +250,12 @@ all::
 #   DEFAULT_EDITOR='$GIT_FALLBACK_EDITOR',
 #   DEFAULT_EDITOR='"C:\Program Files\Vim\gvim.exe" --nofork'
 #
+# Define COMPUTE_HEADER_DEPENDENCIES to "yes" if you want dependencies on
+# header files to be automatically computed, to avoid rebuilding objects when
+# an unrelated header file changes.  Define it to "no" to use the hard-coded
+# dependency rules.  The default is "auto", which means to use computed header
+# dependencies if your compiler is detected to support it.
+#
 # Define CHECK_HEADER_DEPENDENCIES to check for problems in the hard-coded
 # dependency rules.
 #
@@ -515,9 +521,10 @@ LIB_H += compat/mingw.h
 LIB_H += compat/obstack.h
 LIB_H += compat/win32/pthread.h
 LIB_H += compat/win32/syslog.h
-LIB_H += compat/win32/sys/poll.h
+LIB_H += compat/win32/poll.h
 LIB_H += compat/win32/dirent.h
 LIB_H += connected.h
+LIB_H += convert.h
 LIB_H += csum-file.h
 LIB_H += decorate.h
 LIB_H += delta.h
@@ -1088,6 +1095,7 @@ ifeq ($(uname_S),Windows)
        NO_PREAD = YesPlease
        NEEDS_CRYPTO_WITH_SSL = YesPlease
        NO_LIBGEN_H = YesPlease
+       NO_SYS_POLL_H = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_IPV6 = YesPlease
        NO_SETENV = YesPlease
@@ -1126,7 +1134,7 @@ ifeq ($(uname_S),Windows)
        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/sys/poll.o compat/win32/dirent.o
+               compat/win32/poll.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
@@ -1181,6 +1189,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        NO_PREAD = YesPlease
        NEEDS_CRYPTO_WITH_SSL = YesPlease
        NO_LIBGEN_H = YesPlease
+       NO_SYS_POLL_H = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_SETENV = YesPlease
        NO_UNSETENV = YesPlease
@@ -1214,7 +1223,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
        COMPAT_OBJS += compat/mingw.o compat/winansi.o \
                compat/win32/pthread.o compat/win32/syslog.o \
-               compat/win32/sys/poll.o compat/win32/dirent.o
+               compat/win32/poll.o compat/win32/dirent.o
        EXTLIBS += -lws2_32
        PTHREAD_LIBS =
        X = .exe
@@ -1243,21 +1252,32 @@ endif
 endif
 
 ifdef CHECK_HEADER_DEPENDENCIES
-COMPUTE_HEADER_DEPENDENCIES =
+COMPUTE_HEADER_DEPENDENCIES = no
 USE_COMPUTED_HEADER_DEPENDENCIES =
-else
+endif
+
 ifndef COMPUTE_HEADER_DEPENDENCIES
+COMPUTE_HEADER_DEPENDENCIES = auto
+endif
+
+ifeq ($(COMPUTE_HEADER_DEPENDENCIES),auto)
 dep_check = $(shell $(CC) $(ALL_CFLAGS) \
        -c -MF /dev/null -MMD -MP -x c /dev/null -o /dev/null 2>&1; \
        echo $$?)
 ifeq ($(dep_check),0)
-COMPUTE_HEADER_DEPENDENCIES=YesPlease
-endif
+override COMPUTE_HEADER_DEPENDENCIES = yes
+else
+override COMPUTE_HEADER_DEPENDENCIES = no
 endif
 endif
 
-ifdef COMPUTE_HEADER_DEPENDENCIES
+ifeq ($(COMPUTE_HEADER_DEPENDENCIES),yes)
 USE_COMPUTED_HEADER_DEPENDENCIES = YesPlease
+else
+ifneq ($(COMPUTE_HEADER_DEPENDENCIES),no)
+$(error please set COMPUTE_HEADER_DEPENDENCIES to yes, no, or auto \
+(not "$(COMPUTE_HEADER_DEPENDENCIES)"))
+endif
 endif
 
 ifdef SANE_TOOL_PATH
@@ -1458,7 +1478,7 @@ ifdef NO_STRLCPY
 endif
 ifdef NO_STRTOUMAX
        COMPAT_CFLAGS += -DNO_STRTOUMAX
-       COMPAT_OBJS += compat/strtoumax.o
+       COMPAT_OBJS += compat/strtoumax.o compat/strtoimax.o
 endif
 ifdef NO_STRTOULL
        COMPAT_CFLAGS += -DNO_STRTOULL
@@ -1904,7 +1924,7 @@ OBJECTS := $(GIT_OBJS) $(XDIFF_OBJS) $(VCSSVN_OBJS)
 dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d)
 dep_dirs := $(addsuffix .depend,$(sort $(dir $(OBJECTS))))
 
-ifdef COMPUTE_HEADER_DEPENDENCIES
+ifeq ($(COMPUTE_HEADER_DEPENDENCIES),yes)
 $(dep_dirs):
        @mkdir -p $@
 
@@ -1917,7 +1937,7 @@ Please unset CHECK_HEADER_DEPENDENCIES and try again)
 endif
 endif
 
-ifndef COMPUTE_HEADER_DEPENDENCIES
+ifneq ($(COMPUTE_HEADER_DEPENDENCIES),yes)
 ifndef CHECK_HEADER_DEPENDENCIES
 dep_dirs =
 missing_dep_dirs =
@@ -2007,13 +2027,13 @@ builtin/branch.o builtin/checkout.o builtin/clone.o builtin/reset.o branch.o tra
 builtin/bundle.o bundle.o transport.o: bundle.h
 builtin/bisect--helper.o builtin/rev-list.o bisect.o: bisect.h
 builtin/clone.o builtin/fetch-pack.o transport.o: fetch-pack.h
-builtin/grep.o builtin/pack-objects.o transport-helper.o: thread-utils.h
+builtin/grep.o builtin/pack-objects.o transport-helper.o thread-utils.o: thread-utils.h
 builtin/send-pack.o transport.o: send-pack.h
 builtin/log.o builtin/shortlog.o: shortlog.h
 builtin/prune.o builtin/reflog.o reachable.o: reachable.h
 builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
 builtin/tar-tree.o archive-tar.o: tar.h
-connect.o transport.o http-backend.o: url.h
+connect.o transport.o url.o http-backend.o: url.h
 http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
 http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
 
index d8098762f62a9dfb991f64702d34047182cfa951..025a97be0281b9fd3ccff2b36c03495b005ac4fe 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -241,6 +241,7 @@ void create_branch(const char *head,
 void remove_branch_state(void)
 {
        unlink(git_path("CHERRY_PICK_HEAD"));
+       unlink(git_path("REVERT_HEAD"));
        unlink(git_path("MERGE_HEAD"));
        unlink(git_path("MERGE_RR"));
        unlink(git_path("MERGE_MSG"));
index 84a8a0b52136c4d1e43ec10f9ef5ed76b7d3c12f..b3b59db534ff0763c822ae9da571d5643a8b709a 100644 (file)
@@ -250,9 +250,6 @@ static int fuzzy_matchlines(const char *s1, size_t n1,
        const char *last2 = s2 + n2 - 1;
        int result = 0;
 
-       if (n1 < 0 || n2 < 0)
-               return 0;
-
        /* ignore line endings */
        while ((*last1 == '\r') || (*last1 == '\n'))
                last1--;
index 26a5d424b8ceb0fd403a492e46e3637fd35068ba..80febbe420db1c75bbcf7eda6a733e7e66549790 100644 (file)
@@ -2096,6 +2096,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
        if (!contents_from || strcmp("-", contents_from)) {
                struct stat st;
                const char *read_from;
+               char *buf_ptr;
                unsigned long buf_len;
 
                if (contents_from) {
@@ -2113,8 +2114,8 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
                switch (st.st_mode & S_IFMT) {
                case S_IFREG:
                        if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
-                           textconv_object(read_from, mode, null_sha1, &buf.buf, &buf_len))
-                               buf.len = buf_len;
+                           textconv_object(read_from, mode, null_sha1, &buf_ptr, &buf_len))
+                               strbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);
                        else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
                                die_errno("cannot open or read '%s'", read_from);
                        break;
index 009b7138ac72c5845225ce1f801be908ede4e3b4..55cad766c7e3d284b1361b1beca8c5d51de96083 100644 (file)
@@ -705,7 +705,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
                             0);
 
-       if (!delete && !rename && !force_create && argc == 0)
+       if (!delete && !rename && argc == 0)
                list = 1;
 
        if (!!delete + !!rename + !!force_create + !!list > 1)
@@ -719,11 +719,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        else if (list)
                return print_ref_list(kinds, detached, verbose, abbrev,
                                      with_commit, argv);
-       else if (rename && (argc == 1))
-               rename_branch(head, argv[0], rename > 1);
-       else if (rename && (argc == 2))
-               rename_branch(argv[0], argv[1], rename > 1);
-       else if (argc <= 2) {
+       else if (rename) {
+               if (argc == 1)
+                       rename_branch(head, argv[0], rename > 1);
+               else if (argc == 2)
+                       rename_branch(argv[0], argv[1], rename > 1);
+               else
+                       usage_with_options(builtin_branch_usage, options);
+       } else if (argc > 0 && argc <= 2) {
                if (kinds != REF_LOCAL_BRANCH)
                        die(_("-a and -r options to 'git branch' do not make sense with a branch name"));
                create_branch(head, argv[0], (argc == 2) ? argv[1] : head,
index c46f2d18e10bcb3b1b458d4ae94d2d3522305632..8f2bebecf313a0e4b742f9327ec178c7e3547dd2 100644 (file)
@@ -1514,6 +1514,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        }
 
        unlink(git_path("CHERRY_PICK_HEAD"));
+       unlink(git_path("REVERT_HEAD"));
        unlink(git_path("MERGE_HEAD"));
        unlink(git_path("MERGE_MSG"));
        unlink(git_path("MERGE_MODE"));
index 1118689fb246b864ce758039543327c4304cdaa4..0fe638fc45c780e53901b8be22d3b4d715be3c30 100644 (file)
@@ -182,7 +182,7 @@ static int builtin_diff_combined(struct rev_info *revs,
                hashcpy((unsigned char *)(parent + i), ent[i].item->sha1);
        diff_tree_combined(parent[0], parent + 1, ents - 1,
                           revs->dense_combined_merges, revs);
-       free(parent);
+       free((void *)parent);
        return 0;
 }
 
index df1a88b51ae7773a15276d144113c0002fddb1cd..30d0dc82f053a5cbdfabcf474be816484ef3ca2b 100644 (file)
@@ -11,6 +11,7 @@
 #include "fsck.h"
 #include "parse-options.h"
 #include "dir.h"
+#include "progress.h"
 
 #define REACHABLE 0x0001
 #define SEEN      0x0002
@@ -27,8 +28,10 @@ static const char *head_points_at;
 static int errors_found;
 static int write_lost_and_found;
 static int verbose;
+static int show_progress = -1;
 #define ERROR_OBJECT 01
 #define ERROR_REACHABLE 02
+#define ERROR_PACK 04
 
 #ifdef NO_D_INO_IN_DIRENT
 #define SORT_DIRENT 0
@@ -137,7 +140,11 @@ static int traverse_one_object(struct object *obj)
 
 static int traverse_reachable(void)
 {
+       struct progress *progress = NULL;
+       unsigned int nr = 0;
        int result = 0;
+       if (show_progress)
+               progress = start_progress_delay("Checking connectivity", 0, 0, 2);
        while (pending.nr) {
                struct object_array_entry *entry;
                struct object *obj;
@@ -145,7 +152,9 @@ static int traverse_reachable(void)
                entry = pending.objects + --pending.nr;
                obj = entry->item;
                result |= traverse_one_object(obj);
+               display_progress(progress, ++nr);
        }
+       stop_progress(&progress);
        return !!result;
 }
 
@@ -281,14 +290,8 @@ static void check_connectivity(void)
        }
 }
 
-static int fsck_sha1(const unsigned char *sha1)
+static int fsck_obj(struct object *obj)
 {
-       struct object *obj = parse_object(sha1);
-       if (!obj) {
-               errors_found |= ERROR_OBJECT;
-               return error("%s: object corrupt or missing",
-                            sha1_to_hex(sha1));
-       }
        if (obj->flags & SEEN)
                return 0;
        obj->flags |= SEEN;
@@ -331,6 +334,29 @@ static int fsck_sha1(const unsigned char *sha1)
        return 0;
 }
 
+static int fsck_sha1(const unsigned char *sha1)
+{
+       struct object *obj = parse_object(sha1);
+       if (!obj) {
+               errors_found |= ERROR_OBJECT;
+               return error("%s: object corrupt or missing",
+                            sha1_to_hex(sha1));
+       }
+       return fsck_obj(obj);
+}
+
+static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type,
+                          unsigned long size, void *buffer, int *eaten)
+{
+       struct object *obj;
+       obj = parse_object_buffer(sha1, type, size, buffer, eaten);
+       if (!obj) {
+               errors_found |= ERROR_OBJECT;
+               return error("%s: object corrupt or missing", sha1_to_hex(sha1));
+       }
+       return fsck_obj(obj);
+}
+
 /*
  * This is the sorting chunk size: make it reasonably
  * big so that we can sort well..
@@ -512,15 +538,20 @@ static void get_default_heads(void)
 static void fsck_object_dir(const char *path)
 {
        int i;
+       struct progress *progress = NULL;
 
        if (verbose)
                fprintf(stderr, "Checking object directory\n");
 
+       if (show_progress)
+               progress = start_progress("Checking object directories", 256);
        for (i = 0; i < 256; i++) {
                static char dir[4096];
                sprintf(dir, "%s/%02x", path, i);
                fsck_dir(i, dir);
+               display_progress(progress, i+1);
        }
+       stop_progress(&progress);
        fsck_sha1_list();
 }
 
@@ -591,6 +622,7 @@ static struct option fsck_opts[] = {
        OPT_BOOLEAN(0, "strict", &check_strict, "enable more strict checking"),
        OPT_BOOLEAN(0, "lost-found", &write_lost_and_found,
                                "write dangling objects in .git/lost-found"),
+       OPT_BOOL(0, "progress", &show_progress, "show progress"),
        OPT_END(),
 };
 
@@ -603,6 +635,12 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
        read_replace_refs = 0;
 
        argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
+
+       if (show_progress == -1)
+               show_progress = isatty(2);
+       if (verbose)
+               show_progress = 0;
+
        if (write_lost_and_found) {
                check_full = 1;
                include_reflogs = 0;
@@ -622,20 +660,28 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 
        if (check_full) {
                struct packed_git *p;
+               uint32_t total = 0, count = 0;
+               struct progress *progress = NULL;
 
                prepare_packed_git();
-               for (p = packed_git; p; p = p->next)
-                       /* verify gives error messages itself */
-                       verify_pack(p);
 
+               if (show_progress) {
+                       for (p = packed_git; p; p = p->next) {
+                               if (open_pack_index(p))
+                                       continue;
+                               total += p->num_objects;
+                       }
+
+                       progress = start_progress("Checking objects", total);
+               }
                for (p = packed_git; p; p = p->next) {
-                       uint32_t j, num;
-                       if (open_pack_index(p))
-                               continue;
-                       num = p->num_objects;
-                       for (j = 0; j < num; j++)
-                               fsck_sha1(nth_packed_object_sha1(p, j));
+                       /* verify gives error messages itself */
+                       if (verify_pack(p, fsck_obj_buffer,
+                                       progress, count))
+                               errors_found |= ERROR_PACK;
+                       count += p->num_objects;
                }
+               stop_progress(&progress);
        }
 
        heads = 0;
index 0498094711d1addd40f526f0c76dd8ddb76ef550..271376d82b4391318fda9d5cfd5a0764d3768117 100644 (file)
@@ -32,7 +32,7 @@ static const char *prune_expire = "2.weeks.ago";
 static const char *argv_pack_refs[] = {"pack-refs", "--all", "--prune", NULL};
 static const char *argv_reflog[] = {"reflog", "expire", "--all", NULL};
 static const char *argv_repack[MAX_ADD] = {"repack", "-d", "-l", NULL};
-static const char *argv_prune[] = {"prune", "--expire", NULL, NULL};
+static const char *argv_prune[] = {"prune", "--expire", NULL, NULL, NULL};
 static const char *argv_rerere[] = {"rerere", "gc", NULL};
 
 static int gc_config(const char *var, const char *value, void *cb)
@@ -243,6 +243,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 
        if (prune_expire) {
                argv_prune[2] = prune_expire;
+               if (quiet)
+                       argv_prune[3] = "--no-progress";
                if (run_command_v_opt(argv_prune, RUN_GIT_CMD))
                        return error(FAILED_RUN, argv_prune[0]);
        }
index 3d7329d78c6e3ec31ed8ce03b8928c9ed24afb9e..988ea1d3324d6e32fcfd3b97da0fad5ae41b592c 100644 (file)
@@ -557,18 +557,19 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
 static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                     struct tree_desc *tree, struct strbuf *base, int tn_len)
 {
-       int hit = 0, match = 0;
+       int hit = 0;
+       enum interesting match = entry_not_interesting;
        struct name_entry entry;
        int old_baselen = base->len;
 
        while (tree_entry(tree, &entry)) {
-               int te_len = tree_entry_len(entry.path, entry.sha1);
+               int te_len = tree_entry_len(&entry);
 
-               if (match != 2) {
+               if (match != all_entries_interesting) {
                        match = tree_entry_interesting(&entry, base, tn_len, pathspec);
-                       if (match < 0)
+                       if (match == all_entries_not_interesting)
                                break;
-                       if (match == 0)
+                       if (match == entry_not_interesting)
                                continue;
                }
 
index dffd5ec1245865259fd4e72cc304286a1a5b4633..2870a6af6fbc868455f2961483cfbfdb065a1a14 100644 (file)
@@ -316,13 +316,15 @@ static void squash_message(struct commit *commit)
        struct rev_info rev;
        struct strbuf out = STRBUF_INIT;
        struct commit_list *j;
+       const char *filename;
        int fd;
        struct pretty_print_context ctx = {0};
 
        printf(_("Squash commit -- not updating HEAD\n"));
-       fd = open(git_path("SQUASH_MSG"), O_WRONLY | O_CREAT, 0666);
+       filename = git_path("SQUASH_MSG");
+       fd = open(filename, O_WRONLY | O_CREAT, 0666);
        if (fd < 0)
-               die_errno(_("Could not write to '%s'"), git_path("SQUASH_MSG"));
+               die_errno(_("Could not write to '%s'"), filename);
 
        init_revisions(&rev, NULL);
        rev.ignore_merges = 1;
@@ -492,14 +494,16 @@ static void merge_name(const char *remote, struct strbuf *msg)
 
        if (!strcmp(remote, "FETCH_HEAD") &&
                        !access(git_path("FETCH_HEAD"), R_OK)) {
+               const char *filename;
                FILE *fp;
                struct strbuf line = STRBUF_INIT;
                char *ptr;
 
-               fp = fopen(git_path("FETCH_HEAD"), "r");
+               filename = git_path("FETCH_HEAD");
+               fp = fopen(filename, "r");
                if (!fp)
                        die_errno(_("could not open '%s' for reading"),
-                                 git_path("FETCH_HEAD"));
+                                 filename);
                strbuf_getline(&line, fp, '\n');
                fclose(fp);
                ptr = strstr(line.buf, "\tnot-for-merge\t");
@@ -847,20 +851,22 @@ static void add_strategies(const char *string, unsigned attr)
 
 static void write_merge_msg(struct strbuf *msg)
 {
-       int fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
+       const char *filename = git_path("MERGE_MSG");
+       int fd = open(filename, O_WRONLY | O_CREAT, 0666);
        if (fd < 0)
                die_errno(_("Could not open '%s' for writing"),
-                         git_path("MERGE_MSG"));
+                         filename);
        if (write_in_full(fd, msg->buf, msg->len) != msg->len)
-               die_errno(_("Could not write to '%s'"), git_path("MERGE_MSG"));
+               die_errno(_("Could not write to '%s'"), filename);
        close(fd);
 }
 
 static void read_merge_msg(struct strbuf *msg)
 {
+       const char *filename = git_path("MERGE_MSG");
        strbuf_reset(msg);
-       if (strbuf_read_file(msg, git_path("MERGE_MSG"), 0) < 0)
-               die_errno(_("Could not read from '%s'"), git_path("MERGE_MSG"));
+       if (strbuf_read_file(msg, filename, 0) < 0)
+               die_errno(_("Could not read from '%s'"), filename);
 }
 
 static void write_merge_state(void);
@@ -948,13 +954,14 @@ static int finish_automerge(struct commit *head,
 
 static int suggest_conflicts(int renormalizing)
 {
+       const char *filename;
        FILE *fp;
        int pos;
 
-       fp = fopen(git_path("MERGE_MSG"), "a");
+       filename = git_path("MERGE_MSG");
+       fp = fopen(filename, "a");
        if (!fp)
-               die_errno(_("Could not open '%s' for writing"),
-                         git_path("MERGE_MSG"));
+               die_errno(_("Could not open '%s' for writing"), filename);
        fprintf(fp, "\nConflicts:\n");
        for (pos = 0; pos < active_nr; pos++) {
                struct cache_entry *ce = active_cache[pos];
@@ -1046,6 +1053,7 @@ static int setup_with_upstream(const char ***argv)
 
 static void write_merge_state(void)
 {
+       const char *filename;
        int fd;
        struct commit_list *j;
        struct strbuf buf = STRBUF_INIT;
@@ -1053,24 +1061,25 @@ static void write_merge_state(void)
        for (j = remoteheads; j; j = j->next)
                strbuf_addf(&buf, "%s\n",
                        sha1_to_hex(j->item->object.sha1));
-       fd = open(git_path("MERGE_HEAD"), O_WRONLY | O_CREAT, 0666);
+       filename = git_path("MERGE_HEAD");
+       fd = open(filename, O_WRONLY | O_CREAT, 0666);
        if (fd < 0)
-               die_errno(_("Could not open '%s' for writing"),
-                         git_path("MERGE_HEAD"));
+               die_errno(_("Could not open '%s' for writing"), filename);
        if (write_in_full(fd, buf.buf, buf.len) != buf.len)
-               die_errno(_("Could not write to '%s'"), git_path("MERGE_HEAD"));
+               die_errno(_("Could not write to '%s'"), filename);
        close(fd);
        strbuf_addch(&merge_msg, '\n');
        write_merge_msg(&merge_msg);
-       fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+       filename = git_path("MERGE_MODE");
+       fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
        if (fd < 0)
-               die_errno(_("Could not open '%s' for writing"),
-                         git_path("MERGE_MODE"));
+               die_errno(_("Could not open '%s' for writing"), filename);
        strbuf_reset(&buf);
        if (!allow_fast_forward)
                strbuf_addf(&buf, "no-ff");
        if (write_in_full(fd, buf.buf, buf.len) != buf.len)
-               die_errno(_("Could not write to '%s'"), git_path("MERGE_MODE"));
+               die_errno(_("Could not write to '%s'"), filename);
        close(fd);
 }
 
index 098395fda1932674e29f8d2cb332c722a6cb275f..4ae1c412d47bd581f22ec8b821a1111224dddd28 100644 (file)
@@ -60,6 +60,7 @@ static void write_tree(unsigned char *sha1)
        }
 
        write_sha1_file(buf.buf, buf.len, tree_type, sha1);
+       strbuf_release(&buf);
 }
 
 static const char *mktree_usage[] = {
index 7864056f1ee64b896a7378cc76555e2cf7c3fd89..1b374583c2751801dfae1d0d1861d28f81c7ad7b 100644 (file)
@@ -291,7 +291,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
                max = get_max_object_index();
                for (i = 0; i < max; i++) {
                        struct object *obj = get_indexed_object(i);
-                       if (!obj)
+                       if (!obj || obj->type != OBJ_COMMIT)
                                continue;
                        show_name(obj, NULL,
                                  always, allow_undefined, data.name_only);
index ba3705d1de0d91714be4c967a26ffd263e09878c..558cd34bccf66b1ef4cf9d66bfefe43fae76ceb3 100644 (file)
@@ -454,8 +454,8 @@ static int mark_tagged(const char *path, const unsigned char *sha1, int flag,
        return 0;
 }
 
-static void add_to_write_order(struct object_entry **wo,
-                              int *endp,
+static inline void add_to_write_order(struct object_entry **wo,
+                              unsigned int *endp,
                               struct object_entry *e)
 {
        if (e->filled)
@@ -465,32 +465,62 @@ static void add_to_write_order(struct object_entry **wo,
 }
 
 static void add_descendants_to_write_order(struct object_entry **wo,
-                                          int *endp,
+                                          unsigned int *endp,
                                           struct object_entry *e)
 {
-       struct object_entry *child;
-
-       for (child = e->delta_child; child; child = child->delta_sibling)
-               add_to_write_order(wo, endp, child);
-       for (child = e->delta_child; child; child = child->delta_sibling)
-               add_descendants_to_write_order(wo, endp, child);
+       int add_to_order = 1;
+       while (e) {
+               if (add_to_order) {
+                       struct object_entry *s;
+                       /* add this node... */
+                       add_to_write_order(wo, endp, e);
+                       /* all its siblings... */
+                       for (s = e->delta_sibling; s; s = s->delta_sibling) {
+                               add_to_write_order(wo, endp, s);
+                       }
+               }
+               /* drop down a level to add left subtree nodes if possible */
+               if (e->delta_child) {
+                       add_to_order = 1;
+                       e = e->delta_child;
+               } else {
+                       add_to_order = 0;
+                       /* our sibling might have some children, it is next */
+                       if (e->delta_sibling) {
+                               e = e->delta_sibling;
+                               continue;
+                       }
+                       /* go back to our parent node */
+                       e = e->delta;
+                       while (e && !e->delta_sibling) {
+                               /* we're on the right side of a subtree, keep
+                                * going up until we can go right again */
+                               e = e->delta;
+                       }
+                       if (!e) {
+                               /* done- we hit our original root node */
+                               return;
+                       }
+                       /* pass it off to sibling at this level */
+                       e = e->delta_sibling;
+               }
+       };
 }
 
 static void add_family_to_write_order(struct object_entry **wo,
-                                     int *endp,
+                                     unsigned int *endp,
                                      struct object_entry *e)
 {
        struct object_entry *root;
 
        for (root = e; root->delta; root = root->delta)
                ; /* nothing */
-       add_to_write_order(wo, endp, root);
        add_descendants_to_write_order(wo, endp, root);
 }
 
 static struct object_entry **compute_write_order(void)
 {
-       int i, wo_end;
+       unsigned int i, wo_end, last_untagged;
 
        struct object_entry **wo = xmalloc(nr_objects * sizeof(*wo));
 
@@ -506,8 +536,8 @@ static struct object_entry **compute_write_order(void)
         * Make sure delta_sibling is sorted in the original
         * recency order.
         */
-       for (i = nr_objects - 1; 0 <= i; i--) {
-               struct object_entry *e = &objects[i];
+       for (i = nr_objects; i > 0;) {
+               struct object_entry *e = &objects[--i];
                if (!e->delta)
                        continue;
                /* Mark me as the first child */
@@ -521,7 +551,7 @@ static struct object_entry **compute_write_order(void)
        for_each_tag_ref(mark_tagged, NULL);
 
        /*
-        * Give the commits in the original recency order until
+        * Give the objects in the original recency order until
         * we see a tagged tip.
         */
        for (i = wo_end = 0; i < nr_objects; i++) {
@@ -529,6 +559,7 @@ static struct object_entry **compute_write_order(void)
                        break;
                add_to_write_order(wo, &wo_end, &objects[i]);
        }
+       last_untagged = i;
 
        /*
         * Then fill all the tagged tips.
@@ -541,7 +572,7 @@ static struct object_entry **compute_write_order(void)
        /*
         * And then all remaining commits and tags.
         */
-       for (i = 0; i < nr_objects; i++) {
+       for (i = last_untagged; i < nr_objects; i++) {
                if (objects[i].type != OBJ_COMMIT &&
                    objects[i].type != OBJ_TAG)
                        continue;
@@ -551,7 +582,7 @@ static struct object_entry **compute_write_order(void)
        /*
         * And then all the trees.
         */
-       for (i = 0; i < nr_objects; i++) {
+       for (i = last_untagged; i < nr_objects; i++) {
                if (objects[i].type != OBJ_TREE)
                        continue;
                add_to_write_order(wo, &wo_end, &objects[i]);
@@ -560,8 +591,13 @@ static struct object_entry **compute_write_order(void)
        /*
         * Finally all the rest in really tight order
         */
-       for (i = 0; i < nr_objects; i++)
-               add_family_to_write_order(wo, &wo_end, &objects[i]);
+       for (i = last_untagged; i < nr_objects; i++) {
+               if (!objects[i].filled)
+                       add_family_to_write_order(wo, &wo_end, &objects[i]);
+       }
+
+       if (wo_end != nr_objects)
+               die("ordered %u objects, expected %"PRIu32, wo_end, nr_objects);
 
        return wo;
 }
@@ -979,7 +1015,7 @@ static void add_pbase_object(struct tree_desc *tree,
        while (tree_entry(tree,&entry)) {
                if (S_ISGITLINK(entry.mode))
                        continue;
-               cmp = tree_entry_len(entry.path, entry.sha1) != cmplen ? 1 :
+               cmp = tree_entry_len(&entry) != cmplen ? 1 :
                      memcmp(name, entry.path, cmplen);
                if (cmp > 0)
                        continue;
index e65690ba370511072dfa1e64838eef5e5686aac9..58d7cb83240ecef7ab3ff82f3aa92959ec7a62fe 100644 (file)
@@ -5,6 +5,7 @@
 #include "builtin.h"
 #include "reachable.h"
 #include "parse-options.h"
+#include "progress.h"
 #include "dir.h"
 
 static const char * const prune_usage[] = {
@@ -14,6 +15,7 @@ static const char * const prune_usage[] = {
 static int show_only;
 static int verbose;
 static unsigned long expire;
+static int show_progress = -1;
 
 static int prune_tmp_object(const char *path, const char *filename)
 {
@@ -124,9 +126,11 @@ static void remove_temporary_files(const char *path)
 int cmd_prune(int argc, const char **argv, const char *prefix)
 {
        struct rev_info revs;
+       struct progress *progress = NULL;
        const struct option options[] = {
                OPT__DRY_RUN(&show_only, "do not remove, show only"),
                OPT__VERBOSE(&verbose, "report pruned objects"),
+               OPT_BOOL(0, "progress", &show_progress, "show progress"),
                OPT_DATE(0, "expire", &expire,
                         "expire objects older than <time>"),
                OPT_END()
@@ -152,7 +156,14 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
                else
                        die("unrecognized argument: %s", name);
        }
-       mark_reachable_objects(&revs, 1);
+
+       if (show_progress == -1)
+               show_progress = isatty(2);
+       if (show_progress)
+               progress = start_progress_delay("Checking connectivity", 0, 0, 2);
+
+       mark_reachable_objects(&revs, 1, progress);
+       stop_progress(&progress);
        prune_object_dir(get_object_directory());
 
        prune_packed_objects(show_only);
index 261b610d24017557c137d83a9c005b662e795b6a..7ec68a1e8089f74ce7c70fecd86d5c18264ce4bc 100644 (file)
@@ -634,7 +634,7 @@ static int command_singleton_iterator(void *cb_data, unsigned char sha1[20])
        struct command **cmd_list = cb_data;
        struct command *cmd = *cmd_list;
 
-       if (!cmd)
+       if (!cmd || is_null_sha1(cmd->new_sha1))
                return -1; /* end of list */
        *cmd_list = NULL; /* this returns only one */
        hashcpy(sha1, cmd->new_sha1);
@@ -659,11 +659,16 @@ static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20])
        struct command **cmd_list = cb_data;
        struct command *cmd = *cmd_list;
 
-       if (!cmd)
-               return -1; /* end of list */
-       *cmd_list = cmd->next;
-       hashcpy(sha1, cmd->new_sha1);
-       return 0;
+       while (cmd) {
+               if (!is_null_sha1(cmd->new_sha1)) {
+                       hashcpy(sha1, cmd->new_sha1);
+                       *cmd_list = cmd->next;
+                       return 0;
+               }
+               cmd = cmd->next;
+       }
+       *cmd_list = NULL;
+       return -1; /* end of list */
 }
 
 static void execute_commands(struct command *commands, const char *unpacker_error)
index 3a9c80f3dbfe26d5623c118fc0fcaa257e01b973..062d7dad1b5af720e70adcaa05b60bf68977b05c 100644 (file)
@@ -647,7 +647,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
                init_revisions(&cb.revs, prefix);
                if (cb.verbose)
                        printf("Marking reachable objects...");
-               mark_reachable_objects(&cb.revs, 0);
+               mark_reachable_objects(&cb.revs, 0, NULL);
                if (cb.verbose)
                        putchar('\n');
        }
index 733514979969f69ad45448a67d981b621bbee146..c810643815e38f4ada805e2af49973e4e0051801 100644 (file)
@@ -1399,7 +1399,7 @@ static int set_branches(int argc, const char **argv)
                             builtin_remote_setbranches_usage, 0);
        if (argc == 0) {
                error("no remote specified");
-               usage_with_options(builtin_remote_seturl_usage, options);
+               usage_with_options(builtin_remote_setbranches_usage, options);
        }
        argv[argc] = NULL;
 
@@ -1427,7 +1427,7 @@ static int set_url(int argc, const char **argv)
                            "delete URLs"),
                OPT_END()
        };
-       argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage,
+       argc = parse_options(argc, argv, NULL, options, builtin_remote_seturl_usage,
                             PARSE_OPT_KEEP_ARGV0);
 
        if (add_mode && delete_mode)
index 87df70edc33fcc71177b863e6ced870330e505d0..1ea525c10e4c00b66006bf46465ebd490823f25f 100644 (file)
@@ -40,7 +40,12 @@ static const char * const cherry_pick_usage[] = {
 };
 
 enum replay_action { REVERT, CHERRY_PICK };
-enum replay_subcommand { REPLAY_NONE, REPLAY_RESET, REPLAY_CONTINUE };
+enum replay_subcommand {
+       REPLAY_NONE,
+       REPLAY_REMOVE_STATE,
+       REPLAY_CONTINUE,
+       REPLAY_ROLLBACK
+};
 
 struct replay_opts {
        enum replay_action action;
@@ -133,11 +138,13 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
 {
        const char * const * usage_str = revert_or_cherry_pick_usage(opts);
        const char *me = action_name(opts);
-       int reset = 0;
+       int remove_state = 0;
        int contin = 0;
+       int rollback = 0;
        struct option options[] = {
-               OPT_BOOLEAN(0, "reset", &reset, "forget the current operation"),
-               OPT_BOOLEAN(0, "continue", &contin, "continue the current operation"),
+               OPT_BOOLEAN(0, "quit", &remove_state, "end revert or cherry-pick sequence"),
+               OPT_BOOLEAN(0, "continue", &contin, "resume revert or cherry-pick sequence"),
+               OPT_BOOLEAN(0, "abort", &rollback, "cancel revert or cherry-pick sequence"),
                OPT_BOOLEAN('n', "no-commit", &opts->no_commit, "don't automatically commit"),
                OPT_BOOLEAN('e', "edit", &opts->edit, "edit the commit message"),
                OPT_NOOP_NOARG('r', NULL),
@@ -168,25 +175,32 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
 
        /* Check for incompatible subcommands */
        verify_opt_mutually_compatible(me,
-                               "--reset", reset,
+                               "--quit", remove_state,
                                "--continue", contin,
+                               "--abort", rollback,
                                NULL);
 
        /* Set the subcommand */
-       if (reset)
-               opts->subcommand = REPLAY_RESET;
+       if (remove_state)
+               opts->subcommand = REPLAY_REMOVE_STATE;
        else if (contin)
                opts->subcommand = REPLAY_CONTINUE;
+       else if (rollback)
+               opts->subcommand = REPLAY_ROLLBACK;
        else
                opts->subcommand = REPLAY_NONE;
 
        /* Check for incompatible command line arguments */
        if (opts->subcommand != REPLAY_NONE) {
                char *this_operation;
-               if (opts->subcommand == REPLAY_RESET)
-                       this_operation = "--reset";
-               else
+               if (opts->subcommand == REPLAY_REMOVE_STATE)
+                       this_operation = "--quit";
+               else if (opts->subcommand == REPLAY_CONTINUE)
                        this_operation = "--continue";
+               else {
+                       assert(opts->subcommand == REPLAY_ROLLBACK);
+                       this_operation = "--abort";
+               }
 
                verify_opt_compatible(me, this_operation,
                                "--no-commit", opts->no_commit,
@@ -286,19 +300,20 @@ static char *get_encoding(const char *message)
        return NULL;
 }
 
-static void write_cherry_pick_head(struct commit *commit)
+static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
 {
+       const char *filename;
        int fd;
        struct strbuf buf = STRBUF_INIT;
 
        strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1));
 
-       fd = open(git_path("CHERRY_PICK_HEAD"), O_WRONLY | O_CREAT, 0666);
+       filename = git_path("%s", pseudoref);
+       fd = open(filename, O_WRONLY | O_CREAT, 0666);
        if (fd < 0)
-               die_errno(_("Could not open '%s' for writing"),
-                         git_path("CHERRY_PICK_HEAD"));
+               die_errno(_("Could not open '%s' for writing"), filename);
        if (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd))
-               die_errno(_("Could not write to '%s'"), git_path("CHERRY_PICK_HEAD"));
+               die_errno(_("Could not write to '%s'"), filename);
        strbuf_release(&buf);
 }
 
@@ -331,7 +346,7 @@ static void write_message(struct strbuf *msgbuf, const char *filename)
        int msg_fd = hold_lock_file_for_update(&msg_file, filename,
                                               LOCK_DIE_ON_ERROR);
        if (write_in_full(msg_fd, msgbuf->buf, msgbuf->len) < 0)
-               die_errno(_("Could not write to %s."), filename);
+               die_errno(_("Could not write to %s"), filename);
        strbuf_release(msgbuf);
        if (commit_lock_file(&msg_file) < 0)
                die(_("Error wrapping up %s"), filename);
@@ -593,7 +608,9 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
         * write it at all.
         */
        if (opts->action == CHERRY_PICK && !opts->no_commit && (res == 0 || res == 1))
-               write_cherry_pick_head(commit);
+               write_cherry_pick_head(commit, "CHERRY_PICK_HEAD");
+       if (opts->action == REVERT && ((opts->no_commit && res == 0) || res == 1))
+               write_cherry_pick_head(commit, "REVERT_HEAD");
 
        if (res) {
                error(opts->action == REVERT
@@ -767,7 +784,7 @@ static void read_populate_todo(struct commit_list **todo_list,
 
        fd = open(todo_file, O_RDONLY);
        if (fd < 0)
-               die_errno(_("Could not open %s."), todo_file);
+               die_errno(_("Could not open %s"), todo_file);
        if (strbuf_read(&buf, fd, 0) < 0) {
                close(fd);
                strbuf_release(&buf);
@@ -842,10 +859,13 @@ static int create_seq_dir(void)
 {
        const char *seq_dir = git_path(SEQ_DIR);
 
-       if (file_exists(seq_dir))
-               return error(_("%s already exists."), seq_dir);
+       if (file_exists(seq_dir)) {
+               error(_("a cherry-pick or revert is already in progress"));
+               advise(_("try \"git cherry-pick (--continue | --quit | --abort)\""));
+               return -1;
+       }
        else if (mkdir(seq_dir, 0777) < 0)
-               die_errno(_("Could not create sequencer directory '%s'."), seq_dir);
+               die_errno(_("Could not create sequencer directory %s"), seq_dir);
        return 0;
 }
 
@@ -859,11 +879,77 @@ static void save_head(const char *head)
        fd = hold_lock_file_for_update(&head_lock, head_file, LOCK_DIE_ON_ERROR);
        strbuf_addf(&buf, "%s\n", head);
        if (write_in_full(fd, buf.buf, buf.len) < 0)
-               die_errno(_("Could not write to %s."), head_file);
+               die_errno(_("Could not write to %s"), head_file);
        if (commit_lock_file(&head_lock) < 0)
                die(_("Error wrapping up %s."), head_file);
 }
 
+static int reset_for_rollback(const unsigned char *sha1)
+{
+       const char *argv[4];    /* reset --merge <arg> + NULL */
+       argv[0] = "reset";
+       argv[1] = "--merge";
+       argv[2] = sha1_to_hex(sha1);
+       argv[3] = NULL;
+       return run_command_v_opt(argv, RUN_GIT_CMD);
+}
+
+static int rollback_single_pick(void)
+{
+       unsigned char head_sha1[20];
+
+       if (!file_exists(git_path("CHERRY_PICK_HEAD")) &&
+           !file_exists(git_path("REVERT_HEAD")))
+               return error(_("no cherry-pick or revert in progress"));
+       if (!resolve_ref("HEAD", head_sha1, 0, NULL))
+               return error(_("cannot resolve HEAD"));
+       if (is_null_sha1(head_sha1))
+               return error(_("cannot abort from a branch yet to be born"));
+       return reset_for_rollback(head_sha1);
+}
+
+static int sequencer_rollback(struct replay_opts *opts)
+{
+       const char *filename;
+       FILE *f;
+       unsigned char sha1[20];
+       struct strbuf buf = STRBUF_INIT;
+
+       filename = git_path(SEQ_HEAD_FILE);
+       f = fopen(filename, "r");
+       if (!f && errno == ENOENT) {
+               /*
+                * There is no multiple-cherry-pick in progress.
+                * If CHERRY_PICK_HEAD or REVERT_HEAD indicates
+                * a single-cherry-pick in progress, abort that.
+                */
+               return rollback_single_pick();
+       }
+       if (!f)
+               return error(_("cannot open %s: %s"), filename,
+                                               strerror(errno));
+       if (strbuf_getline(&buf, f, '\n')) {
+               error(_("cannot read %s: %s"), filename, ferror(f) ?
+                       strerror(errno) : _("unexpected end of file"));
+               fclose(f);
+               goto fail;
+       }
+       fclose(f);
+       if (get_sha1_hex(buf.buf, sha1) || buf.buf[40] != '\0') {
+               error(_("stored pre-cherry-pick HEAD file '%s' is corrupt"),
+                       filename);
+               goto fail;
+       }
+       if (reset_for_rollback(sha1))
+               goto fail;
+       remove_sequencer_state(1);
+       strbuf_release(&buf);
+       return 0;
+fail:
+       strbuf_release(&buf);
+       return -1;
+}
+
 static void save_todo(struct commit_list *todo_list, struct replay_opts *opts)
 {
        const char *todo_file = git_path(SEQ_TODO_FILE);
@@ -876,7 +962,7 @@ static void save_todo(struct commit_list *todo_list, struct replay_opts *opts)
                die(_("Could not format %s."), todo_file);
        if (write_in_full(fd, buf.buf, buf.len) < 0) {
                strbuf_release(&buf);
-               die_errno(_("Could not write to %s."), todo_file);
+               die_errno(_("Could not write to %s"), todo_file);
        }
        if (commit_lock_file(&todo_lock) < 0) {
                strbuf_release(&buf);
@@ -964,43 +1050,41 @@ static int pick_revisions(struct replay_opts *opts)
         * cherry-pick should be handled differently from an existing
         * one that is being continued
         */
-       if (opts->subcommand == REPLAY_RESET) {
+       if (opts->subcommand == REPLAY_REMOVE_STATE) {
                remove_sequencer_state(1);
                return 0;
-       } else if (opts->subcommand == REPLAY_CONTINUE) {
+       }
+       if (opts->subcommand == REPLAY_ROLLBACK)
+               return sequencer_rollback(opts);
+       if (opts->subcommand == REPLAY_CONTINUE) {
                if (!file_exists(git_path(SEQ_TODO_FILE)))
-                       goto error;
+                       return error(_("No %s in progress"), action_name(opts));
                read_populate_opts(&opts);
                read_populate_todo(&todo_list, opts);
 
                /* Verify that the conflict has been resolved */
                if (!index_differs_from("HEAD", 0))
                        todo_list = todo_list->next;
-       } else {
-               /*
-                * Start a new cherry-pick/ revert sequence; but
-                * first, make sure that an existing one isn't in
-                * progress
-                */
+               return pick_commits(todo_list, opts);
+       }
 
-               walk_revs_populate_todo(&todo_list, opts);
-               if (create_seq_dir() < 0) {
-                       error(_("A cherry-pick or revert is in progress."));
-                       advise(_("Use --continue to continue the operation"));
-                       advise(_("or --reset to forget about it"));
-                       return -1;
-               }
-               if (get_sha1("HEAD", sha1)) {
-                       if (opts->action == REVERT)
-                               return error(_("Can't revert as initial commit"));
-                       return error(_("Can't cherry-pick into empty head"));
-               }
-               save_head(sha1_to_hex(sha1));
-               save_opts(opts);
+       /*
+        * Start a new cherry-pick/ revert sequence; but
+        * first, make sure that an existing one isn't in
+        * progress
+        */
+
+       walk_revs_populate_todo(&todo_list, opts);
+       if (create_seq_dir() < 0)
+               return -1;
+       if (get_sha1("HEAD", sha1)) {
+               if (opts->action == REVERT)
+                       return error(_("Can't revert as initial commit"));
+               return error(_("Can't cherry-pick into empty head"));
        }
+       save_head(sha1_to_hex(sha1));
+       save_opts(opts);
        return pick_commits(todo_list, opts);
-error:
-       return error(_("No %s in progress"), action_name(opts));
 }
 
 int cmd_revert(int argc, const char **argv, const char *prefix)
index 4d3b93fedb5f2eca68edca15ca1e10cb60176d36..1288ffcc52530f8ef9561acd2eb2ec5322c9e230 100644 (file)
@@ -22,8 +22,6 @@ static size_t cleanup(char *line, size_t len)
  * Remove empty lines from the beginning and end
  * and also trailing spaces from every line.
  *
- * Note that the buffer will not be NUL-terminated.
- *
  * Turn multiple consecutive empty lines between paragraphs
  * into just one empty line.
  *
diff --git a/compat/strtoimax.c b/compat/strtoimax.c
new file mode 100644 (file)
index 0000000..ac09ed8
--- /dev/null
@@ -0,0 +1,10 @@
+#include "../git-compat-util.h"
+
+intmax_t gitstrtoimax (const char *nptr, char **endptr, int base)
+{
+#if defined(NO_STRTOULL)
+       return strtol(nptr, endptr, base);
+#else
+       return strtoll(nptr, endptr, base);
+#endif
+}
diff --git a/compat/win32/poll.c b/compat/win32/poll.c
new file mode 100644 (file)
index 0000000..403eaa7
--- /dev/null
@@ -0,0 +1,606 @@
+/* Emulation for poll(2)
+   Contributed by Paolo Bonzini.
+
+   Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
+
+   This file is part of gnulib.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Tell gcc not to warn about the (nfd < 0) tests, below.  */
+#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
+
+#include <malloc.h>
+
+#include <sys/types.h>
+
+/* Specification.  */
+#include <poll.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <assert.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_NATIVE
+# if defined (_MSC_VER)
+#  define _WIN32_WINNT 0x0502
+# endif
+# include <winsock2.h>
+# include <windows.h>
+# include <io.h>
+# include <stdio.h>
+# include <conio.h>
+#else
+# include <sys/time.h>
+# include <sys/socket.h>
+# include <sys/select.h>
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+
+#include <time.h>
+
+#ifndef INFTIM
+# define INFTIM (-1)
+#endif
+
+/* BeOS does not have MSG_PEEK.  */
+#ifndef MSG_PEEK
+# define MSG_PEEK 0
+#endif
+
+#ifdef WIN32_NATIVE
+
+#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
+
+static BOOL
+IsSocketHandle (HANDLE h)
+{
+  WSANETWORKEVENTS ev;
+
+  if (IsConsoleHandle (h))
+    return FALSE;
+
+  /* Under Wine, it seems that getsockopt returns 0 for pipes too.
+     WSAEnumNetworkEvents instead distinguishes the two correctly.  */
+  ev.lNetworkEvents = 0xDEADBEEF;
+  WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
+  return ev.lNetworkEvents != 0xDEADBEEF;
+}
+
+/* Declare data structures for ntdll functions.  */
+typedef struct _FILE_PIPE_LOCAL_INFORMATION {
+  ULONG NamedPipeType;
+  ULONG NamedPipeConfiguration;
+  ULONG MaximumInstances;
+  ULONG CurrentInstances;
+  ULONG InboundQuota;
+  ULONG ReadDataAvailable;
+  ULONG OutboundQuota;
+  ULONG WriteQuotaAvailable;
+  ULONG NamedPipeState;
+  ULONG NamedPipeEnd;
+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
+
+typedef struct _IO_STATUS_BLOCK
+{
+  union {
+    DWORD Status;
+    PVOID Pointer;
+  } u;
+  ULONG_PTR Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+typedef enum _FILE_INFORMATION_CLASS {
+  FilePipeLocalInformation = 24
+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+
+typedef DWORD (WINAPI *PNtQueryInformationFile)
+        (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
+
+# ifndef PIPE_BUF
+#  define PIPE_BUF      512
+# endif
+
+/* Compute revents values for file handle H.  If some events cannot happen
+   for the handle, eliminate them from *P_SOUGHT.  */
+
+static int
+win32_compute_revents (HANDLE h, int *p_sought)
+{
+  int i, ret, happened;
+  INPUT_RECORD *irbuffer;
+  DWORD avail, nbuffer;
+  BOOL bRet;
+  IO_STATUS_BLOCK iosb;
+  FILE_PIPE_LOCAL_INFORMATION fpli;
+  static PNtQueryInformationFile NtQueryInformationFile;
+  static BOOL once_only;
+
+  switch (GetFileType (h))
+    {
+    case FILE_TYPE_PIPE:
+      if (!once_only)
+       {
+         NtQueryInformationFile = (PNtQueryInformationFile)
+           GetProcAddress (GetModuleHandle ("ntdll.dll"),
+                           "NtQueryInformationFile");
+         once_only = TRUE;
+       }
+
+      happened = 0;
+      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
+       {
+         if (avail)
+           happened |= *p_sought & (POLLIN | POLLRDNORM);
+       }
+      else if (GetLastError () == ERROR_BROKEN_PIPE)
+       happened |= POLLHUP;
+
+      else
+       {
+         /* It was the write-end of the pipe.  Check if it is writable.
+            If NtQueryInformationFile fails, optimistically assume the pipe is
+            writable.  This could happen on Win9x, where NtQueryInformationFile
+            is not available, or if we inherit a pipe that doesn't permit
+            FILE_READ_ATTRIBUTES access on the write end (I think this should
+            not happen since WinXP SP2; WINE seems fine too).  Otherwise,
+            ensure that enough space is available for atomic writes.  */
+         memset (&iosb, 0, sizeof (iosb));
+         memset (&fpli, 0, sizeof (fpli));
+
+         if (!NtQueryInformationFile
+             || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
+                                        FilePipeLocalInformation)
+             || fpli.WriteQuotaAvailable >= PIPE_BUF
+             || (fpli.OutboundQuota < PIPE_BUF &&
+                 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
+           happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
+       }
+      return happened;
+
+    case FILE_TYPE_CHAR:
+      ret = WaitForSingleObject (h, 0);
+      if (!IsConsoleHandle (h))
+       return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
+
+      nbuffer = avail = 0;
+      bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
+      if (bRet)
+       {
+         /* Input buffer.  */
+         *p_sought &= POLLIN | POLLRDNORM;
+         if (nbuffer == 0)
+           return POLLHUP;
+         if (!*p_sought)
+           return 0;
+
+         irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
+         bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
+         if (!bRet || avail == 0)
+           return POLLHUP;
+
+         for (i = 0; i < avail; i++)
+           if (irbuffer[i].EventType == KEY_EVENT)
+             return *p_sought;
+         return 0;
+       }
+      else
+       {
+         /* Screen buffer.  */
+         *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
+         return *p_sought;
+       }
+
+    default:
+      ret = WaitForSingleObject (h, 0);
+      if (ret == WAIT_OBJECT_0)
+       return *p_sought & ~(POLLPRI | POLLRDBAND);
+
+      return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
+    }
+}
+
+/* Convert fd_sets returned by select into revents values.  */
+
+static int
+win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
+{
+  int happened = 0;
+
+  if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
+    happened |= (POLLIN | POLLRDNORM) & sought;
+
+  else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
+    {
+      int r, error;
+
+      char data[64];
+      WSASetLastError (0);
+      r = recv (h, data, sizeof (data), MSG_PEEK);
+      error = WSAGetLastError ();
+      WSASetLastError (0);
+
+      if (r > 0 || error == WSAENOTCONN)
+       happened |= (POLLIN | POLLRDNORM) & sought;
+
+      /* Distinguish hung-up sockets from other errors.  */
+      else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
+              || error == WSAECONNABORTED || error == WSAENETRESET)
+       happened |= POLLHUP;
+
+      else
+       happened |= POLLERR;
+    }
+
+  if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
+    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
+
+  if (lNetworkEvents & FD_OOB)
+    happened |= (POLLPRI | POLLRDBAND) & sought;
+
+  return happened;
+}
+
+#else /* !MinGW */
+
+/* Convert select(2) returned fd_sets into poll(2) revents values.  */
+static int
+compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
+{
+  int happened = 0;
+  if (FD_ISSET (fd, rfds))
+    {
+      int r;
+      int socket_errno;
+
+# if defined __MACH__ && defined __APPLE__
+      /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
+        for some kinds of descriptors.  Detect if this descriptor is a
+        connected socket, a server socket, or something else using a
+        0-byte recv, and use ioctl(2) to detect POLLHUP.  */
+      r = recv (fd, NULL, 0, MSG_PEEK);
+      socket_errno = (r < 0) ? errno : 0;
+      if (r == 0 || socket_errno == ENOTSOCK)
+       ioctl (fd, FIONREAD, &r);
+# else
+      char data[64];
+      r = recv (fd, data, sizeof (data), MSG_PEEK);
+      socket_errno = (r < 0) ? errno : 0;
+# endif
+      if (r == 0)
+       happened |= POLLHUP;
+
+      /* If the event happened on an unconnected server socket,
+        that's fine. */
+      else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
+       happened |= (POLLIN | POLLRDNORM) & sought;
+
+      /* Distinguish hung-up sockets from other errors.  */
+      else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
+              || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
+       happened |= POLLHUP;
+
+      else
+       happened |= POLLERR;
+    }
+
+  if (FD_ISSET (fd, wfds))
+    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
+
+  if (FD_ISSET (fd, efds))
+    happened |= (POLLPRI | POLLRDBAND) & sought;
+
+  return happened;
+}
+#endif /* !MinGW */
+
+int
+poll (struct pollfd *pfd, nfds_t nfd, int timeout)
+{
+#ifndef WIN32_NATIVE
+  fd_set rfds, wfds, efds;
+  struct timeval tv;
+  struct timeval *ptv;
+  int maxfd, rc;
+  nfds_t i;
+
+# ifdef _SC_OPEN_MAX
+  static int sc_open_max = -1;
+
+  if (nfd < 0
+      || (nfd > sc_open_max
+         && (sc_open_max != -1
+             || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
+    {
+      errno = EINVAL;
+      return -1;
+    }
+# else /* !_SC_OPEN_MAX */
+#  ifdef OPEN_MAX
+  if (nfd < 0 || nfd > OPEN_MAX)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+#  endif /* OPEN_MAX -- else, no check is needed */
+# endif /* !_SC_OPEN_MAX */
+
+  /* EFAULT is not necessary to implement, but let's do it in the
+     simplest case. */
+  if (!pfd)
+    {
+      errno = EFAULT;
+      return -1;
+    }
+
+  /* convert timeout number into a timeval structure */
+  if (timeout == 0)
+    {
+      ptv = &tv;
+      ptv->tv_sec = 0;
+      ptv->tv_usec = 0;
+    }
+  else if (timeout > 0)
+    {
+      ptv = &tv;
+      ptv->tv_sec = timeout / 1000;
+      ptv->tv_usec = (timeout % 1000) * 1000;
+    }
+  else if (timeout == INFTIM)
+    /* wait forever */
+    ptv = NULL;
+  else
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  /* create fd sets and determine max fd */
+  maxfd = -1;
+  FD_ZERO (&rfds);
+  FD_ZERO (&wfds);
+  FD_ZERO (&efds);
+  for (i = 0; i < nfd; i++)
+    {
+      if (pfd[i].fd < 0)
+       continue;
+
+      if (pfd[i].events & (POLLIN | POLLRDNORM))
+       FD_SET (pfd[i].fd, &rfds);
+
+      /* see select(2): "the only exceptional condition detectable
+        is out-of-band data received on a socket", hence we push
+        POLLWRBAND events onto wfds instead of efds. */
+      if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
+       FD_SET (pfd[i].fd, &wfds);
+      if (pfd[i].events & (POLLPRI | POLLRDBAND))
+       FD_SET (pfd[i].fd, &efds);
+      if (pfd[i].fd >= maxfd
+         && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
+                              | POLLRDNORM | POLLRDBAND
+                              | POLLWRNORM | POLLWRBAND)))
+       {
+         maxfd = pfd[i].fd;
+         if (maxfd > FD_SETSIZE)
+           {
+             errno = EOVERFLOW;
+             return -1;
+           }
+       }
+    }
+
+  /* examine fd sets */
+  rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
+  if (rc < 0)
+    return rc;
+
+  /* establish results */
+  rc = 0;
+  for (i = 0; i < nfd; i++)
+    if (pfd[i].fd < 0)
+      pfd[i].revents = 0;
+    else
+      {
+       int happened = compute_revents (pfd[i].fd, pfd[i].events,
+                                       &rfds, &wfds, &efds);
+       if (happened)
+         {
+           pfd[i].revents = happened;
+           rc++;
+         }
+      }
+
+  return rc;
+#else
+  static struct timeval tv0;
+  static HANDLE hEvent;
+  WSANETWORKEVENTS ev;
+  HANDLE h, handle_array[FD_SETSIZE + 2];
+  DWORD ret, wait_timeout, nhandles;
+  fd_set rfds, wfds, xfds;
+  BOOL poll_again;
+  MSG msg;
+  int rc = 0;
+  nfds_t i;
+
+  if (nfd < 0 || timeout < -1)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  if (!hEvent)
+    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+
+restart:
+  handle_array[0] = hEvent;
+  nhandles = 1;
+  FD_ZERO (&rfds);
+  FD_ZERO (&wfds);
+  FD_ZERO (&xfds);
+
+  /* Classify socket handles and create fd sets. */
+  for (i = 0; i < nfd; i++)
+    {
+      int sought = pfd[i].events;
+      pfd[i].revents = 0;
+      if (pfd[i].fd < 0)
+       continue;
+      if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
+                     | POLLPRI | POLLRDBAND)))
+       continue;
+
+      h = (HANDLE) _get_osfhandle (pfd[i].fd);
+      assert (h != NULL);
+      if (IsSocketHandle (h))
+       {
+         int requested = FD_CLOSE;
+
+         /* see above; socket handles are mapped onto select.  */
+         if (sought & (POLLIN | POLLRDNORM))
+           {
+             requested |= FD_READ | FD_ACCEPT;
+             FD_SET ((SOCKET) h, &rfds);
+           }
+         if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
+           {
+             requested |= FD_WRITE | FD_CONNECT;
+             FD_SET ((SOCKET) h, &wfds);
+           }
+         if (sought & (POLLPRI | POLLRDBAND))
+           {
+             requested |= FD_OOB;
+             FD_SET ((SOCKET) h, &xfds);
+           }
+
+         if (requested)
+           WSAEventSelect ((SOCKET) h, hEvent, requested);
+       }
+      else
+       {
+         /* Poll now.  If we get an event, do not poll again.  Also,
+            screen buffer handles are waitable, and they'll block until
+            a character is available.  win32_compute_revents eliminates
+            bits for the "wrong" direction. */
+         pfd[i].revents = win32_compute_revents (h, &sought);
+         if (sought)
+           handle_array[nhandles++] = h;
+         if (pfd[i].revents)
+           timeout = 0;
+       }
+    }
+
+  if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
+    {
+      /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
+        no need to call select again.  */
+      poll_again = FALSE;
+      wait_timeout = 0;
+    }
+  else
+    {
+      poll_again = TRUE;
+      if (timeout == INFTIM)
+       wait_timeout = INFINITE;
+      else
+       wait_timeout = timeout;
+    }
+
+  for (;;)
+    {
+      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
+                                      wait_timeout, QS_ALLINPUT);
+
+      if (ret == WAIT_OBJECT_0 + nhandles)
+       {
+         /* new input of some other kind */
+         BOOL bRet;
+         while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
+           {
+             TranslateMessage (&msg);
+             DispatchMessage (&msg);
+           }
+       }
+      else
+       break;
+    }
+
+  if (poll_again)
+    select (0, &rfds, &wfds, &xfds, &tv0);
+
+  /* Place a sentinel at the end of the array.  */
+  handle_array[nhandles] = NULL;
+  nhandles = 1;
+  for (i = 0; i < nfd; i++)
+    {
+      int happened;
+
+      if (pfd[i].fd < 0)
+       continue;
+      if (!(pfd[i].events & (POLLIN | POLLRDNORM |
+                            POLLOUT | POLLWRNORM | POLLWRBAND)))
+       continue;
+
+      h = (HANDLE) _get_osfhandle (pfd[i].fd);
+      if (h != handle_array[nhandles])
+       {
+         /* It's a socket.  */
+         WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
+         WSAEventSelect ((SOCKET) h, 0, 0);
+
+         /* If we're lucky, WSAEnumNetworkEvents already provided a way
+            to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
+         if (FD_ISSET ((SOCKET) h, &rfds)
+             && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
+           ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
+         if (FD_ISSET ((SOCKET) h, &wfds))
+           ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
+         if (FD_ISSET ((SOCKET) h, &xfds))
+           ev.lNetworkEvents |= FD_OOB;
+
+         happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
+                                                  ev.lNetworkEvents);
+       }
+      else
+       {
+         /* Not a socket.  */
+         int sought = pfd[i].events;
+         happened = win32_compute_revents (h, &sought);
+         nhandles++;
+       }
+
+       if ((pfd[i].revents |= happened) != 0)
+       rc++;
+    }
+
+  if (!rc && timeout == INFTIM)
+    {
+      SwitchToThread();
+      goto restart;
+    }
+
+  return rc;
+#endif
+}
diff --git a/compat/win32/poll.h b/compat/win32/poll.h
new file mode 100644 (file)
index 0000000..b7aa59d
--- /dev/null
@@ -0,0 +1,53 @@
+/* Header for poll(2) emulation
+   Contributed by Paolo Bonzini.
+
+   Copyright 2001, 2002, 2003, 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of gnulib.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GL_POLL_H
+#define _GL_POLL_H
+
+/* fake a poll(2) environment */
+#define POLLIN      0x0001      /* any readable data available   */
+#define POLLPRI     0x0002      /* OOB/Urgent readable data      */
+#define POLLOUT     0x0004      /* file descriptor is writeable  */
+#define POLLERR     0x0008      /* some poll error occurred      */
+#define POLLHUP     0x0010      /* file descriptor was "hung up" */
+#define POLLNVAL    0x0020      /* requested events "invalid"    */
+#define POLLRDNORM  0x0040
+#define POLLRDBAND  0x0080
+#define POLLWRNORM  0x0100
+#define POLLWRBAND  0x0200
+
+struct pollfd
+{
+  int fd;                       /* which file descriptor to poll */
+  short events;                 /* events we are interested in   */
+  short revents;                /* events found on return        */
+};
+
+typedef unsigned long nfds_t;
+
+extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout);
+
+/* Define INFTIM only if doing so conforms to POSIX.  */
+#if !defined (_POSIX_C_SOURCE) && !defined (_XOPEN_SOURCE)
+#define INFTIM (-1)
+#endif
+
+#endif /* _GL_POLL_H */
diff --git a/compat/win32/sys/poll.c b/compat/win32/sys/poll.c
deleted file mode 100644 (file)
index 708a6c9..0000000
+++ /dev/null
@@ -1,599 +0,0 @@
-/* Emulation for poll(2)
-   Contributed by Paolo Bonzini.
-
-   Copyright 2001-2003, 2006-2010 Free Software Foundation, Inc.
-
-   This file is part of gnulib.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along
-   with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-
-/* Tell gcc not to warn about the (nfd < 0) tests, below.  */
-#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
-# pragma GCC diagnostic ignored "-Wtype-limits"
-#endif
-
-#include <malloc.h>
-
-#include <sys/types.h>
-#include "poll.h"
-#include <errno.h>
-#include <limits.h>
-#include <assert.h>
-
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-# define WIN32_NATIVE
-# if defined (_MSC_VER)
-#  define _WIN32_WINNT 0x0502
-# endif
-# include <winsock2.h>
-# include <windows.h>
-# include <io.h>
-# include <stdio.h>
-# include <conio.h>
-#else
-# include <sys/time.h>
-# include <sys/socket.h>
-# include <sys/select.h>
-# include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-#endif
-
-#include <time.h>
-
-#ifndef INFTIM
-# define INFTIM (-1)
-#endif
-
-/* BeOS does not have MSG_PEEK.  */
-#ifndef MSG_PEEK
-# define MSG_PEEK 0
-#endif
-
-#ifdef WIN32_NATIVE
-
-#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
-
-static BOOL
-IsSocketHandle (HANDLE h)
-{
-  WSANETWORKEVENTS ev;
-
-  if (IsConsoleHandle (h))
-    return FALSE;
-
-  /* Under Wine, it seems that getsockopt returns 0 for pipes too.
-     WSAEnumNetworkEvents instead distinguishes the two correctly.  */
-  ev.lNetworkEvents = 0xDEADBEEF;
-  WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
-  return ev.lNetworkEvents != 0xDEADBEEF;
-}
-
-/* Declare data structures for ntdll functions.  */
-typedef struct _FILE_PIPE_LOCAL_INFORMATION {
-  ULONG NamedPipeType;
-  ULONG NamedPipeConfiguration;
-  ULONG MaximumInstances;
-  ULONG CurrentInstances;
-  ULONG InboundQuota;
-  ULONG ReadDataAvailable;
-  ULONG OutboundQuota;
-  ULONG WriteQuotaAvailable;
-  ULONG NamedPipeState;
-  ULONG NamedPipeEnd;
-} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
-
-typedef struct _IO_STATUS_BLOCK
-{
-  union {
-    DWORD Status;
-    PVOID Pointer;
-  } u;
-  ULONG_PTR Information;
-} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
-
-typedef enum _FILE_INFORMATION_CLASS {
-  FilePipeLocalInformation = 24
-} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
-
-typedef DWORD (WINAPI *PNtQueryInformationFile)
-        (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
-
-# ifndef PIPE_BUF
-#  define PIPE_BUF      512
-# endif
-
-/* Compute revents values for file handle H.  If some events cannot happen
-   for the handle, eliminate them from *P_SOUGHT.  */
-
-static int
-win32_compute_revents (HANDLE h, int *p_sought)
-{
-  int i, ret, happened;
-  INPUT_RECORD *irbuffer;
-  DWORD avail, nbuffer;
-  BOOL bRet;
-  IO_STATUS_BLOCK iosb;
-  FILE_PIPE_LOCAL_INFORMATION fpli;
-  static PNtQueryInformationFile NtQueryInformationFile;
-  static BOOL once_only;
-
-  switch (GetFileType (h))
-    {
-    case FILE_TYPE_PIPE:
-      if (!once_only)
-       {
-         NtQueryInformationFile = (PNtQueryInformationFile)
-           GetProcAddress (GetModuleHandle ("ntdll.dll"),
-                           "NtQueryInformationFile");
-         once_only = TRUE;
-       }
-
-      happened = 0;
-      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
-       {
-         if (avail)
-           happened |= *p_sought & (POLLIN | POLLRDNORM);
-       }
-      else if (GetLastError () == ERROR_BROKEN_PIPE)
-       happened |= POLLHUP;
-
-      else
-       {
-         /* It was the write-end of the pipe.  Check if it is writable.
-            If NtQueryInformationFile fails, optimistically assume the pipe is
-            writable.  This could happen on Win9x, where NtQueryInformationFile
-            is not available, or if we inherit a pipe that doesn't permit
-            FILE_READ_ATTRIBUTES access on the write end (I think this should
-            not happen since WinXP SP2; WINE seems fine too).  Otherwise,
-            ensure that enough space is available for atomic writes.  */
-         memset (&iosb, 0, sizeof (iosb));
-         memset (&fpli, 0, sizeof (fpli));
-
-         if (!NtQueryInformationFile
-             || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
-                                        FilePipeLocalInformation)
-             || fpli.WriteQuotaAvailable >= PIPE_BUF
-             || (fpli.OutboundQuota < PIPE_BUF &&
-                 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
-           happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
-       }
-      return happened;
-
-    case FILE_TYPE_CHAR:
-      ret = WaitForSingleObject (h, 0);
-      if (!IsConsoleHandle (h))
-       return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
-
-      nbuffer = avail = 0;
-      bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
-      if (bRet)
-       {
-         /* Input buffer.  */
-         *p_sought &= POLLIN | POLLRDNORM;
-         if (nbuffer == 0)
-           return POLLHUP;
-         if (!*p_sought)
-           return 0;
-
-         irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
-         bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
-         if (!bRet || avail == 0)
-           return POLLHUP;
-
-         for (i = 0; i < avail; i++)
-           if (irbuffer[i].EventType == KEY_EVENT)
-             return *p_sought;
-         return 0;
-       }
-      else
-       {
-         /* Screen buffer.  */
-         *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
-         return *p_sought;
-       }
-
-    default:
-      ret = WaitForSingleObject (h, 0);
-      if (ret == WAIT_OBJECT_0)
-       return *p_sought & ~(POLLPRI | POLLRDBAND);
-
-      return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
-    }
-}
-
-/* Convert fd_sets returned by select into revents values.  */
-
-static int
-win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
-{
-  int happened = 0;
-
-  if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
-    happened |= (POLLIN | POLLRDNORM) & sought;
-
-  else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
-    {
-      int r, error;
-
-      char data[64];
-      WSASetLastError (0);
-      r = recv (h, data, sizeof (data), MSG_PEEK);
-      error = WSAGetLastError ();
-      WSASetLastError (0);
-
-      if (r > 0 || error == WSAENOTCONN)
-       happened |= (POLLIN | POLLRDNORM) & sought;
-
-      /* Distinguish hung-up sockets from other errors.  */
-      else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
-              || error == WSAECONNABORTED || error == WSAENETRESET)
-       happened |= POLLHUP;
-
-      else
-       happened |= POLLERR;
-    }
-
-  if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
-    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
-
-  if (lNetworkEvents & FD_OOB)
-    happened |= (POLLPRI | POLLRDBAND) & sought;
-
-  return happened;
-}
-
-#else /* !MinGW */
-
-/* Convert select(2) returned fd_sets into poll(2) revents values.  */
-static int
-compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
-{
-  int happened = 0;
-  if (FD_ISSET (fd, rfds))
-    {
-      int r;
-      int socket_errno;
-
-# if defined __MACH__ && defined __APPLE__
-      /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
-        for some kinds of descriptors.  Detect if this descriptor is a
-        connected socket, a server socket, or something else using a
-        0-byte recv, and use ioctl(2) to detect POLLHUP.  */
-      r = recv (fd, NULL, 0, MSG_PEEK);
-      socket_errno = (r < 0) ? errno : 0;
-      if (r == 0 || socket_errno == ENOTSOCK)
-       ioctl (fd, FIONREAD, &r);
-# else
-      char data[64];
-      r = recv (fd, data, sizeof (data), MSG_PEEK);
-      socket_errno = (r < 0) ? errno : 0;
-# endif
-      if (r == 0)
-       happened |= POLLHUP;
-
-      /* If the event happened on an unconnected server socket,
-        that's fine. */
-      else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
-       happened |= (POLLIN | POLLRDNORM) & sought;
-
-      /* Distinguish hung-up sockets from other errors.  */
-      else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
-              || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
-       happened |= POLLHUP;
-
-      else
-       happened |= POLLERR;
-    }
-
-  if (FD_ISSET (fd, wfds))
-    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
-
-  if (FD_ISSET (fd, efds))
-    happened |= (POLLPRI | POLLRDBAND) & sought;
-
-  return happened;
-}
-#endif /* !MinGW */
-
-int
-poll (pfd, nfd, timeout)
-     struct pollfd *pfd;
-     nfds_t nfd;
-     int timeout;
-{
-#ifndef WIN32_NATIVE
-  fd_set rfds, wfds, efds;
-  struct timeval tv;
-  struct timeval *ptv;
-  int maxfd, rc;
-  nfds_t i;
-
-# ifdef _SC_OPEN_MAX
-  static int sc_open_max = -1;
-
-  if (nfd < 0
-      || (nfd > sc_open_max
-         && (sc_open_max != -1
-             || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
-    {
-      errno = EINVAL;
-      return -1;
-    }
-# else /* !_SC_OPEN_MAX */
-#  ifdef OPEN_MAX
-  if (nfd < 0 || nfd > OPEN_MAX)
-    {
-      errno = EINVAL;
-      return -1;
-    }
-#  endif /* OPEN_MAX -- else, no check is needed */
-# endif /* !_SC_OPEN_MAX */
-
-  /* EFAULT is not necessary to implement, but let's do it in the
-     simplest case. */
-  if (!pfd)
-    {
-      errno = EFAULT;
-      return -1;
-    }
-
-  /* convert timeout number into a timeval structure */
-  if (timeout == 0)
-    {
-      ptv = &tv;
-      ptv->tv_sec = 0;
-      ptv->tv_usec = 0;
-    }
-  else if (timeout > 0)
-    {
-      ptv = &tv;
-      ptv->tv_sec = timeout / 1000;
-      ptv->tv_usec = (timeout % 1000) * 1000;
-    }
-  else if (timeout == INFTIM)
-    /* wait forever */
-    ptv = NULL;
-  else
-    {
-      errno = EINVAL;
-      return -1;
-    }
-
-  /* create fd sets and determine max fd */
-  maxfd = -1;
-  FD_ZERO (&rfds);
-  FD_ZERO (&wfds);
-  FD_ZERO (&efds);
-  for (i = 0; i < nfd; i++)
-    {
-      if (pfd[i].fd < 0)
-       continue;
-
-      if (pfd[i].events & (POLLIN | POLLRDNORM))
-       FD_SET (pfd[i].fd, &rfds);
-
-      /* see select(2): "the only exceptional condition detectable
-        is out-of-band data received on a socket", hence we push
-        POLLWRBAND events onto wfds instead of efds. */
-      if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
-       FD_SET (pfd[i].fd, &wfds);
-      if (pfd[i].events & (POLLPRI | POLLRDBAND))
-       FD_SET (pfd[i].fd, &efds);
-      if (pfd[i].fd >= maxfd
-         && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
-                              | POLLRDNORM | POLLRDBAND
-                              | POLLWRNORM | POLLWRBAND)))
-       {
-         maxfd = pfd[i].fd;
-         if (maxfd > FD_SETSIZE)
-           {
-             errno = EOVERFLOW;
-             return -1;
-           }
-       }
-    }
-
-  /* examine fd sets */
-  rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
-  if (rc < 0)
-    return rc;
-
-  /* establish results */
-  rc = 0;
-  for (i = 0; i < nfd; i++)
-    if (pfd[i].fd < 0)
-      pfd[i].revents = 0;
-    else
-      {
-       int happened = compute_revents (pfd[i].fd, pfd[i].events,
-                                       &rfds, &wfds, &efds);
-       if (happened)
-         {
-           pfd[i].revents = happened;
-           rc++;
-         }
-      }
-
-  return rc;
-#else
-  static struct timeval tv0;
-  static HANDLE hEvent;
-  WSANETWORKEVENTS ev;
-  HANDLE h, handle_array[FD_SETSIZE + 2];
-  DWORD ret, wait_timeout, nhandles;
-  fd_set rfds, wfds, xfds;
-  BOOL poll_again;
-  MSG msg;
-  int rc = 0;
-  nfds_t i;
-
-  if (nfd < 0 || timeout < -1)
-    {
-      errno = EINVAL;
-      return -1;
-    }
-
-  if (!hEvent)
-    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
-
-  handle_array[0] = hEvent;
-  nhandles = 1;
-  FD_ZERO (&rfds);
-  FD_ZERO (&wfds);
-  FD_ZERO (&xfds);
-
-  /* Classify socket handles and create fd sets. */
-  for (i = 0; i < nfd; i++)
-    {
-      int sought = pfd[i].events;
-      pfd[i].revents = 0;
-      if (pfd[i].fd < 0)
-       continue;
-      if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
-                     | POLLPRI | POLLRDBAND)))
-       continue;
-
-      h = (HANDLE) _get_osfhandle (pfd[i].fd);
-      assert (h != NULL);
-      if (IsSocketHandle (h))
-       {
-         int requested = FD_CLOSE;
-
-         /* see above; socket handles are mapped onto select.  */
-         if (sought & (POLLIN | POLLRDNORM))
-           {
-             requested |= FD_READ | FD_ACCEPT;
-             FD_SET ((SOCKET) h, &rfds);
-           }
-         if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
-           {
-             requested |= FD_WRITE | FD_CONNECT;
-             FD_SET ((SOCKET) h, &wfds);
-           }
-         if (sought & (POLLPRI | POLLRDBAND))
-           {
-             requested |= FD_OOB;
-             FD_SET ((SOCKET) h, &xfds);
-           }
-
-         if (requested)
-           WSAEventSelect ((SOCKET) h, hEvent, requested);
-       }
-      else
-       {
-         /* Poll now.  If we get an event, do not poll again.  Also,
-            screen buffer handles are waitable, and they'll block until
-            a character is available.  win32_compute_revents eliminates
-            bits for the "wrong" direction. */
-         pfd[i].revents = win32_compute_revents (h, &sought);
-         if (sought)
-           handle_array[nhandles++] = h;
-         if (pfd[i].revents)
-           timeout = 0;
-       }
-    }
-
-  if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
-    {
-      /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
-        no need to call select again.  */
-      poll_again = FALSE;
-      wait_timeout = 0;
-    }
-  else
-    {
-      poll_again = TRUE;
-      if (timeout == INFTIM)
-       wait_timeout = INFINITE;
-      else
-       wait_timeout = timeout;
-    }
-
-  for (;;)
-    {
-      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
-                                      wait_timeout, QS_ALLINPUT);
-
-      if (ret == WAIT_OBJECT_0 + nhandles)
-       {
-         /* new input of some other kind */
-         BOOL bRet;
-         while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
-           {
-             TranslateMessage (&msg);
-             DispatchMessage (&msg);
-           }
-       }
-      else
-       break;
-    }
-
-  if (poll_again)
-    select (0, &rfds, &wfds, &xfds, &tv0);
-
-  /* Place a sentinel at the end of the array.  */
-  handle_array[nhandles] = NULL;
-  nhandles = 1;
-  for (i = 0; i < nfd; i++)
-    {
-      int happened;
-
-      if (pfd[i].fd < 0)
-       continue;
-      if (!(pfd[i].events & (POLLIN | POLLRDNORM |
-                            POLLOUT | POLLWRNORM | POLLWRBAND)))
-       continue;
-
-      h = (HANDLE) _get_osfhandle (pfd[i].fd);
-      if (h != handle_array[nhandles])
-       {
-         /* It's a socket.  */
-         WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
-         WSAEventSelect ((SOCKET) h, 0, 0);
-
-         /* If we're lucky, WSAEnumNetworkEvents already provided a way
-            to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
-         if (FD_ISSET ((SOCKET) h, &rfds)
-             && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
-           ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
-         if (FD_ISSET ((SOCKET) h, &wfds))
-           ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
-         if (FD_ISSET ((SOCKET) h, &xfds))
-           ev.lNetworkEvents |= FD_OOB;
-
-         happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
-                                                  ev.lNetworkEvents);
-       }
-      else
-       {
-         /* Not a socket.  */
-         int sought = pfd[i].events;
-         happened = win32_compute_revents (h, &sought);
-         nhandles++;
-       }
-
-       if ((pfd[i].revents |= happened) != 0)
-       rc++;
-    }
-
-  return rc;
-#endif
-}
diff --git a/compat/win32/sys/poll.h b/compat/win32/sys/poll.h
deleted file mode 100644 (file)
index b7aa59d..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Header for poll(2) emulation
-   Contributed by Paolo Bonzini.
-
-   Copyright 2001, 2002, 2003, 2007, 2009, 2010 Free Software Foundation, Inc.
-
-   This file is part of gnulib.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along
-   with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-
-#ifndef _GL_POLL_H
-#define _GL_POLL_H
-
-/* fake a poll(2) environment */
-#define POLLIN      0x0001      /* any readable data available   */
-#define POLLPRI     0x0002      /* OOB/Urgent readable data      */
-#define POLLOUT     0x0004      /* file descriptor is writeable  */
-#define POLLERR     0x0008      /* some poll error occurred      */
-#define POLLHUP     0x0010      /* file descriptor was "hung up" */
-#define POLLNVAL    0x0020      /* requested events "invalid"    */
-#define POLLRDNORM  0x0040
-#define POLLRDBAND  0x0080
-#define POLLWRNORM  0x0100
-#define POLLWRBAND  0x0200
-
-struct pollfd
-{
-  int fd;                       /* which file descriptor to poll */
-  short events;                 /* events we are interested in   */
-  short revents;                /* events found on return        */
-};
-
-typedef unsigned long nfds_t;
-
-extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout);
-
-/* Define INFTIM only if doing so conforms to POSIX.  */
-#if !defined (_POSIX_C_SOURCE) && !defined (_XOPEN_SOURCE)
-#define INFTIM (-1)
-#endif
-
-#endif /* _GL_POLL_H */
index edf9914df6a1a789780c98d53b7b779908bb9141..5ea101fb251d27eadac20c665a7f01fb210c20d1 100644 (file)
--- a/config.c
+++ b/config.c
@@ -333,7 +333,7 @@ static int git_parse_file(config_fn_t fn, void *data)
        die("bad config file line %d in %s", cf->linenr, cf->name);
 }
 
-static int parse_unit_factor(const char *end, unsigned long *val)
+static int parse_unit_factor(const char *end, uintmax_t *val)
 {
        if (!*end)
                return 1;
@@ -356,11 +356,23 @@ static int git_parse_long(const char *value, long *ret)
 {
        if (value && *value) {
                char *end;
-               long val = strtol(value, &end, 0);
-               unsigned long factor = 1;
+               intmax_t val;
+               uintmax_t uval;
+               uintmax_t factor = 1;
+
+               errno = 0;
+               val = strtoimax(value, &end, 0);
+               if (errno == ERANGE)
+                       return 0;
                if (!parse_unit_factor(end, &factor))
                        return 0;
-               *ret = val * factor;
+               uval = abs(val);
+               uval *= factor;
+               if ((uval > maximum_signed_value_of_type(long)) ||
+                   (abs(val) > uval))
+                       return 0;
+               val *= factor;
+               *ret = val;
                return 1;
        }
        return 0;
@@ -370,9 +382,19 @@ int git_parse_ulong(const char *value, unsigned long *ret)
 {
        if (value && *value) {
                char *end;
-               unsigned long val = strtoul(value, &end, 0);
+               uintmax_t val;
+               uintmax_t oldval;
+
+               errno = 0;
+               val = strtoumax(value, &end, 0);
+               if (errno == ERANGE)
+                       return 0;
+               oldval = val;
                if (!parse_unit_factor(end, &val))
                        return 0;
+               if ((val > maximum_unsigned_value_of_type(long)) ||
+                   (oldval > val))
+                       return 0;
                *ret = val;
                return 1;
        }
@@ -553,7 +575,7 @@ static int git_default_core_config(const char *var, const char *value)
 
        if (!strcmp(var, "core.packedgitwindowsize")) {
                int pgsz_x2 = getpagesize() * 2;
-               packed_git_window_size = git_config_int(var, value);
+               packed_git_window_size = git_config_ulong(var, value);
 
                /* This value must be multiple of (pagesize * 2) */
                packed_git_window_size /= pgsz_x2;
@@ -564,18 +586,17 @@ static int git_default_core_config(const char *var, const char *value)
        }
 
        if (!strcmp(var, "core.bigfilethreshold")) {
-               long n = git_config_int(var, value);
-               big_file_threshold = 0 < n ? n : 0;
+               big_file_threshold = git_config_ulong(var, value);
                return 0;
        }
 
        if (!strcmp(var, "core.packedgitlimit")) {
-               packed_git_limit = git_config_int(var, value);
+               packed_git_limit = git_config_ulong(var, value);
                return 0;
        }
 
        if (!strcmp(var, "core.deltabasecachelimit")) {
-               delta_base_cache_limit = git_config_int(var, value);
+               delta_base_cache_limit = git_config_ulong(var, value);
                return 0;
        }
 
@@ -865,12 +886,12 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
 
        home = getenv("HOME");
        if (home) {
-               char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
+               char buf[PATH_MAX];
+               char *user_config = mksnpath(buf, sizeof(buf), "%s/.gitconfig", home);
                if (!access(user_config, R_OK)) {
                        ret += git_config_from_file(fn, user_config, data);
                        found += 1;
                }
-               free(user_config);
        }
 
        if (repo_config && !access(repo_config, R_OK)) {
index 98af8f5c7ee68876e94194524cc0cda9d3f25345..b7c1edf1cc763199d41a490b212a3b65ea581a86 100755 (executable)
@@ -110,7 +110,7 @@ __git_ps1_show_upstream ()
        local upstream=git legacy="" verbose=""
 
        # get some config options from git-config
-       output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
+       local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
        while read key value; do
                case "$key" in
                bash.showupstream)
index f885d707c4a9d80928cecb3d4867deb268929670..7fd8bf031e1eb10f6dda2342f32c86454ef7efb3 100755 (executable)
@@ -847,6 +847,38 @@ class P4Submit(Command, P4UserMap):
 
         return template
 
+    def edit_template(self, template_file):
+        """Invoke the editor to let the user change the submission
+           message.  Return true if okay to continue with the submit."""
+
+        # if configured to skip the editing part, just submit
+        if gitConfig("git-p4.skipSubmitEdit") == "true":
+            return True
+
+        # look at the modification time, to check later if the user saved
+        # the file
+        mtime = os.stat(template_file).st_mtime
+
+        # invoke the editor
+        if os.environ.has_key("P4EDITOR"):
+            editor = os.environ.get("P4EDITOR")
+        else:
+            editor = read_pipe("git var GIT_EDITOR").strip()
+        system(editor + " " + template_file)
+
+        # If the file was not saved, prompt to see if this patch should
+        # be skipped.  But skip this verification step if configured so.
+        if gitConfig("git-p4.skipSubmitEditCheck") == "true":
+            return True
+
+        if os.stat(template_file).st_mtime <= mtime:
+            while True:
+                response = raw_input("Submit template unchanged. Submit anyway? [y]es, [n]o (skip this patch) ")
+                if response == 'y':
+                    return True
+                if response == 'n':
+                    return False
+
     def applyCommit(self, id):
         print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id))
 
@@ -1001,7 +1033,7 @@ class P4Submit(Command, P4UserMap):
 
             separatorLine = "######## everything below this line is just the diff #######\n"
 
-            [handle, fileName] = tempfile.mkstemp()
+            (handle, fileName) = tempfile.mkstemp()
             tmpFile = os.fdopen(handle, "w+")
             if self.isWindows:
                 submitTemplate = submitTemplate.replace("\n", "\r\n")
@@ -1009,25 +1041,9 @@ class P4Submit(Command, P4UserMap):
                 newdiff = newdiff.replace("\n", "\r\n")
             tmpFile.write(submitTemplate + separatorLine + diff + newdiff)
             tmpFile.close()
-            mtime = os.stat(fileName).st_mtime
-            if os.environ.has_key("P4EDITOR"):
-                editor = os.environ.get("P4EDITOR")
-            else:
-                editor = read_pipe("git var GIT_EDITOR").strip()
-            system(editor + " " + fileName)
-
-            if gitConfig("git-p4.skipSubmitEditCheck") == "true":
-                checkModTime = False
-            else:
-                checkModTime = True
 
-            response = "y"
-            if checkModTime and (os.stat(fileName).st_mtime <= mtime):
-                response = "x"
-                while response != "y" and response != "n":
-                    response = raw_input("Submit template unchanged. Submit anyway? [y]es, [n]o (skip this patch) ")
-
-            if response == "y":
+            if self.edit_template(fileName):
+                # read the edited message and submit
                 tmpFile = open(fileName, "rb")
                 message = tmpFile.read()
                 tmpFile.close()
@@ -1039,11 +1055,12 @@ class P4Submit(Command, P4UserMap):
                 if self.preserveUser:
                     if p4User:
                         # Get last changelist number. Cannot easily get it from
-                        # the submit command output as the output is unmarshalled.
+                        # the submit command output as the output is
+                        # unmarshalled.
                         changelist = self.lastP4Changelist()
                         self.modifyChangelistUser(changelist, p4User)
-
             else:
+                # skip this patch
                 for f in editedFiles:
                     p4_revert(f)
                 for f in filesToAdd:
@@ -1318,6 +1335,19 @@ class P4Sync(Command, P4UserMap):
             text = p4_read_pipe(['print', '-q', '-o', '-', file['depotFile']])
             contents = [ text ]
 
+        if type_base == "apple":
+            # Apple filetype files will be streamed as a concatenation of
+            # its appledouble header and the contents.  This is useless
+            # on both macs and non-macs.  If using "print -q -o xx", it
+            # will create "xx" with the data, and "%xx" with the header.
+            # This is also not very useful.
+            #
+            # Ideally, someday, this script can learn how to generate
+            # appledouble files directly and import those to git, but
+            # non-mac machines can never find a use for apple filetype.
+            print "\nIgnoring apple filetype file %s" % file['depotFile']
+            return
+
         # Perhaps windows wants unicode, utf16 newlines translated too;
         # but this is not doing it.
         if self.isWindows and type_base == "text":
index 52003ae9045626077009811cd8e10c1135d69cd0..5044a121e01668d941fdc09124b9db354213c460 100644 (file)
@@ -202,11 +202,24 @@ able to find the relevant client.  This client spec will be used to
 both filter the files cloned by git and set the directory layout as
 specified in the client (this implies --keep-path style semantics).
 
-git-p4.skipSubmitModTimeCheck
+git-p4.skipSubmitEdit
 
-  git config [--global] git-p4.skipSubmitModTimeCheck false
+  git config [--global] git-p4.skipSubmitEdit false
 
-If true, submit will not check if the p4 change template has been modified.
+Normally, git-p4 invokes an editor after each commit is applied so
+that you can make changes to the submit message.  Setting this
+variable to true will skip the editing step, submitting the change as is.
+
+git-p4.skipSubmitEditCheck
+
+  git config [--global] git-p4.skipSubmitEditCheck false
+
+After the editor is invoked, git-p4 normally makes sure you saved the
+change description, as an indication that you did indeed read it over
+and edit it.  You can quit without saving to abort the submit (or skip
+this change and continue).  Setting this variable to true will cause
+git-p4 not to check if you saved the change description.  This variable
+only matters if git-p4.skipSubmitEdit has not been set to true.
 
 git-p4.preserveUser
 
index 3bb5a4dd57c669bc59be0e2317ef33b64b024992..86e9c29ec05139844ff46868e2b52dfbc274cc39 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -641,7 +641,7 @@ static int ident_to_worktree(const char *path, const char *src, size_t len,
        return 1;
 }
 
-static int git_path_check_crlf(const char *path, struct git_attr_check *check)
+static enum crlf_action git_path_check_crlf(const char *path, struct git_attr_check *check)
 {
        const char *value = check->value;
 
@@ -658,7 +658,7 @@ static int git_path_check_crlf(const char *path, struct git_attr_check *check)
        return CRLF_GUESS;
 }
 
-static int git_path_check_eol(const char *path, struct git_attr_check *check)
+static enum eol git_path_check_eol(const char *path, struct git_attr_check *check)
 {
        const char *value = check->value;
 
@@ -811,7 +811,7 @@ int renormalize_buffer(const char *path, const char *src, size_t len, struct str
                src = dst->buf;
                len = dst->len;
        }
-       return ret | convert_to_git(path, src, len, dst, 0);
+       return ret | convert_to_git(path, src, len, dst, SAFE_CRLF_FALSE);
 }
 
 /*****************************************************************
diff --git a/dir.c b/dir.c
index 6c0d7825799f6c35a2c1f1830767ab6203e2da92..0a78d00b545ac4f302ea89b6393773669907599e 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -968,34 +968,34 @@ static int read_directory_recursive(struct dir_struct *dir,
 {
        DIR *fdir = opendir(*base ? base : ".");
        int contents = 0;
+       struct dirent *de;
+       char path[PATH_MAX + 1];
 
-       if (fdir) {
-               struct dirent *de;
-               char path[PATH_MAX + 1];
-               memcpy(path, base, baselen);
-
-               while ((de = readdir(fdir)) != NULL) {
-                       int len;
-                       switch (treat_path(dir, de, path, sizeof(path),
-                                          baselen, simplify, &len)) {
-                       case path_recurse:
-                               contents += read_directory_recursive
-                                       (dir, path, len, 0, simplify);
-                               continue;
-                       case path_ignored:
-                               continue;
-                       case path_handled:
-                               break;
-                       }
-                       contents++;
-                       if (check_only)
-                               goto exit_early;
-                       else
-                               dir_add_name(dir, path, len);
+       if (!fdir)
+               return 0;
+
+       memcpy(path, base, baselen);
+
+       while ((de = readdir(fdir)) != NULL) {
+               int len;
+               switch (treat_path(dir, de, path, sizeof(path),
+                                  baselen, simplify, &len)) {
+               case path_recurse:
+                       contents += read_directory_recursive(dir, path, len, 0, simplify);
+                       continue;
+               case path_ignored:
+                       continue;
+               case path_handled:
+                       break;
                }
-exit_early:
-               closedir(fdir);
+               contents++;
+               if (check_only)
+                       goto exit_early;
+               else
+                       dir_add_name(dir, path, len);
        }
+exit_early:
+       closedir(fdir);
 
        return contents;
 }
index 53186dacbb298a685a3a8a8037478a3bbe9a2a2e..77062ed2a66e1efda60ead8ce99abedc8d04ce71 100644 (file)
@@ -218,7 +218,7 @@ extern char *gitbasename(char *);
 #define find_last_dir_sep(path) strrchr(path, '/')
 #endif
 
-#if __HP_cc >= 61000
+#if defined(__HP_cc) && (__HP_cc >= 61000)
 #define NORETURN __attribute__((noreturn))
 #define NORETURN_PTR
 #elif defined(__GNUC__) && !defined(NO_NORETURN)
@@ -350,6 +350,8 @@ extern size_t gitstrlcpy(char *, const char *, size_t);
 #ifdef NO_STRTOUMAX
 #define strtoumax gitstrtoumax
 extern uintmax_t gitstrtoumax(const char *, char **, int);
+#define strtoimax gitstrtoimax
+extern intmax_t gitstrtoimax(const char *, char **, int);
 #endif
 
 #ifdef NO_STRTOK_R
index b67fef0bf69da170a5a9748b9da8c31c6e1ca5c7..e30df22d89d97642f0b99c3a35ee0b2c5c062bb3 100755 (executable)
@@ -684,7 +684,7 @@ sub populate_merge_info {
                                fatal "merge commit $d has ancestor $parent, but that change "
                      ."does not have git-svn metadata!";
                        }
-                       unless ($branchurl =~ /^$rooturl(.*)/) {
+                       unless ($branchurl =~ /^\Q$rooturl\E(.*)/) {
                                fatal "commit $parent git-svn metadata changed mid-run!";
                        }
                        my $branchpath = $1;
@@ -867,7 +867,7 @@ sub cmd_dcommit {
                                                         ."has uuid $uuid!";
                                        }
 
-                                       unless ($branchurl =~ /^$rooturl(.*)/) {
+                                       unless ($branchurl =~ /^\Q$rooturl\E(.*)/) {
                                                # This branch is very strange indeed.
                                                fatal "merge parent $parent for $d is on branch "
                                                         ."$branchurl, which is not under the "
diff --git a/http.c b/http.c
index a4bc770e2d6196958ec5b795ca89be24be182a34..44fcc4d178fcedaa87f1917608dd32a65c24c98a 100644 (file)
--- a/http.c
+++ b/http.c
@@ -4,7 +4,6 @@
 #include "run-command.h"
 #include "url.h"
 
-int data_received;
 int active_requests;
 int http_is_verbose;
 size_t http_post_buffer = 16 * LARGE_PACKET_MAX;
@@ -99,13 +98,11 @@ size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
        struct strbuf *buffer = buffer_;
 
        strbuf_add(buffer, ptr, size);
-       data_received++;
        return size;
 }
 
 size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf)
 {
-       data_received++;
        return eltsize * nmemb;
 }
 
@@ -279,8 +276,6 @@ static CURL *get_curl_handle(void)
        curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
 #endif
 
-       init_curl_http_auth(result);
-
        if (ssl_cert != NULL)
                curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
        if (has_cert_password())
@@ -538,7 +533,6 @@ struct active_request_slot *get_active_slot(void)
 
        active_requests++;
        slot->in_use = 1;
-       slot->local = NULL;
        slot->results = NULL;
        slot->finished = NULL;
        slot->callback_data = NULL;
@@ -642,8 +636,6 @@ void step_active_slots(void)
 void run_active_slot(struct active_request_slot *slot)
 {
 #ifdef USE_CURL_MULTI
-       long last_pos = 0;
-       long current_pos;
        fd_set readfds;
        fd_set writefds;
        fd_set excfds;
@@ -653,25 +645,33 @@ void run_active_slot(struct active_request_slot *slot)
 
        slot->finished = &finished;
        while (!finished) {
-               data_received = 0;
                step_active_slots();
 
-               if (!data_received && slot->local != NULL) {
-                       current_pos = ftell(slot->local);
-                       if (current_pos > last_pos)
-                               data_received++;
-                       last_pos = current_pos;
-               }
+               if (slot->in_use) {
+#if LIBCURL_VERSION_NUM >= 0x070f04
+                       long curl_timeout;
+                       curl_multi_timeout(curlm, &curl_timeout);
+                       if (curl_timeout == 0) {
+                               continue;
+                       } else if (curl_timeout == -1) {
+                               select_timeout.tv_sec  = 0;
+                               select_timeout.tv_usec = 50000;
+                       } else {
+                               select_timeout.tv_sec  =  curl_timeout / 1000;
+                               select_timeout.tv_usec = (curl_timeout % 1000) * 1000;
+                       }
+#else
+                       select_timeout.tv_sec  = 0;
+                       select_timeout.tv_usec = 50000;
+#endif
 
-               if (slot->in_use && !data_received) {
-                       max_fd = 0;
+                       max_fd = -1;
                        FD_ZERO(&readfds);
                        FD_ZERO(&writefds);
                        FD_ZERO(&excfds);
-                       select_timeout.tv_sec = 0;
-                       select_timeout.tv_usec = 50000;
-                       select(max_fd, &readfds, &writefds,
-                              &excfds, &select_timeout);
+                       curl_multi_fdset(curlm, &readfds, &writefds, &excfds, &max_fd);
+
+                       select(max_fd+1, &readfds, &writefds, &excfds, &select_timeout);
                }
        }
 #else
@@ -749,14 +749,6 @@ static inline int needs_quote(int ch)
        return 1;
 }
 
-static inline int hex(int v)
-{
-       if (v < 10)
-               return '0' + v;
-       else
-               return 'A' + v - 10;
-}
-
 static char *quote_ref_url(const char *base, const char *ref)
 {
        struct strbuf buf = STRBUF_INIT;
@@ -824,7 +816,6 @@ static int http_request(const char *url, void *result, int target, int options)
                                headers = curl_slist_append(headers, buf.buf);
                                strbuf_reset(&buf);
                        }
-                       slot->local = result;
                } else
                        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
                                         fwrite_buffer);
@@ -846,7 +837,7 @@ static int http_request(const char *url, void *result, int target, int options)
                else if (missing_target(&results))
                        ret = HTTP_MISSING_TARGET;
                else if (results.http_code == 401) {
-                       if (user_name) {
+                       if (user_name && user_pass) {
                                ret = HTTP_NOAUTH;
                        } else {
                                /*
@@ -855,7 +846,8 @@ static int http_request(const char *url, void *result, int target, int options)
                                 * but that is non-portable.  Using git_getpass() can at least be stubbed
                                 * on other platforms with a different implementation if/when necessary.
                                 */
-                               user_name = xstrdup(git_getpass_with_description("Username", description));
+                               if (!user_name)
+                                       user_name = xstrdup(git_getpass_with_description("Username", description));
                                init_curl_http_auth(slot->curl);
                                ret = HTTP_REAUTH;
                        }
@@ -871,7 +863,6 @@ static int http_request(const char *url, void *result, int target, int options)
                ret = HTTP_START_FAILED;
        }
 
-       slot->local = NULL;
        curl_slist_free_all(headers);
        strbuf_release(&buf);
 
@@ -1066,7 +1057,6 @@ void release_http_pack_request(struct http_pack_request *preq)
        if (preq->packfile != NULL) {
                fclose(preq->packfile);
                preq->packfile = NULL;
-               preq->slot->local = NULL;
        }
        if (preq->range_header != NULL) {
                curl_slist_free_all(preq->range_header);
@@ -1088,7 +1078,6 @@ int finish_http_pack_request(struct http_pack_request *preq)
 
        fclose(preq->packfile);
        preq->packfile = NULL;
-       preq->slot->local = NULL;
 
        lst = preq->lst;
        while (*lst != p)
@@ -1157,7 +1146,6 @@ struct http_pack_request *new_http_pack_request(
        }
 
        preq->slot = get_active_slot();
-       preq->slot->local = preq->packfile;
        curl_easy_setopt(preq->slot->curl, CURLOPT_FILE, preq->packfile);
        curl_easy_setopt(preq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
        curl_easy_setopt(preq->slot->curl, CURLOPT_URL, preq->url);
@@ -1214,7 +1202,6 @@ static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb,
                git_SHA1_Update(&freq->c, expn,
                                sizeof(expn) - freq->stream.avail_out);
        } while (freq->stream.avail_in && freq->zret == Z_OK);
-       data_received++;
        return size;
 }
 
diff --git a/http.h b/http.h
index 3c332a98e9358a296b937453351018ac1042120e..ee1606942a9716b45da937873949220ab7f8092b 100644 (file)
--- a/http.h
+++ b/http.h
@@ -49,7 +49,6 @@ struct slot_results {
 
 struct active_request_slot {
        CURL *curl;
-       FILE *local;
        int in_use;
        CURLcode curl_result;
        long http_code;
@@ -89,7 +88,6 @@ extern void step_active_slots(void);
 extern void http_init(struct remote *remote, const char *url);
 extern void http_cleanup(void);
 
-extern int data_received;
 extern int active_requests;
 extern int http_is_verbose;
 extern size_t http_post_buffer;
index 39d80c01753527e45716ec762beeb891dfc7d28d..3dd4a960190a1b0016b26dec9187692111b73e3f 100644 (file)
@@ -71,7 +71,8 @@ static void process_tree(struct rev_info *revs,
        struct tree_desc desc;
        struct name_entry entry;
        struct name_path me;
-       int match = revs->diffopt.pathspec.nr == 0 ? 2 : 0;
+       enum interesting match = revs->diffopt.pathspec.nr == 0 ?
+               all_entries_interesting: entry_not_interesting;
        int baselen = base->len;
 
        if (!revs->tree_objects)
@@ -97,12 +98,12 @@ static void process_tree(struct rev_info *revs,
        init_tree_desc(&desc, tree->buffer, tree->size);
 
        while (tree_entry(&desc, &entry)) {
-               if (match != 2) {
+               if (match != all_entries_interesting) {
                        match = tree_entry_interesting(&entry, base, 0,
                                                       &revs->diffopt.pathspec);
-                       if (match < 0)
+                       if (match == all_entries_not_interesting)
                                break;
-                       if (match == 0)
+                       if (match == entry_not_interesting)
                                continue;
                }
 
index 02fcfde0b0b786af5229559586cf8ff5758429bc..8c3196c7d76ff90e90a9fb4ff569aff6a429861a 100644 (file)
--- a/mailmap.c
+++ b/mailmap.c
@@ -70,8 +70,7 @@ static void add_mapping(struct string_list *map,
        } else {
                /* create mailmap entry */
                struct string_list_item *item = string_list_insert_at_index(map, index, old_email);
-               item->util = xmalloc(sizeof(struct mailmap_entry));
-               memset(item->util, 0, sizeof(struct mailmap_entry));
+               item->util = xcalloc(1, sizeof(struct mailmap_entry));
                ((struct mailmap_entry *)item->util)->namemap.strdup_strings = 1;
        }
        me = (struct mailmap_entry *)map->items[index].util;
@@ -88,7 +87,7 @@ static void add_mapping(struct string_list *map,
                        me->email = xstrdup(new_email);
                }
        } else {
-               struct mailmap_info *mi = xmalloc(sizeof(struct mailmap_info));
+               struct mailmap_info *mi = xcalloc(1, sizeof(struct mailmap_info));
                debug_mm("mailmap: adding (complex) entry for %s at index %d\n", old_email, index);
                if (new_name)
                        mi->name = xstrdup(new_name);
index 225dd769954fa0fcb6e70da58b2ce5ed88e9451e..d8d25c23e99dddd9bd0bf83d73f2ae136d7307b5 100644 (file)
@@ -74,7 +74,7 @@ static void hash_index_entry(struct index_state *istate, struct cache_entry *ce)
        if (ce->ce_flags & CE_HASHED)
                return;
        ce->ce_flags |= CE_HASHED;
-       ce->next = NULL;
+       ce->next = ce->dir_next = NULL;
        hash = hash_name(ce->name, ce_namelen(ce));
        pos = insert_hash(hash, ce, &istate->name_hash);
        if (pos) {
index e9e41993117ae03ed7c9d1f28081a42b2eee97ca..ce10aacf2978024eda0234482964577e9235f2d2 100644 (file)
@@ -21,14 +21,6 @@ void init_notes_merge_options(struct notes_merge_options *o)
        o->verbosity = NOTES_MERGE_VERBOSITY_DEFAULT;
 }
 
-#define OUTPUT(o, v, ...) \
-       do { \
-               if ((o)->verbosity >= (v)) { \
-                       printf(__VA_ARGS__); \
-                       puts(""); \
-               } \
-       } while (0)
-
 static int path_to_sha1(const char *path, unsigned char *sha1)
 {
        char hex_sha1[40];
@@ -392,21 +384,26 @@ static int merge_one_change_manual(struct notes_merge_options *o,
 
        strbuf_addf(&(o->commit_msg), "\t%s\n", sha1_to_hex(p->obj));
 
-       OUTPUT(o, 2, "Auto-merging notes for %s", sha1_to_hex(p->obj));
+       if (o->verbosity >= 2)
+               printf("Auto-merging notes for %s\n", sha1_to_hex(p->obj));
        check_notes_merge_worktree(o);
        if (is_null_sha1(p->local)) {
                /* D/F conflict, checkout p->remote */
                assert(!is_null_sha1(p->remote));
-               OUTPUT(o, 1, "CONFLICT (delete/modify): Notes for object %s "
-                      "deleted in %s and modified in %s. Version from %s "
-                      "left in tree.", sha1_to_hex(p->obj), lref, rref, rref);
+               if (o->verbosity >= 1)
+                       printf("CONFLICT (delete/modify): Notes for object %s "
+                               "deleted in %s and modified in %s. Version from %s "
+                               "left in tree.\n",
+                               sha1_to_hex(p->obj), lref, rref, rref);
                write_note_to_worktree(p->obj, p->remote);
        } else if (is_null_sha1(p->remote)) {
                /* D/F conflict, checkout p->local */
                assert(!is_null_sha1(p->local));
-               OUTPUT(o, 1, "CONFLICT (delete/modify): Notes for object %s "
-                      "deleted in %s and modified in %s. Version from %s "
-                      "left in tree.", sha1_to_hex(p->obj), rref, lref, lref);
+               if (o->verbosity >= 1)
+                       printf("CONFLICT (delete/modify): Notes for object %s "
+                               "deleted in %s and modified in %s. Version from %s "
+                               "left in tree.\n",
+                               sha1_to_hex(p->obj), rref, lref, lref);
                write_note_to_worktree(p->obj, p->local);
        } else {
                /* "regular" conflict, checkout result of ll_merge() */
@@ -415,8 +412,9 @@ static int merge_one_change_manual(struct notes_merge_options *o,
                        reason = "add/add";
                assert(!is_null_sha1(p->local));
                assert(!is_null_sha1(p->remote));
-               OUTPUT(o, 1, "CONFLICT (%s): Merge conflict in notes for "
-                      "object %s", reason, sha1_to_hex(p->obj));
+               if (o->verbosity >= 1)
+                       printf("CONFLICT (%s): Merge conflict in notes for "
+                               "object %s\n", reason, sha1_to_hex(p->obj));
                ll_merge_in_worktree(o, p);
        }
 
@@ -438,24 +436,30 @@ static int merge_one_change(struct notes_merge_options *o,
        case NOTES_MERGE_RESOLVE_MANUAL:
                return merge_one_change_manual(o, p, t);
        case NOTES_MERGE_RESOLVE_OURS:
-               OUTPUT(o, 2, "Using local notes for %s", sha1_to_hex(p->obj));
+               if (o->verbosity >= 2)
+                       printf("Using local notes for %s\n",
+                                               sha1_to_hex(p->obj));
                /* nothing to do */
                return 0;
        case NOTES_MERGE_RESOLVE_THEIRS:
-               OUTPUT(o, 2, "Using remote notes for %s", sha1_to_hex(p->obj));
+               if (o->verbosity >= 2)
+                       printf("Using remote notes for %s\n",
+                                               sha1_to_hex(p->obj));
                if (add_note(t, p->obj, p->remote, combine_notes_overwrite))
                        die("BUG: combine_notes_overwrite failed");
                return 0;
        case NOTES_MERGE_RESOLVE_UNION:
-               OUTPUT(o, 2, "Concatenating local and remote notes for %s",
-                      sha1_to_hex(p->obj));
+               if (o->verbosity >= 2)
+                       printf("Concatenating local and remote notes for %s\n",
+                                                       sha1_to_hex(p->obj));
                if (add_note(t, p->obj, p->remote, combine_notes_concatenate))
                        die("failed to concatenate notes "
                            "(combine_notes_concatenate)");
                return 0;
        case NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ:
-               OUTPUT(o, 2, "Concatenating unique lines in local and remote "
-                      "notes for %s", sha1_to_hex(p->obj));
+               if (o->verbosity >= 2)
+                       printf("Concatenating unique lines in local and remote "
+                               "notes for %s\n", sha1_to_hex(p->obj));
                if (add_note(t, p->obj, p->remote, combine_notes_cat_sort_uniq))
                        die("failed to concatenate notes "
                            "(combine_notes_cat_sort_uniq)");
@@ -518,8 +522,9 @@ static int merge_from_diffs(struct notes_merge_options *o,
        conflicts = merge_changes(o, changes, &num_changes, t);
        free(changes);
 
-       OUTPUT(o, 4, "Merge result: %i unmerged notes and a %s notes tree",
-              conflicts, t->dirty ? "dirty" : "clean");
+       if (o->verbosity >= 4)
+               printf("Merge result: %i unmerged notes and a %s notes tree\n",
+                       conflicts, t->dirty ? "dirty" : "clean");
 
        return conflicts ? -1 : 1;
 }
@@ -617,33 +622,40 @@ int notes_merge(struct notes_merge_options *o,
        if (!bases) {
                base_sha1 = null_sha1;
                base_tree_sha1 = EMPTY_TREE_SHA1_BIN;
-               OUTPUT(o, 4, "No merge base found; doing history-less merge");
+               if (o->verbosity >= 4)
+                       printf("No merge base found; doing history-less merge\n");
        } else if (!bases->next) {
                base_sha1 = bases->item->object.sha1;
                base_tree_sha1 = bases->item->tree->object.sha1;
-               OUTPUT(o, 4, "One merge base found (%.7s)",
-                      sha1_to_hex(base_sha1));
+               if (o->verbosity >= 4)
+                       printf("One merge base found (%.7s)\n",
+                               sha1_to_hex(base_sha1));
        } else {
                /* TODO: How to handle multiple merge-bases? */
                base_sha1 = bases->item->object.sha1;
                base_tree_sha1 = bases->item->tree->object.sha1;
-               OUTPUT(o, 3, "Multiple merge bases found. Using the first "
-                      "(%.7s)", sha1_to_hex(base_sha1));
+               if (o->verbosity >= 3)
+                       printf("Multiple merge bases found. Using the first "
+                               "(%.7s)\n", sha1_to_hex(base_sha1));
        }
 
-       OUTPUT(o, 4, "Merging remote commit %.7s into local commit %.7s with "
-              "merge-base %.7s", sha1_to_hex(remote->object.sha1),
-              sha1_to_hex(local->object.sha1), sha1_to_hex(base_sha1));
+       if (o->verbosity >= 4)
+               printf("Merging remote commit %.7s into local commit %.7s with "
+                       "merge-base %.7s\n", sha1_to_hex(remote->object.sha1),
+                       sha1_to_hex(local->object.sha1),
+                       sha1_to_hex(base_sha1));
 
        if (!hashcmp(remote->object.sha1, base_sha1)) {
                /* Already merged; result == local commit */
-               OUTPUT(o, 2, "Already up-to-date!");
+               if (o->verbosity >= 2)
+                       printf("Already up-to-date!\n");
                hashcpy(result_sha1, local->object.sha1);
                goto found_result;
        }
        if (!hashcmp(local->object.sha1, base_sha1)) {
                /* Fast-forward; result == remote commit */
-               OUTPUT(o, 2, "Fast-forward");
+               if (o->verbosity >= 2)
+                       printf("Fast-forward\n");
                hashcpy(result_sha1, remote->object.sha1);
                goto found_result;
        }
@@ -685,8 +697,9 @@ int notes_merge_commit(struct notes_merge_options *o,
        int path_len = strlen(path), i;
        const char *msg = strstr(partial_commit->buffer, "\n\n");
 
-       OUTPUT(o, 3, "Committing notes in notes merge worktree at %.*s",
-              path_len - 1, path);
+       if (o->verbosity >= 3)
+               printf("Committing notes in notes merge worktree at %.*s\n",
+                       path_len - 1, path);
 
        if (!msg || msg[2] == '\0')
                die("partial notes commit has empty message");
@@ -701,7 +714,9 @@ int notes_merge_commit(struct notes_merge_options *o,
                unsigned char obj_sha1[20], blob_sha1[20];
 
                if (ent->len - path_len != 40 || get_sha1_hex(relpath, obj_sha1)) {
-                       OUTPUT(o, 3, "Skipping non-SHA1 entry '%s'", ent->name);
+                       if (o->verbosity >= 3)
+                               printf("Skipping non-SHA1 entry '%s'\n",
+                                                               ent->name);
                        continue;
                }
 
@@ -713,14 +728,16 @@ int notes_merge_commit(struct notes_merge_options *o,
                if (add_note(partial_tree, obj_sha1, blob_sha1, NULL))
                        die("Failed to add resolved note '%s' to notes tree",
                            ent->name);
-               OUTPUT(o, 4, "Added resolved note for object %s: %s",
-                      sha1_to_hex(obj_sha1), sha1_to_hex(blob_sha1));
+               if (o->verbosity >= 4)
+                       printf("Added resolved note for object %s: %s\n",
+                               sha1_to_hex(obj_sha1), sha1_to_hex(blob_sha1));
        }
 
        create_notes_commit(partial_tree, partial_commit->parents, msg,
                            result_sha1);
-       OUTPUT(o, 4, "Finalized notes merge commit: %s",
-              sha1_to_hex(result_sha1));
+       if (o->verbosity >= 4)
+               printf("Finalized notes merge commit: %s\n",
+                       sha1_to_hex(result_sha1));
        free(path);
        return 0;
 }
@@ -732,7 +749,8 @@ int notes_merge_abort(struct notes_merge_options *o)
        int ret;
 
        strbuf_addstr(&buf, git_path(NOTES_MERGE_WORKTREE));
-       OUTPUT(o, 3, "Removing notes merge worktree at %s", buf.buf);
+       if (o->verbosity >= 3)
+               printf("Removing notes merge worktree at %s\n", buf.buf);
        ret = remove_dir_recursively(&buf, 0);
        strbuf_release(&buf);
        return ret;
index 0c19b6e5a5677bd14989175abddc119381fac4ef..63a595c45c961fce54cca95ab6e09e3336f0bb8e 100644 (file)
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "pack.h"
 #include "pack-revindex.h"
+#include "progress.h"
 
 struct idx_entry {
        off_t                offset;
@@ -42,7 +43,10 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,
 }
 
 static int verify_packfile(struct packed_git *p,
-               struct pack_window **w_curs)
+                          struct pack_window **w_curs,
+                          verify_fn fn,
+                          struct progress *progress, uint32_t base_count)
+
 {
        off_t index_size = p->index_size;
        const unsigned char *index_base = p->index_data;
@@ -113,20 +117,25 @@ static int verify_packfile(struct packed_git *p,
                                            p->pack_name, (uintmax_t)offset);
                }
                data = unpack_entry(p, entries[i].offset, &type, &size);
-               if (!data) {
+               if (!data)
                        err = error("cannot unpack %s from %s at offset %"PRIuMAX"",
                                    sha1_to_hex(entries[i].sha1), p->pack_name,
                                    (uintmax_t)entries[i].offset);
-                       break;
-               }
-               if (check_sha1_signature(entries[i].sha1, data, size, typename(type))) {
+               else if (check_sha1_signature(entries[i].sha1, data, size, typename(type)))
                        err = error("packed %s from %s is corrupt",
                                    sha1_to_hex(entries[i].sha1), p->pack_name);
-                       free(data);
-                       break;
+               else if (fn) {
+                       int eaten = 0;
+                       fn(entries[i].sha1, type, size, data, &eaten);
+                       if (eaten)
+                               data = NULL;
                }
+               if (((base_count + i) & 1023) == 0)
+                       display_progress(progress, base_count + i);
                free(data);
+
        }
+       display_progress(progress, base_count + i);
        free(entries);
 
        return err;
@@ -155,7 +164,8 @@ int verify_pack_index(struct packed_git *p)
        return err;
 }
 
-int verify_pack(struct packed_git *p)
+int verify_pack(struct packed_git *p, verify_fn fn,
+               struct progress *progress, uint32_t base_count)
 {
        int err = 0;
        struct pack_window *w_curs = NULL;
@@ -164,7 +174,7 @@ int verify_pack(struct packed_git *p)
        if (!p->index_data)
                return -1;
 
-       err |= verify_packfile(p, &w_curs);
+       err |= verify_packfile(p, &w_curs, fn, progress, base_count);
        unuse_pack(&w_curs);
 
        return err;
diff --git a/pack.h b/pack.h
index 722a54e00a2cb7d9514c12f799fb1ec15930cf5d..324a1d73c041053cf84e81681d11e52a5be6c62b 100644 (file)
--- a/pack.h
+++ b/pack.h
@@ -70,10 +70,14 @@ struct pack_idx_entry {
        off_t offset;
 };
 
+
+struct progress;
+typedef int (*verify_fn)(const unsigned char*, enum object_type, unsigned long, void*, int*);
+
 extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *, unsigned char *sha1);
 extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
 extern int verify_pack_index(struct packed_git *);
-extern int verify_pack(struct packed_git *);
+extern int verify_pack(struct packed_git *, verify_fn fn, struct progress *, uint32_t);
 extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);
 extern char *index_pack_lockfile(int fd);
 extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned char *);
index 98b24772c7ebe838d513d8e24f3c8acff7839cb9..9235e73163204593379cdf6367133b5b503423c2 100644 (file)
@@ -1,5 +1,6 @@
 perl.mak
 perl.mak.old
+MYMETA.yml
 blib
 blibdirs
 pm_to_blib
index f45eb54e4c99b8d67e4aa85f9a6218ea7a560592..230fe1cc82e3a3bf7c0fef604350868d917acef4 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -1094,7 +1094,6 @@ void format_commit_message(const struct commit *commit,
 {
        struct format_commit_context context;
        static const char utf8[] = "UTF-8";
-       const char *enc;
        const char *output_enc = pretty_ctx->output_encoding;
 
        memset(&context, 0, sizeof(context));
@@ -1103,10 +1102,13 @@ void format_commit_message(const struct commit *commit,
        context.wrap_start = sb->len;
        context.message = commit->buffer;
        if (output_enc) {
-               enc = get_header(commit, "encoding");
-               enc = enc ? enc : utf8;
-               if (strcmp(enc, output_enc))
+               char *enc = get_header(commit, "encoding");
+               if (strcmp(enc ? enc : utf8, output_enc)) {
                        context.message = logmsg_reencode(commit, output_enc);
+                       if (!context.message)
+                               context.message = commit->buffer;
+               }
+               free(enc);
        }
 
        strbuf_expand(sb, format, format_commit_item, &context);
index 3fc6b1d320faad3a528db016a0d800ff1bdde4f0..bf7970661f26664e461ed5d6fd7a1982f7e8fadd 100644 (file)
@@ -7,11 +7,25 @@
 #include "revision.h"
 #include "reachable.h"
 #include "cache-tree.h"
+#include "progress.h"
+
+struct connectivity_progress {
+       struct progress *progress;
+       unsigned long count;
+};
+
+static void update_progress(struct connectivity_progress *cp)
+{
+       cp->count++;
+       if ((cp->count & 1023) == 0)
+               display_progress(cp->progress, cp->count);
+}
 
 static void process_blob(struct blob *blob,
                         struct object_array *p,
                         struct name_path *path,
-                        const char *name)
+                        const char *name,
+                        struct connectivity_progress *cp)
 {
        struct object *obj = &blob->object;
 
@@ -20,6 +34,7 @@ static void process_blob(struct blob *blob,
        if (obj->flags & SEEN)
                return;
        obj->flags |= SEEN;
+       update_progress(cp);
        /* Nothing to do, really .. The blob lookup was the important part */
 }
 
@@ -34,7 +49,8 @@ static void process_gitlink(const unsigned char *sha1,
 static void process_tree(struct tree *tree,
                         struct object_array *p,
                         struct name_path *path,
-                        const char *name)
+                        const char *name,
+                        struct connectivity_progress *cp)
 {
        struct object *obj = &tree->object;
        struct tree_desc desc;
@@ -46,6 +62,7 @@ static void process_tree(struct tree *tree,
        if (obj->flags & SEEN)
                return;
        obj->flags |= SEEN;
+       update_progress(cp);
        if (parse_tree(tree) < 0)
                die("bad tree object %s", sha1_to_hex(obj->sha1));
        add_object(obj, p, path, name);
@@ -57,23 +74,25 @@ static void process_tree(struct tree *tree,
 
        while (tree_entry(&desc, &entry)) {
                if (S_ISDIR(entry.mode))
-                       process_tree(lookup_tree(entry.sha1), p, &me, entry.path);
+                       process_tree(lookup_tree(entry.sha1), p, &me, entry.path, cp);
                else if (S_ISGITLINK(entry.mode))
                        process_gitlink(entry.sha1, p, &me, entry.path);
                else
-                       process_blob(lookup_blob(entry.sha1), p, &me, entry.path);
+                       process_blob(lookup_blob(entry.sha1), p, &me, entry.path, cp);
        }
        free(tree->buffer);
        tree->buffer = NULL;
 }
 
-static void process_tag(struct tag *tag, struct object_array *p, const char *name)
+static void process_tag(struct tag *tag, struct object_array *p,
+                       const char *name, struct connectivity_progress *cp)
 {
        struct object *obj = &tag->object;
 
        if (obj->flags & SEEN)
                return;
        obj->flags |= SEEN;
+       update_progress(cp);
 
        if (parse_tag(tag) < 0)
                die("bad tag object %s", sha1_to_hex(obj->sha1));
@@ -81,15 +100,18 @@ static void process_tag(struct tag *tag, struct object_array *p, const char *nam
                add_object(tag->tagged, p, NULL, name);
 }
 
-static void walk_commit_list(struct rev_info *revs)
+static void walk_commit_list(struct rev_info *revs,
+                            struct connectivity_progress *cp)
 {
        int i;
        struct commit *commit;
        struct object_array objects = OBJECT_ARRAY_INIT;
 
        /* Walk all commits, process their trees */
-       while ((commit = get_revision(revs)) != NULL)
-               process_tree(commit->tree, &objects, NULL, "");
+       while ((commit = get_revision(revs)) != NULL) {
+               process_tree(commit->tree, &objects, NULL, "", cp);
+               update_progress(cp);
+       }
 
        /* Then walk all the pending objects, recursively processing them too */
        for (i = 0; i < revs->pending.nr; i++) {
@@ -97,15 +119,15 @@ static void walk_commit_list(struct rev_info *revs)
                struct object *obj = pending->item;
                const char *name = pending->name;
                if (obj->type == OBJ_TAG) {
-                       process_tag((struct tag *) obj, &objects, name);
+                       process_tag((struct tag *) obj, &objects, name, cp);
                        continue;
                }
                if (obj->type == OBJ_TREE) {
-                       process_tree((struct tree *)obj, &objects, NULL, name);
+                       process_tree((struct tree *)obj, &objects, NULL, name, cp);
                        continue;
                }
                if (obj->type == OBJ_BLOB) {
-                       process_blob((struct blob *)obj, &objects, NULL, name);
+                       process_blob((struct blob *)obj, &objects, NULL, name, cp);
                        continue;
                }
                die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
@@ -191,8 +213,11 @@ static void add_cache_refs(struct rev_info *revs)
                add_cache_tree(active_cache_tree, revs);
 }
 
-void mark_reachable_objects(struct rev_info *revs, int mark_reflog)
+void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
+                           struct progress *progress)
 {
+       struct connectivity_progress cp;
+
        /*
         * Set up revision parsing, and mark us as being interested
         * in all object types, not just commits.
@@ -211,11 +236,15 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog)
        if (mark_reflog)
                for_each_reflog(add_one_reflog, revs);
 
+       cp.progress = progress;
+       cp.count = 0;
+
        /*
         * Set up the revision walk - this will move all commits
         * from the pending list to the commit walking list.
         */
        if (prepare_revision_walk(revs))
                die("revision walk setup failed");
-       walk_commit_list(revs);
+       walk_commit_list(revs, &cp);
+       display_progress(cp.progress, cp.count);
 }
index 40751810b64f8bbf9c0a633472a0ef27d23ed1a5..5d082adfecc47c40074212df2ddedc00d8a5ecb1 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef REACHEABLE_H
 #define REACHEABLE_H
 
-extern void mark_reachable_objects(struct rev_info *revs, int mark_reflog);
+struct progress;
+extern void mark_reachable_objects(struct rev_info *revs, int mark_reflog, struct progress *);
 
 #endif
diff --git a/refs.c b/refs.c
index e69ba26b74e430388c63af21473438468678bb4b..e7843eb6b70b7de6c1ed1992db7adee1d99b27bc 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -48,7 +48,7 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
 }
 
 static void add_ref(const char *name, const unsigned char *sha1,
-                   int flag, struct ref_array *refs,
+                   int flag, int check_name, struct ref_array *refs,
                    struct ref_entry **new_entry)
 {
        int len;
@@ -59,7 +59,8 @@ static void add_ref(const char *name, const unsigned char *sha1,
        entry = xmalloc(sizeof(struct ref_entry) + len);
        hashcpy(entry->sha1, sha1);
        hashclr(entry->peeled);
-       if (check_refname_format(name, REFNAME_ALLOW_ONELEVEL|REFNAME_DOT_COMPONENT))
+       if (check_name &&
+           check_refname_format(name, REFNAME_ALLOW_ONELEVEL|REFNAME_DOT_COMPONENT))
                die("Reference has invalid format: '%s'", name);
        memcpy(entry->name, name, len);
        entry->flag = flag;
@@ -234,7 +235,7 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
 
                name = parse_ref_line(refline, sha1);
                if (name) {
-                       add_ref(name, sha1, flag, array, &last);
+                       add_ref(name, sha1, flag, 1, array, &last);
                        continue;
                }
                if (last &&
@@ -249,7 +250,7 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
 
 void add_extra_ref(const char *name, const unsigned char *sha1, int flag)
 {
-       add_ref(name, sha1, flag, &extra_refs, NULL);
+       add_ref(name, sha1, flag, 0, &extra_refs, NULL);
 }
 
 void clear_extra_refs(void)
@@ -333,12 +334,11 @@ static void get_ref_dir(const char *submodule, const char *base,
                                        hashclr(sha1);
                                        flag |= REF_ISBROKEN;
                                }
-                       } else
-                               if (!resolve_ref(ref, sha1, 1, &flag)) {
-                                       hashclr(sha1);
-                                       flag |= REF_ISBROKEN;
-                               }
-                       add_ref(ref, sha1, flag, array, NULL);
+                       } else if (!resolve_ref(ref, sha1, 1, &flag)) {
+                               hashclr(sha1);
+                               flag |= REF_ISBROKEN;
+                       }
+                       add_ref(ref, sha1, flag, 1, array, NULL);
                }
                free(ref);
                closedir(dir);
index 905d29501213f058f0d8cc88e7ba57527d506483..f435fdb4b147d2e2ce5480ddb4832228af1cb73b 100644 (file)
@@ -13,7 +13,7 @@
  *
  * With the aggressive flag, it additionally removes SEQ_OLD_DIR,
  * ignoring any errors.  Inteded to be used by the sequencer's
- * '--reset' subcommand.
+ * '--quit' subcommand.
  */
 void remove_sequencer_state(int aggressive);
 
index 27f3b9b278a97f66f92ca61a2bc39e30f0a70317..956422ba4a5df5f46caaf85f10e4c85321439272 100644 (file)
@@ -1267,7 +1267,8 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
        while (c & 0x80) {
                if (len <= used || bitsizeof(long) <= shift) {
                        error("bad object header");
-                       return 0;
+                       size = used = 0;
+                       break;
                }
                c = buf[used++];
                size += (c & 0x7f) << shift;
@@ -2616,7 +2617,7 @@ static int index_mem(unsigned char *sha1, void *buf, size_t size,
        if ((type == OBJ_BLOB) && path) {
                struct strbuf nbuf = STRBUF_INIT;
                if (convert_to_git(path, buf, size, &nbuf,
-                                  write_object ? safe_crlf : 0)) {
+                                  write_object ? safe_crlf : SAFE_CRLF_FALSE)) {
                        buf = strbuf_detach(&nbuf, &size);
                        re_allocated = 1;
                }
index 0fd10a0fdbf5d1af10819dea808b43f6b13b98a8..52cdcc6a6347a786deafad34efdb9dc4dc3670ff 100644 (file)
@@ -391,7 +391,7 @@ static void commit_need_pushing(struct commit *commit, struct commit_list *paren
        rev.diffopt.format_callback_data = needs_pushing;
        diff_tree_combined(commit->object.sha1, parents, n, 1, &rev);
 
-       free(parents);
+       free((void *)parents);
 }
 
 int check_submodule_needs_pushing(unsigned char new_sha1[20], const char *remotes_name)
index 2f5eada0d2801c7bc99dbbbed4d7b0ff839f25b7..bc73c2099b5069ab136a1d93aef5a8ab4a0dad1f 100755 (executable)
@@ -74,6 +74,11 @@ test_expect_success \
         git branch -d l/m &&
         git branch l'
 
+test_expect_success \
+    'git branch -m dumps usage' \
+       'test_expect_code 129 git branch -m 2>err &&
+       grep "[Uu]sage: git branch" err'
+
 test_expect_success \
     'git branch -m m m/m should work' \
        'git branch -l m &&
index cb45574a7b5cbdf6da58f609befc4a0bb396db2f..ee1659c17810d2c9ce7836582a80fd3d0d89ca24 100755 (executable)
@@ -253,6 +253,60 @@ test_expect_success 'revert also handles conflicts sanely' '
        test_cmp expected actual
 '
 
+test_expect_success 'failed revert sets REVERT_HEAD' '
+       pristine_detach initial &&
+       test_must_fail git revert picked &&
+       test_cmp_rev picked REVERT_HEAD
+'
+
+test_expect_success 'successful revert does not set REVERT_HEAD' '
+       pristine_detach base &&
+       git revert base &&
+       test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
+       test_must_fail git rev-parse --verify REVERT_HEAD
+'
+
+test_expect_success 'revert --no-commit sets REVERT_HEAD' '
+       pristine_detach base &&
+       git revert --no-commit base &&
+       test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
+       test_cmp_rev base REVERT_HEAD
+'
+
+test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' '
+       pristine_detach base &&
+       echo foo > foo &&
+       test_must_fail git revert base &&
+       test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
+       test_must_fail git rev-parse --verify REVERT_HEAD
+'
+
+test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
+       pristine_detach initial &&
+       (
+               GIT_CHERRY_PICK_HELP="and then do something else" &&
+               GIT_REVERT_HELP="and then do something else, again" &&
+               export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
+               test_must_fail git revert picked
+       ) &&
+       test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
+       test_cmp_rev picked REVERT_HEAD
+'
+
+test_expect_success 'git reset clears REVERT_HEAD' '
+       pristine_detach initial &&
+       test_must_fail git revert picked &&
+       git reset &&
+       test_must_fail git rev-parse --verify REVERT_HEAD
+'
+
+test_expect_success 'failed commit does not clear REVERT_HEAD' '
+       pristine_detach initial &&
+       test_must_fail git revert picked &&
+       test_must_fail git commit &&
+       test_cmp_rev picked REVERT_HEAD
+'
+
 test_expect_success 'revert conflict, diff3 -m style' '
        pristine_detach initial &&
        git config merge.conflictstyle diff3 &&
index 3bca2b3dd5cc252cad615b83f84891f6dc2bacfe..2c4c1c851dcbb1cd38edc2a2620e2b04e36f7192 100755 (executable)
@@ -2,6 +2,7 @@
 
 test_description='Test cherry-pick continuation features
 
+  + yetanotherpick: rewrites foo to e
   + anotherpick: rewrites foo to d
   + picked: rewrites foo to c
   + unrelatedpick: rewrites unrelated to reallyunrelated
@@ -13,12 +14,18 @@ test_description='Test cherry-pick continuation features
 . ./test-lib.sh
 
 pristine_detach () {
-       git cherry-pick --reset &&
+       git cherry-pick --quit &&
        git checkout -f "$1^0" &&
        git read-tree -u --reset HEAD &&
        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 '
        echo unrelated >unrelated &&
        git add unrelated &&
@@ -27,6 +34,7 @@ test_expect_success setup '
        test_commit unrelatedpick unrelated reallyunrelated &&
        test_commit picked foo c &&
        test_commit anotherpick foo d &&
+       test_commit yetanotherpick foo e &&
        git config advice.detachedhead false
 
 '
@@ -70,18 +78,117 @@ test_expect_success 'cherry-pick cleans up sequencer state upon success' '
        test_path_is_missing .git/sequencer
 '
 
-test_expect_success '--reset does not complain when no cherry-pick is in progress' '
+test_expect_success '--quit does not complain when no cherry-pick is in progress' '
        pristine_detach initial &&
-       git cherry-pick --reset
+       git cherry-pick --quit
 '
 
-test_expect_success '--reset cleans up sequencer state' '
+test_expect_success '--abort requires cherry-pick in progress' '
+       pristine_detach initial &&
+       test_must_fail git cherry-pick --abort
+'
+
+test_expect_success '--quit cleans up sequencer state' '
        pristine_detach initial &&
        test_must_fail git cherry-pick base..picked &&
-       git cherry-pick --reset &&
+       git cherry-pick --quit &&
        test_path_is_missing .git/sequencer
 '
 
+test_expect_success '--quit keeps HEAD and conflicted index intact' '
+       pristine_detach initial &&
+       cat >expect <<-\EOF &&
+       OBJID
+       :100644 100644 OBJID OBJID M    unrelated
+       OBJID
+       :000000 100644 OBJID OBJID A    foo
+       :000000 100644 OBJID OBJID A    unrelated
+       EOF
+       test_must_fail git cherry-pick base..picked &&
+       git cherry-pick --quit &&
+       test_path_is_missing .git/sequencer &&
+       test_must_fail git update-index --refresh &&
+       {
+               git rev-list HEAD |
+               git diff-tree --root --stdin |
+               sed "s/$_x40/OBJID/g"
+       } >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success '--abort to cancel multiple cherry-pick' '
+       pristine_detach initial &&
+       test_must_fail git cherry-pick base..anotherpick &&
+       git cherry-pick --abort &&
+       test_path_is_missing .git/sequencer &&
+       test_cmp_rev initial HEAD &&
+       git update-index --refresh &&
+       git diff-index --exit-code HEAD
+'
+
+test_expect_success '--abort to cancel single cherry-pick' '
+       pristine_detach initial &&
+       test_must_fail git cherry-pick picked &&
+       git cherry-pick --abort &&
+       test_path_is_missing .git/sequencer &&
+       test_cmp_rev initial HEAD &&
+       git update-index --refresh &&
+       git diff-index --exit-code HEAD
+'
+
+test_expect_success 'cherry-pick --abort to cancel multiple revert' '
+       pristine_detach anotherpick &&
+       test_must_fail git revert base..picked &&
+       git cherry-pick --abort &&
+       test_path_is_missing .git/sequencer &&
+       test_cmp_rev anotherpick HEAD &&
+       git update-index --refresh &&
+       git diff-index --exit-code HEAD
+'
+
+test_expect_success 'revert --abort works, too' '
+       pristine_detach anotherpick &&
+       test_must_fail git revert base..picked &&
+       git revert --abort &&
+       test_path_is_missing .git/sequencer &&
+       test_cmp_rev anotherpick HEAD
+'
+
+test_expect_success '--abort to cancel single revert' '
+       pristine_detach anotherpick &&
+       test_must_fail git revert picked &&
+       git revert --abort &&
+       test_path_is_missing .git/sequencer &&
+       test_cmp_rev anotherpick HEAD &&
+       git update-index --refresh &&
+       git diff-index --exit-code HEAD
+'
+
+test_expect_success '--abort keeps unrelated change, easy case' '
+       pristine_detach unrelatedpick &&
+       echo changed >expect &&
+       test_must_fail git cherry-pick picked..yetanotherpick &&
+       echo changed >unrelated &&
+       git cherry-pick --abort &&
+       test_cmp expect unrelated
+'
+
+test_expect_success '--abort refuses to clobber unrelated change, harder case' '
+       pristine_detach initial &&
+       echo changed >expect &&
+       test_must_fail git cherry-pick base..anotherpick &&
+       echo changed >unrelated &&
+       test_must_fail git cherry-pick --abort &&
+       test_cmp expect unrelated &&
+       git rev-list HEAD >log &&
+       test_line_count = 2 log &&
+       test_must_fail git update-index --refresh &&
+
+       git checkout unrelated &&
+       git cherry-pick --abort &&
+       test_cmp_rev initial HEAD
+'
+
 test_expect_success 'cherry-pick cleans up sequencer state when one commit is left' '
        pristine_detach initial &&
        test_must_fail git cherry-pick base..picked &&
@@ -106,6 +213,16 @@ test_expect_success 'cherry-pick cleans up sequencer state when one commit is le
        test_cmp expect actual
 '
 
+test_expect_failure '--abort after last commit in sequence' '
+       pristine_detach initial &&
+       test_must_fail git cherry-pick base..picked &&
+       git cherry-pick --abort &&
+       test_path_is_missing .git/sequencer &&
+       test_cmp_rev initial HEAD &&
+       git update-index --refresh &&
+       git diff-index --exit-code HEAD
+'
+
 test_expect_success 'cherry-pick does not implicitly stomp an existing operation' '
        pristine_detach initial &&
        test_must_fail git cherry-pick base..anotherpick &&
index b5ced8483a8fc663eb53b514bbb56df92f217deb..1bc57ac03f9df7e82fab5478b7234ab1435c60e3 100755 (executable)
@@ -28,7 +28,7 @@ test_expect_success setup '
                done
        ) &&
        (
-               git clone --reference=original "file:///$(pwd)/original" one &&
+               git clone --reference=original "file://$(pwd)/original" one &&
                cd one &&
                echo Z >count &&
                git add count &&
index 895f5595aee9341276e79497b9c4a8736c78e5e7..c4c375ac042bbb7f58998c87d8c9277d2f5004a6 100755 (executable)
@@ -146,4 +146,11 @@ test_expect_success 'cloning with reference being subset of source (-l -s)' \
 
 cd "$base_dir"
 
+test_expect_success 'clone with reference from a tagged repository' '
+       (
+               cd A && git tag -a -m 'tagged' HEAD
+       ) &&
+       git clone --reference=A A I
+'
+
 test_done
index c6f1f9f8ab2353ec81401828f8500cb7c1a869fb..691e4a4481eba2994ec40e498d4cd25fcff67f26 100755 (executable)
@@ -164,7 +164,7 @@ test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if
        cp .git/BISECT_START saved &&
        test_must_fail git bisect start $HASH4 foo -- &&
        git branch > branch.output &&
-       grep "* (no branch)" branch.output > /dev/null &&
+       test_i18ngrep "* (no branch)" branch.output > /dev/null &&
        test_cmp saved .git/BISECT_START
 '
 test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' '
index 4956caaf82be8c42ef01a9adae55387e87adaa04..83f7ea59c9b4e05aa200bc4ebd77f0c16bd8ef33 100755 (executable)
@@ -12,7 +12,7 @@ test_description='Test interaction of reset --hard with sequencer
 . ./test-lib.sh
 
 pristine_detach () {
-       git cherry-pick --reset &&
+       git cherry-pick --quit &&
        git checkout -f "$1^0" &&
        git read-tree -u --reset HEAD &&
        git clean -d -f -f -q -x
@@ -41,4 +41,12 @@ test_expect_success 'reset --hard cleans up sequencer state, providing one-level
        test_path_is_missing .git/sequencer-old
 '
 
+test_expect_success 'cherry-pick --abort does not leave sequencer-old dir' '
+       pristine_detach initial &&
+       test_must_fail git cherry-pick base..anotherpick &&
+       git cherry-pick --abort &&
+       test_path_is_missing .git/sequencer &&
+       test_path_is_missing .git/sequencer-old
+'
+
 test_done
index 905255adf0ca5b15d9befa772cda4a650bd15f34..fc57b135c50e34ab86c04d0a0ec81052ce40f8ff 100755 (executable)
@@ -189,7 +189,7 @@ test_expect_success 'status with gitignore' '
        #       untracked
        EOF
        git status --ignored >output &&
-       test_cmp expect output
+       test_i18ncmp expect output
 '
 
 test_expect_success 'status with gitignore (nothing untracked)' '
@@ -247,7 +247,7 @@ test_expect_success 'status with gitignore (nothing untracked)' '
        #       untracked
        EOF
        git status --ignored >output &&
-       test_cmp expect output
+       test_i18ncmp expect output
 '
 
 rm -f .gitignore
index bca359dc1e9afb9195990c583fbf3f1d03ed4bfa..b5fdc048a54a151f78b10e9d379383a421cf3726 100755 (executable)
@@ -24,7 +24,7 @@ check() {
 
 check  1
 check  2 p
-check  3 pr
+check  3 px
 check  4 pre
 check  5 pref
 check  6 prefi
index 32ec82ad678d56bbf27f525fc8588b3391d9117d..4ee42f12f0af6bc7e4b072350f88988b85e40cbb 100755 (executable)
@@ -15,6 +15,7 @@ EOF
 chmod +x helper
 
 test_expect_success 'setup ' '
+       echo "bin: test number 0" >zero.bin &&
        echo "bin: test 1" >one.bin &&
        echo "bin: test number 2" >two.bin &&
        if test_have_prereq SYMLINKS; then
@@ -43,6 +44,7 @@ test_expect_success 'no filter specified' '
 
 test_expect_success 'setup textconv filters' '
        echo "*.bin diff=test" >.gitattributes &&
+       echo "zero.bin eol=crlf" >>.gitattributes &&
        git config diff.test.textconv ./helper &&
        git config diff.test.cachetextconv false
 '
@@ -74,6 +76,15 @@ test_expect_success 'blame --textconv going through revisions' '
        test_cmp expected result
 '
 
+test_expect_success 'blame --textconv with local changes' '
+       test_when_finished "git checkout zero.bin" &&
+       printf "bin: updated number 0\015" >zero.bin &&
+       git blame --textconv zero.bin >blame &&
+       expect="(Not Committed Yet ....-..-.. ..:..:.. +0000 1)" &&
+       expect="$expect converted: updated number 0" &&
+       expr "$(find_blame <blame)" : "^$expect"
+'
+
 test_expect_success 'setup +cachetextconv' '
        git config diff.test.cachetextconv true
 '
index 3b358ef8d8fa485d9d43fe680b13f3961c5c79f8..992bb8cf0ba40104e4c6c43babcd2edbb4ac90f1 100755 (executable)
@@ -101,6 +101,37 @@ test_expect_success 'keyword file test' '
        )
 '
 
+build_gendouble() {
+       cat >gendouble.py <<-\EOF
+       import sys
+       import struct
+       import array
+
+       s = array.array("c", '\0' * 26)
+       struct.pack_into(">L", s,  0, 0x00051607)  # AppleDouble
+       struct.pack_into(">L", s,  4, 0x00020000)  # version 2
+       s.tofile(sys.stdout)
+       EOF
+}
+
+test_expect_success 'ignore apple' '
+       test_when_finished rm -f gendouble.py &&
+       build_gendouble &&
+       (
+               cd "$cli" &&
+               test-genrandom apple 1024 >double.png &&
+               "$PYTHON_PATH" "$TRASH_DIRECTORY/gendouble.py" >%double.png &&
+               p4 add -t apple double.png &&
+               p4 submit -d appledouble
+       ) &&
+       test_when_finished cleanup_git &&
+       "$GITP4" clone --dest="$git" //depot@all &&
+       (
+               cd "$git" &&
+               test ! -f double.png
+       )
+'
+
 test_expect_success 'kill p4d' '
        kill_p4d
 '
diff --git a/t/t9805-skip-submit-edit.sh b/t/t9805-skip-submit-edit.sh
new file mode 100755 (executable)
index 0000000..734ccf2
--- /dev/null
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+test_description='git-p4 skipSubmitEdit config variables'
+
+. ./lib-git-p4.sh
+
+test_expect_success 'start p4d' '
+       start_p4d
+'
+
+test_expect_success 'init depot' '
+       (
+               cd "$cli" &&
+               echo file1 >file1 &&
+               p4 add file1 &&
+               p4 submit -d "change 1"
+       )
+'
+
+# this works because EDITOR is set to :
+test_expect_success 'no config, unedited, say yes' '
+       "$GITP4" clone --dest="$git" //depot &&
+       test_when_finished cleanup_git &&
+       (
+               cd "$git" &&
+               echo line >>file1 &&
+               git commit -a -m "change 2" &&
+               echo y | "$GITP4" submit &&
+               p4 changes //depot/... >wc &&
+               test_line_count = 2 wc
+       )
+'
+
+test_expect_success 'no config, unedited, say no' '
+       "$GITP4" clone --dest="$git" //depot &&
+       test_when_finished cleanup_git &&
+       (
+               cd "$git" &&
+               echo line >>file1 &&
+               git commit -a -m "change 3 (not really)" &&
+               printf "bad response\nn\n" | "$GITP4" submit
+               p4 changes //depot/... >wc &&
+               test_line_count = 2 wc
+       )
+'
+
+test_expect_success 'skipSubmitEdit' '
+       "$GITP4" clone --dest="$git" //depot &&
+       test_when_finished cleanup_git &&
+       (
+               cd "$git" &&
+               git config git-p4.skipSubmitEdit true &&
+               # will fail if editor is even invoked
+               git config core.editor /bin/false &&
+               echo line >>file1 &&
+               git commit -a -m "change 3" &&
+               "$GITP4" submit &&
+               p4 changes //depot/... >wc &&
+               test_line_count = 3 wc
+       )
+'
+
+test_expect_success 'skipSubmitEditCheck' '
+       "$GITP4" clone --dest="$git" //depot &&
+       test_when_finished cleanup_git &&
+       (
+               cd "$git" &&
+               git config git-p4.skipSubmitEditCheck true &&
+               echo line >>file1 &&
+               git commit -a -m "change 4" &&
+               "$GITP4" submit &&
+               p4 changes //depot/... >wc &&
+               test_line_count = 4 wc
+       )
+'
+
+
+test_expect_success 'kill p4d' '
+       kill_p4d
+'
+
+test_done
index b3cc2e4753447d4734ed08a70e3396771257dced..7a51d091b5a6babed91f60b9ff7079308afa4e6f 100644 (file)
@@ -21,8 +21,8 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
        sha1 = tree_entry_extract(t1, &path1, &mode1);
        sha2 = tree_entry_extract(t2, &path2, &mode2);
 
-       pathlen1 = tree_entry_len(path1, sha1);
-       pathlen2 = tree_entry_len(path2, sha2);
+       pathlen1 = tree_entry_len(&t1->entry);
+       pathlen2 = tree_entry_len(&t2->entry);
        cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2);
        if (cmp < 0) {
                show_entry(opt, "-", t1, base);
@@ -64,14 +64,14 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
 static void show_tree(struct diff_options *opt, const char *prefix,
                      struct tree_desc *desc, struct strbuf *base)
 {
-       int match = 0;
+       enum interesting match = entry_not_interesting;
        for (; desc->size; update_tree_entry(desc)) {
-               if (match != 2) {
+               if (match != all_entries_interesting) {
                        match = tree_entry_interesting(&desc->entry, base, 0,
                                                       &opt->pathspec);
-                       if (match < 0)
+                       if (match == all_entries_not_interesting)
                                break;
-                       if (match == 0)
+                       if (match == entry_not_interesting)
                                continue;
                }
                show_entry(opt, prefix, desc, base);
@@ -85,7 +85,7 @@ static void show_entry(struct diff_options *opt, const char *prefix,
        unsigned mode;
        const char *path;
        const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode);
-       int pathlen = tree_entry_len(path, sha1);
+       int pathlen = tree_entry_len(&desc->entry);
        int old_baselen = base->len;
 
        strbuf_add(base, path, pathlen);
@@ -114,12 +114,13 @@ static void show_entry(struct diff_options *opt, const char *prefix,
 }
 
 static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
-                              struct diff_options *opt, int *match)
+                              struct diff_options *opt,
+                              enum interesting *match)
 {
        while (t->size) {
                *match = tree_entry_interesting(&t->entry, base, 0, &opt->pathspec);
                if (*match) {
-                       if (*match < 0)
+                       if (*match == all_entries_not_interesting)
                                t->size = 0;
                        break;
                }
@@ -132,7 +133,8 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
 {
        struct strbuf base;
        int baselen = strlen(base_str);
-       int t1_match = 0, t2_match = 0;
+       enum interesting t1_match = entry_not_interesting;
+       enum interesting t2_match = entry_not_interesting;
 
        /* Enable recursion indefinitely */
        opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
index 418107ec83728473093b43dfe74ab709f312e8a8..f82dba6a1f43bf2a259952a4fd6db94d6335deb7 100644 (file)
@@ -116,7 +116,7 @@ void setup_traverse_info(struct traverse_info *info, const char *base)
 
 char *make_traverse_path(char *path, const struct traverse_info *info, const struct name_entry *n)
 {
-       int len = tree_entry_len(n->path, n->sha1);
+       int len = tree_entry_len(n);
        int pathlen = info->pathlen;
 
        path[pathlen + len] = 0;
@@ -126,7 +126,7 @@ char *make_traverse_path(char *path, const struct traverse_info *info, const str
                        break;
                path[--pathlen] = '/';
                n = &info->name;
-               len = tree_entry_len(n->path, n->sha1);
+               len = tree_entry_len(n);
                info = info->prev;
                pathlen -= len;
        }
@@ -253,7 +253,7 @@ static void extended_entry_extract(struct tree_desc_x *t,
         * The caller wants "first" from this tree, or nothing.
         */
        path = a->path;
-       len = tree_entry_len(a->path, a->sha1);
+       len = tree_entry_len(a);
        switch (check_entry_match(first, first_len, path, len)) {
        case -1:
                entry_clear(a);
@@ -271,7 +271,7 @@ static void extended_entry_extract(struct tree_desc_x *t,
        while (probe.size) {
                entry_extract(&probe, a);
                path = a->path;
-               len = tree_entry_len(a->path, a->sha1);
+               len = tree_entry_len(a);
                switch (check_entry_match(first, first_len, path, len)) {
                case -1:
                        entry_clear(a);
@@ -362,7 +362,7 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
                        e = entry + i;
                        if (!e->path)
                                continue;
-                       len = tree_entry_len(e->path, e->sha1);
+                       len = tree_entry_len(e);
                        if (!first) {
                                first = e->path;
                                first_len = len;
@@ -381,7 +381,7 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
                                /* Cull the ones that are not the earliest */
                                if (!e->path)
                                        continue;
-                               len = tree_entry_len(e->path, e->sha1);
+                               len = tree_entry_len(e);
                                if (name_compare(e->path, len, first, first_len))
                                        entry_clear(e);
                        }
@@ -434,8 +434,8 @@ static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char
                int entrylen, cmp;
 
                sha1 = tree_entry_extract(t, &entry, mode);
+               entrylen = tree_entry_len(&t->entry);
                update_tree_entry(t);
-               entrylen = tree_entry_len(entry, sha1);
                if (entrylen > namelen)
                        continue;
                cmp = memcmp(name, entry, entrylen);
@@ -465,7 +465,6 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch
        int retval;
        void *tree;
        unsigned long size;
-       struct tree_desc t;
        unsigned char root[20];
 
        tree = read_object_with_reference(tree_sha1, tree_type, &size, root);
@@ -478,8 +477,13 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch
                return 0;
        }
 
-       init_tree_desc(&t, tree, size);
-       retval = find_tree_entry(&t, name, sha1, mode);
+       if (!size) {
+               retval = -1;
+       } else {
+               struct tree_desc t;
+               init_tree_desc(&t, tree, size);
+               retval = find_tree_entry(&t, name, sha1, mode);
+       }
        free(tree);
        return retval;
 }
@@ -573,30 +577,26 @@ static int match_dir_prefix(const char *base,
  *
  * Pre-condition: either baselen == base_offset (i.e. empty path)
  * or base[baselen-1] == '/' (i.e. with trailing slash).
- *
- * Return:
- *  - 2 for "yes, and all subsequent entries will be"
- *  - 1 for yes
- *  - zero for no
- *  - negative for "no, and no subsequent entries will be either"
  */
-int tree_entry_interesting(const struct name_entry *entry,
-                          struct strbuf *base, int base_offset,
-                          const struct pathspec *ps)
+enum interesting tree_entry_interesting(const struct name_entry *entry,
+                                       struct strbuf *base, int base_offset,
+                                       const struct pathspec *ps)
 {
        int i;
        int pathlen, baselen = base->len - base_offset;
-       int never_interesting = ps->has_wildcard ? 0 : -1;
+       int never_interesting = ps->has_wildcard ?
+               entry_not_interesting : all_entries_not_interesting;
 
        if (!ps->nr) {
                if (!ps->recursive || ps->max_depth == -1)
-                       return 2;
-               return !!within_depth(base->buf + base_offset, baselen,
-                                     !!S_ISDIR(entry->mode),
-                                     ps->max_depth);
+                       return all_entries_interesting;
+               return within_depth(base->buf + base_offset, baselen,
+                                   !!S_ISDIR(entry->mode),
+                                   ps->max_depth) ?
+                       entry_interesting : entry_not_interesting;
        }
 
-       pathlen = tree_entry_len(entry->path, entry->sha1);
+       pathlen = tree_entry_len(entry);
 
        for (i = ps->nr - 1; i >= 0; i--) {
                const struct pathspec_item *item = ps->items+i;
@@ -610,12 +610,13 @@ int tree_entry_interesting(const struct name_entry *entry,
                                goto match_wildcards;
 
                        if (!ps->recursive || ps->max_depth == -1)
-                               return 2;
+                               return all_entries_interesting;
 
-                       return !!within_depth(base_str + matchlen + 1,
-                                             baselen - matchlen - 1,
-                                             !!S_ISDIR(entry->mode),
-                                             ps->max_depth);
+                       return within_depth(base_str + matchlen + 1,
+                                           baselen - matchlen - 1,
+                                           !!S_ISDIR(entry->mode),
+                                           ps->max_depth) ?
+                               entry_interesting : entry_not_interesting;
                }
 
                /* Either there must be no base, or the base must match. */
@@ -623,25 +624,25 @@ int tree_entry_interesting(const struct name_entry *entry,
                        if (match_entry(entry, pathlen,
                                        match + baselen, matchlen - baselen,
                                        &never_interesting))
-                               return 1;
+                               return entry_interesting;
 
-                       if (ps->items[i].use_wildcard) {
+                       if (item->use_wildcard) {
                                if (!fnmatch(match + baselen, entry->path, 0))
-                                       return 1;
+                                       return entry_interesting;
 
                                /*
                                 * Match all directories. We'll try to
                                 * match files later on.
                                 */
                                if (ps->recursive && S_ISDIR(entry->mode))
-                                       return 1;
+                                       return entry_interesting;
                        }
 
                        continue;
                }
 
 match_wildcards:
-               if (!ps->items[i].use_wildcard)
+               if (!item->use_wildcard)
                        continue;
 
                /*
@@ -653,7 +654,7 @@ int tree_entry_interesting(const struct name_entry *entry,
 
                if (!fnmatch(match, base->buf + base_offset, 0)) {
                        strbuf_setlen(base, base_offset + baselen);
-                       return 1;
+                       return entry_interesting;
                }
                strbuf_setlen(base, base_offset + baselen);
 
@@ -662,7 +663,7 @@ int tree_entry_interesting(const struct name_entry *entry,
                 * later on.
                 */
                if (ps->recursive && S_ISDIR(entry->mode))
-                       return 1;
+                       return entry_interesting;
        }
        return never_interesting; /* No matches */
 }
index 0089581e1dd55800302799a7381d4a7ad01bd79d..2bf0db9814a5c9f77fe00c97fa4f723986a7aac1 100644 (file)
@@ -20,9 +20,9 @@ static inline const unsigned char *tree_entry_extract(struct tree_desc *desc, co
        return desc->entry.sha1;
 }
 
-static inline int tree_entry_len(const char *name, const unsigned char *sha1)
+static inline int tree_entry_len(const struct name_entry *ne)
 {
-       return (const char *)sha1 - name - 1;
+       return (const char *)ne->sha1 - ne->path - 1;
 }
 
 void update_tree_entry(struct tree_desc *);
@@ -58,9 +58,19 @@ extern void setup_traverse_info(struct traverse_info *info, const char *base);
 
 static inline int traverse_path_len(const struct traverse_info *info, const struct name_entry *n)
 {
-       return info->pathlen + tree_entry_len(n->path, n->sha1);
+       return info->pathlen + tree_entry_len(n);
 }
 
-extern int tree_entry_interesting(const struct name_entry *, struct strbuf *, int, const struct pathspec *ps);
+/* in general, positive means "kind of interesting" */
+enum interesting {
+       all_entries_not_interesting = -1, /* no, and no subsequent entries will be either */
+       entry_not_interesting = 0,
+       entry_interesting = 1,
+       all_entries_interesting = 2 /* yes, and all subsequent entries will be */
+};
+
+extern enum interesting tree_entry_interesting(const struct name_entry *,
+                                              struct strbuf *, int,
+                                              const struct pathspec *ps);
 
 #endif
diff --git a/tree.c b/tree.c
index 698ecf7af13871cf9639e969f368ba5d7b2e940a..676e9f710ca8d5a568e0c6ea2fa88132da81b48c 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -52,7 +52,8 @@ static int read_tree_1(struct tree *tree, struct strbuf *base,
        struct tree_desc desc;
        struct name_entry entry;
        unsigned char sha1[20];
-       int len, retval = 0, oldlen = base->len;
+       int len, oldlen = base->len;
+       enum interesting retval = entry_not_interesting;
 
        if (parse_tree(tree))
                return -1;
@@ -60,11 +61,11 @@ static int read_tree_1(struct tree *tree, struct strbuf *base,
        init_tree_desc(&desc, tree->buffer, tree->size);
 
        while (tree_entry(&desc, &entry)) {
-               if (retval != 2) {
+               if (retval != all_entries_interesting) {
                        retval = tree_entry_interesting(&entry, base, 0, pathspec);
-                       if (retval < 0)
+                       if (retval == all_entries_not_interesting)
                                break;
-                       if (retval == 0)
+                       if (retval == entry_not_interesting)
                                continue;
                }
 
@@ -99,7 +100,7 @@ static int read_tree_1(struct tree *tree, struct strbuf *base,
                else
                        continue;
 
-               len = tree_entry_len(entry.path, entry.sha1);
+               len = tree_entry_len(&entry);
                strbuf_add(base, entry.path, len);
                strbuf_addch(base, '/');
                retval = read_tree_1(lookup_tree(sha1),
index 8282f5e5f6c615460e1c340d66e395c2d57aef73..7c9ecf665d062d79e9208875d9bf2577e98f4fb2 100644 (file)
@@ -446,7 +446,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
        newinfo.prev = info;
        newinfo.pathspec = info->pathspec;
        newinfo.name = *p;
-       newinfo.pathlen += tree_entry_len(p->path, p->sha1) + 1;
+       newinfo.pathlen += tree_entry_len(p) + 1;
        newinfo.conflicts |= df_conflicts;
 
        for (i = 0; i < n; i++, dirmask >>= 1) {
@@ -495,7 +495,7 @@ static int do_compare_entry(const struct cache_entry *ce, const struct traverse_
        ce_len -= pathlen;
        ce_name = ce->name + pathlen;
 
-       len = tree_entry_len(n->path, n->sha1);
+       len = tree_entry_len(n);
        return df_name_compare(ce_name, ce_len, S_IFREG, n->path, len, n->mode);
 }
 
@@ -626,7 +626,7 @@ static int find_cache_pos(struct traverse_info *info,
        struct unpack_trees_options *o = info->data;
        struct index_state *index = o->src_index;
        int pfxlen = info->pathlen;
-       int p_len = tree_entry_len(p->path, p->sha1);
+       int p_len = tree_entry_len(p);
 
        for (pos = o->cache_bottom; pos < index->cache_nr; pos++) {
                struct cache_entry *ce = index->cache[pos];