Merge branch 'ep/ident-with-getaddrinfo'
authorJunio C Hamano <gitster@pobox.com>
Tue, 15 Dec 2015 17:33:19 +0000 (09:33 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 15 Dec 2015 17:33:19 +0000 (09:33 -0800)
A fix-up for recent topic.

* ep/ident-with-getaddrinfo:
  ident: fix undefined variable when NO_IPV6 is set

368 files changed:
.gitignore
.travis.yml [new file with mode: 0644]
Documentation/RelNotes/1.7.7.txt
Documentation/RelNotes/1.8.3.1.txt
Documentation/RelNotes/1.8.4.1.txt
Documentation/RelNotes/1.8.4.2.txt
Documentation/RelNotes/1.8.4.3.txt
Documentation/RelNotes/1.8.4.4.txt
Documentation/RelNotes/1.9.0.txt
Documentation/RelNotes/2.6.3.txt [new file with mode: 0644]
Documentation/RelNotes/2.6.4.txt [new file with mode: 0644]
Documentation/RelNotes/2.6.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.7.0.txt [new file with mode: 0644]
Documentation/blame-options.txt
Documentation/config.txt
Documentation/diff-options.txt
Documentation/git-bisect.txt
Documentation/git-branch.txt
Documentation/git-cat-file.txt
Documentation/git-check-attr.txt
Documentation/git-check-ignore.txt
Documentation/git-check-ref-format.txt
Documentation/git-checkout.txt
Documentation/git-clone.txt
Documentation/git-commit-tree.txt
Documentation/git-fetch.txt
Documentation/git-fmt-merge-msg.txt
Documentation/git-for-each-ref.txt
Documentation/git-get-tar-commit-id.txt
Documentation/git-hash-object.txt
Documentation/git-merge-file.txt
Documentation/git-mktag.txt
Documentation/git-p4.txt
Documentation/git-patch-id.txt
Documentation/git-push.txt
Documentation/git-quiltimport.txt
Documentation/git-rebase.txt
Documentation/git-remote.txt
Documentation/git-rev-list.txt
Documentation/git-send-email.txt
Documentation/git-show-index.txt
Documentation/git-show-ref.txt
Documentation/git-stash.txt
Documentation/git-stripspace.txt
Documentation/git-submodule.txt
Documentation/git-tag.txt
Documentation/git-unpack-objects.txt
Documentation/git-update-index.txt
Documentation/git-upload-archive.txt
Documentation/git-worktree.txt
Documentation/git.txt
Documentation/giteveryday.txt
Documentation/gitignore.txt
Documentation/gitrevisions.txt
Documentation/glossary-content.txt
Documentation/rev-list-options.txt
Documentation/technical/api-run-command.txt
Documentation/technical/index-format.txt
Documentation/technical/repository-version.txt [new file with mode: 0644]
Documentation/urls-remotes.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
RelNotes
archive-tar.c
archive.c
bisect.c
block-sha1/sha1.h
branch.c
branch.h
builtin.h
builtin/add.c
builtin/am.c
builtin/apply.c
builtin/blame.c
builtin/branch.c
builtin/cat-file.c
builtin/check-attr.c
builtin/check-ignore.c
builtin/checkout.c
builtin/clean.c
builtin/clone.c
builtin/commit-tree.c
builtin/commit.c
builtin/config.c
builtin/count-objects.c
builtin/describe.c
builtin/diff-tree.c
builtin/diff.c
builtin/fast-export.c
builtin/fetch-pack.c
builtin/fetch.c
builtin/fmt-merge-msg.c
builtin/for-each-ref.c
builtin/fsck.c
builtin/gc.c
builtin/get-tar-commit-id.c
builtin/grep.c
builtin/hash-object.c
builtin/help.c
builtin/index-pack.c
builtin/init-db.c
builtin/log.c
builtin/ls-remote.c
builtin/ls-tree.c
builtin/mailinfo.c
builtin/mailsplit.c
builtin/merge-base.c
builtin/merge-file.c
builtin/merge-index.c
builtin/merge-recursive.c
builtin/merge-tree.c
builtin/merge.c
builtin/mktag.c
builtin/name-rev.c
builtin/notes.c
builtin/pack-objects.c
builtin/patch-id.c
builtin/prune.c
builtin/pull.c
builtin/read-tree.c
builtin/receive-pack.c
builtin/reflog.c
builtin/remote-ext.c
builtin/remote.c
builtin/repack.c
builtin/replace.c
builtin/rerere.c
builtin/reset.c
builtin/rev-list.c
builtin/rev-parse.c
builtin/shortlog.c
builtin/show-branch.c
builtin/show-ref.c
builtin/stripspace.c
builtin/submodule--helper.c [new file with mode: 0644]
builtin/tag.c
builtin/unpack-file.c
builtin/unpack-objects.c
builtin/upload-archive.c
builtin/worktree.c
bulk-checkin.c
bundle.c
cache-tree.c
cache.h
color.c
color.h
combine-diff.c
commit.c
compat/apple-common-crypto.h
compat/hstrerror.c
compat/inet_ntop.c
compat/mingw.c
compat/nedmalloc/nedmalloc.c
compat/precompose_utf8.c
compat/precompose_utf8.h
compat/regex/regcomp.c
compat/sha1-chunked.c [new file with mode: 0644]
compat/sha1-chunked.h [new file with mode: 0644]
compat/winansi.c
config.c
config.mak.uname
configure.ac
connect.c
contrib/completion/git-completion.bash
contrib/completion/git-prompt.sh
contrib/hooks/multimail/CHANGES
contrib/hooks/multimail/CONTRIBUTING.rst [new file with mode: 0644]
contrib/hooks/multimail/README
contrib/hooks/multimail/README.Git
contrib/hooks/multimail/doc/gerrit.rst [new file with mode: 0644]
contrib/hooks/multimail/doc/gitolite.rst [new file with mode: 0644]
contrib/hooks/multimail/git_multimail.py
contrib/hooks/multimail/migrate-mailhook-config
contrib/hooks/multimail/post-receive.example
contrib/rerere-train.sh
contrib/subtree/git-subtree.sh
contrib/subtree/t/Makefile
contrib/subtree/t/t7900-subtree.sh
contrib/subtree/todo
convert.c
credential-cache--daemon.c
credential-cache.c
credential-store.c
daemon.c
date.c
decorate.c
diff-lib.c
diff-no-index.c
diff.c
dir.c
entry.c
environment.c
fast-import.c
fetch-pack.c
fsck.c
git-bisect.sh
git-compat-util.h
git-difftool.perl
git-filter-branch.sh
git-merge-one-file.sh
git-p4.py
git-quiltimport.sh
git-rebase--interactive.sh
git-rebase.sh
git-send-email.perl
git-stash.sh
git-submodule.sh
git.c
gitk-git/gitk
gitk-git/po/bg.po
gitk-git/po/ca.po
gitk-git/po/de.po
gitk-git/po/es.po
gitk-git/po/fr.po
gitk-git/po/hu.po
gitk-git/po/it.po
gitk-git/po/ja.po
gitk-git/po/pt_br.po
gitk-git/po/ru.po
gitk-git/po/sv.po
gitk-git/po/vi.po
grep.c
hex.c
http-backend.c
http-push.c
http-walker.c
http.c
http.h
imap-send.c
line-log.c
list-objects.c
ll-merge.c
log-tree.c
mailinfo.c [new file with mode: 0644]
mailinfo.h [new file with mode: 0644]
mailmap.c
merge-blobs.c
merge-recursive.c
merge.c
name-hash.c
notes-merge.c
notes.c
object.c
object.h
pack-bitmap-write.c
pack-bitmap.c
pack-check.c
pack-revindex.c
parse-options-cb.c
parse-options.c
parse-options.h
patch-ids.c
path.c
perl/Git/SVN.pm
pkt-line.c
ppc/sha1.h
pretty.c
progress.c
read-cache.c
ref-filter.c
ref-filter.h
reflog-walk.c
refs.c
refs.h
refs/files-backend.c [new file with mode: 0644]
refs/refs-internal.h [new file with mode: 0644]
remote-curl.c
remote.c
remote.h
rerere.c
rerere.h
revision.c
run-command.c
run-command.h
send-pack.c
sequencer.c
server-info.c
setup.c
sha1_file.c
sha1_name.c
shallow.c
show-index.c
sideband.c
strbuf.c
strbuf.h
submodule-config.c
submodule.c
t/README
t/annotate-tests.sh
t/lib-git-p4.sh
t/perf/p7000-filter-branch.sh [new file with mode: 0755]
t/t0001-init.sh
t/t0002-gitfile.sh
t/t0027-auto-crlf.sh
t/t0060-path-utils.sh
t/t1302-repo-version.sh
t/t1400-update-ref.sh
t/t1401-symbolic-ref.sh
t/t1430-bad-ref-name.sh
t/t1450-fsck.sh
t/t2025-worktree-add.sh
t/t2027-worktree-list.sh [new file with mode: 0755]
t/t2200-add-update.sh
t/t2202-add-addremove.sh
t/t3001-ls-files-others-exclude.sh
t/t3030-merge-recursive.sh
t/t3203-branch-output.sh
t/t3210-pack-refs.sh
t/t3404-rebase-interactive.sh
t/t3420-rebase-autostash.sh
t/t5304-prune.sh
t/t5504-fetch-receive-strict.sh
t/t5505-remote.sh
t/t5509-fetch-push-namespaces.sh
t/t5516-fetch-push.sh
t/t5571-pre-push-hook.sh
t/t5700-clone-reference.sh
t/t5801-remote-helpers.sh
t/t5802-connect-helper.sh
t/t5813-proto-disable-ssh.sh
t/t6030-bisect-porcelain.sh
t/t6031-merge-filemode.sh [new file with mode: 0755]
t/t6031-merge-recursive.sh [deleted file]
t/t6300-for-each-ref.sh
t/t6302-for-each-ref-filter.sh [new file with mode: 0755]
t/t7003-filter-branch.sh
t/t7004-tag.sh
t/t7060-wtstatus.sh
t/t7063-status-untracked-cache.sh
t/t7410-submodule-checkout-to.sh
t/t7600-merge.sh
t/t7610-mergetool.sh
t/t7800-difftool.sh
t/t8009-blame-vs-topicbranches.sh [new file with mode: 0755]
t/t9001-send-email.sh
t/t9300-fast-import.sh
t/t9800-git-p4-basic.sh
t/t9807-git-p4-submit.sh
t/t9811-git-p4-label-import.sh
t/t9815-git-p4-submit-fail.sh
t/t9819-git-p4-case-folding.sh
t/t9822-git-p4-path-encoding.sh [new file with mode: 0755]
t/t9823-git-p4-mock-lfs.sh [new file with mode: 0755]
t/t9824-git-p4-git-lfs.sh [new file with mode: 0755]
t/t9825-git-p4-handle-utf16-without-bom.sh [new file with mode: 0755]
t/t9826-git-p4-keep-empty-commits.sh [new file with mode: 0755]
t/t9903-bash-prompt.sh
t/test-lib-functions.sh
tag.c
test-dump-cache-tree.c
test-match-trees.c
trace.c
transport-helper.c
transport.c
transport.h
tree.c
unpack-trees.c
upload-pack.c
url.c
utf8.c
utf8.h
walker.c
worktree.c [new file with mode: 0644]
worktree.h [new file with mode: 0644]
wrap-for-bin.sh
wrapper.c
wt-status.c

index 4fd81ba..1c2f832 100644 (file)
 /git-status
 /git-stripspace
 /git-submodule
+/git-submodule--helper
 /git-svn
 /git-symbolic-ref
 /git-tag
diff --git a/.travis.yml b/.travis.yml
new file mode 100644 (file)
index 0000000..c3bf9c6
--- /dev/null
@@ -0,0 +1,91 @@
+language: c
+
+os:
+  - linux
+  - osx
+
+compiler:
+  - clang
+  - gcc
+
+addons:
+  apt:
+    packages:
+    - language-pack-is
+
+env:
+  global:
+    - P4_VERSION="15.2"
+    - GIT_LFS_VERSION="1.1.0"
+    - DEFAULT_TEST_TARGET=prove
+    - GIT_PROVE_OPTS="--timer --jobs 3"
+    - GIT_TEST_OPTS="--verbose --tee"
+    - CFLAGS="-g -O2 -Wall -Werror"
+    - GIT_TEST_CLONE_2GB=YesPlease
+    # t9810 occasionally fails on Travis CI OS X
+    # t9816 occasionally fails with "TAP out of sequence errors" on Travis CI OS X
+    - GIT_SKIP_TESTS="t9810 t9816"
+
+before_install:
+  - >
+    case "${TRAVIS_OS_NAME:-linux}" in
+    linux)
+      mkdir --parents custom/p4
+      pushd custom/p4
+        wget --quiet http://filehost.perforce.com/perforce/r$P4_VERSION/bin.linux26x86_64/p4d
+        wget --quiet http://filehost.perforce.com/perforce/r$P4_VERSION/bin.linux26x86_64/p4
+        chmod u+x p4d
+        chmod u+x p4
+        export PATH="$(pwd):$PATH"
+      popd
+      mkdir --parents custom/git-lfs
+      pushd custom/git-lfs
+        wget --quiet https://github.com/github/git-lfs/releases/download/v$GIT_LFS_VERSION/git-lfs-linux-amd64-$GIT_LFS_VERSION.tar.gz
+        tar --extract --gunzip --file "git-lfs-linux-amd64-$GIT_LFS_VERSION.tar.gz"
+        cp git-lfs-$GIT_LFS_VERSION/git-lfs .
+        export PATH="$(pwd):$PATH"
+      popd
+      ;;
+    osx)
+      brew_force_set_latest_binary_hash () {
+        FORMULA=$1
+        SHA=$(brew fetch --force $FORMULA 2>&1 | grep ^SHA256: | cut -d ' ' -f 2)
+        sed -E -i.bak "s/sha256 \"[0-9a-f]{64}\"/sha256 \"$SHA\"/g" \
+          /usr/local/Library/Taps/homebrew/homebrew-binary/$FORMULA.rb
+      }
+      brew update --quiet
+      brew tap homebrew/binary --quiet
+      brew_force_set_latest_binary_hash perforce
+      brew_force_set_latest_binary_hash perforce-server
+      brew install git-lfs perforce-server perforce gettext
+      brew link --force gettext
+      ;;
+    esac;
+    echo "$(tput setaf 6)Perforce Server Version$(tput sgr0)";
+    p4d -V | grep Rev.;
+    echo "$(tput setaf 6)Perforce Client Version$(tput sgr0)";
+    p4 -V | grep Rev.;
+    echo "$(tput setaf 6)Git-LFS Version$(tput sgr0)";
+    git-lfs version;
+
+before_script: make --jobs=2
+
+script: make --quiet test
+
+after_failure:
+  - >
+    : '<-- Click here to see detailed test output!                                                        ';
+    for TEST_EXIT in t/test-results/*.exit;
+    do
+      if [ "$(cat "$TEST_EXIT")" != "0" ];
+      then
+        TEST_OUT="${TEST_EXIT%exit}out";
+        echo "------------------------------------------------------------------------";
+        echo "$(tput setaf 1)${TEST_OUT}...$(tput sgr0)";
+        echo "------------------------------------------------------------------------";
+        cat "${TEST_OUT}";
+      fi;
+    done;
+
+notifications:
+  email: false
index 7655ccc..6eff128 100644 (file)
@@ -84,7 +84,7 @@ Updates since v1.7.6
    logic used by "git diff" to determine the hunk header.
 
  * Invoking the low-level "git http-fetch" without "-a" option (which
-   git itself never did---normal users should not have to worry about
+   git itself never did--normal users should not have to worry about
    this) is now deprecated.
 
  * The "--decorate" option to "git log" and its family learned to
index fc3ea18..986637b 100644 (file)
@@ -1,5 +1,5 @@
 Git v1.8.3.1 Release Notes
-========================
+==========================
 
 Fixes since v1.8.3
 ------------------
index 3aa25a2..96090ef 100644 (file)
@@ -1,5 +1,5 @@
 Git v1.8.4.1 Release Notes
-========================
+==========================
 
 Fixes since v1.8.4
 ------------------
index 9adccb1..bf6fb1a 100644 (file)
@@ -1,5 +1,5 @@
 Git v1.8.4.2 Release Notes
-========================
+==========================
 
 Fixes since v1.8.4.1
 --------------------
index 03f3d17..267a1b3 100644 (file)
@@ -1,5 +1,5 @@
 Git v1.8.4.3 Release Notes
-========================
+==========================
 
 Fixes since v1.8.4.2
 --------------------
index 7bc4c5d..a7c1ce1 100644 (file)
@@ -1,5 +1,5 @@
 Git v1.8.4.4 Release Notes
-========================
+==========================
 
 Fixes since v1.8.4.3
 --------------------
index 752d791..4e4b88a 100644 (file)
@@ -177,7 +177,7 @@ Performance, Internal Implementation, etc.
  * The naming convention of the packfiles has been updated; it used to
    be based on the enumeration of names of the objects that are
    contained in the pack, but now it also depends on how the packed
-   result is represented---packing the same set of objects using
+   result is represented--packing the same set of objects using
    different settings (or delta order) would produce a pack with
    different name.
 
diff --git a/Documentation/RelNotes/2.6.3.txt b/Documentation/RelNotes/2.6.3.txt
new file mode 100644 (file)
index 0000000..fc6fe17
--- /dev/null
@@ -0,0 +1,111 @@
+Git v2.6.3 Release Notes
+========================
+
+Fixes since v2.6.2
+------------------
+
+ * The error message from "git blame --contents --reverse" incorrectly
+   talked about "--contents --children".
+
+ * "git merge-file" tried to signal how many conflicts it found, which
+   obviously would not work well when there are too many of them.
+
+ * The name-hash subsystem that is used to cope with case insensitive
+   filesystems keeps track of directories and their on-filesystem
+   cases for all the paths in the index by holding a pointer to a
+   randomly chosen cache entry that is inside the directory (for its
+   ce->ce_name component).  This pointer was not updated even when the
+   cache entry was removed from the index, leading to use after free.
+   This was fixed by recording the path for each directory instead of
+   borrowing cache entries and restructuring the API somewhat.
+
+ * When the "git am" command was reimplemented in C, "git am -3" had a
+   small regression where it is aborted in its error handling codepath
+   when underlying merge-recursive failed in some ways.
+
+ * The synopsis text and the usage string of subcommands that read
+   list of things from the standard input are often shown as if they
+   only take input from a file on a filesystem, which was misleading.
+
+ * A couple of commands still showed "[options]" in their usage string
+   to note where options should come on their command line, but we
+   spell that "[<options>]" in most places these days.
+
+ * The submodule code has been taught to work better with separate
+   work trees created via "git worktree add".
+
+ * When "git gc --auto" is backgrounded, its diagnosis message is
+   lost.  It now is saved to a file in $GIT_DIR and is shown next time
+   the "gc --auto" is run.
+
+ * Work around "git p4" failing when the P4 depot records the contents
+   in UTF-16 without UTF-16 BOM.
+
+ * Recent update to "rebase -i" that tries to sanity check the edited
+   insn sheet before it uses it has become too picky on Windows where
+   CRLF left by the editor is turned into a trailing CR on the line
+   read via the "read" built-in command.
+
+ * "git clone --dissociate" runs a big "git repack" process at the
+   end, and it helps to close file descriptors that are open on the
+   packs and their idx files before doing so on filesystems that
+   cannot remove a file that is still open.
+
+ * Correct "git p4 --detect-labels" so that it does not fail to create
+   a tag that points at a commit that is also being imported.
+
+ * The internal stripspace() function has been moved to where it
+   logically belongs to, i.e. strbuf API, and the command line parser
+   of "git stripspace" has been updated to use the parse_options API.
+
+ * Prepare for Git on-disk repository representation to undergo
+   backward incompatible changes by introducing a new repository
+   format version "1", with an extension mechanism.
+
+ * "git gc" used to barf when a symbolic ref has gone dangling
+   (e.g. the branch that used to be your upstream's default when you
+   cloned from it is now gone, and you did "fetch --prune").
+
+ * The normalize_ceiling_entry() function does not muck with the end
+   of the path it accepts, and the real world callers do rely on that,
+   but a test insisted that the function drops a trailing slash.
+
+ * "git gc" is safe to run anytime only because it has the built-in
+   grace period to protect young objects.  In order to run with no
+   grace period, the user must make sure that the repository is
+   quiescent.
+
+ * A recent "filter-branch --msg-filter" broke skipping of the commit
+   object header, which is fixed.
+
+ * "git --literal-pathspecs add -u/-A" without any command line
+   argument misbehaved ever since Git 2.0.
+
+ * Merging a branch that removes a path and another that changes the
+   mode bits on the same path should have conflicted at the path, but
+   it didn't and silently favoured the removal.
+
+ * "git imap-send" did not compile well with older version of cURL library.
+
+ * The linkage order of libraries was wrong in places around libcurl.
+
+ * It was not possible to use a repository-lookalike created by "git
+   worktree add" as a local source of "git clone".
+
+ * When "git send-email" wanted to talk over Net::SMTP::SSL,
+   Net::Cmd::datasend() did not like to be fed too many bytes at the
+   same time and failed to send messages.  Send the payload one line
+   at a time to work around the problem.
+
+ * We peek objects from submodule's object store by linking it to the
+   list of alternate object databases, but the code to do so forgot to
+   correctly initialize the list.
+
+ * "git status --branch --short" accessed beyond the constant string
+   "HEAD", which has been corrected.
+
+ * "git daemon" uses "run_command()" without "finish_command()", so it
+   needs to release resources itself, which it forgot to do.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
diff --git a/Documentation/RelNotes/2.6.4.txt b/Documentation/RelNotes/2.6.4.txt
new file mode 100644 (file)
index 0000000..b0256a2
--- /dev/null
@@ -0,0 +1,63 @@
+Git v2.6.4 Release Notes
+========================
+
+Fixes since v2.6.3
+------------------
+
+ * The "configure" script did not test for -lpthread correctly, which
+   upset some linkers.
+
+ * Add support for talking http/https over socks proxy.
+
+ * Portability fix for Windows, which may rewrite $SHELL variable using
+   non-POSIX paths.
+
+ * We now consistently allow all hooks to ignore their standard input,
+   rather than having git complain of SIGPIPE.
+
+ * Fix shell quoting in contrib script.
+
+ * Test portability fix for a topic in v2.6.1.
+
+ * Allow tilde-expansion in some http config variables.
+
+ * Give a useful special case "diff/show --word-diff-regex=." as an
+   example in the documentation.
+
+ * Fix for a corner case in filter-branch.
+
+ * Make git-p4 work on a detached head.
+
+ * Documentation clarification for "check-ignore" without "--verbose".
+
+ * Just like the working tree is cleaned up when the user cancelled
+   submission in P4Submit.applyCommit(), clean up the mess if "p4
+   submit" fails.
+
+ * Having a leftover .idx file without corresponding .pack file in
+   the repository hurts performance; "git gc" learned to prune them.
+
+ * The code to prepare the working tree side of temporary directory
+   for the "dir-diff" feature forgot that symbolic links need not be
+   copied (or symlinked) to the temporary area, as the code already
+   special cases and overwrites them.  Besides, it was wrong to try
+   computing the object name of the target of symbolic link, which may
+   not even exist or may be a directory.
+
+ * There was no way to defeat a configured rebase.autostash variable
+   from the command line, as "git rebase --no-autostash" was missing.
+
+ * Allow "git interpret-trailers" to run outside of a Git repository.
+
+ * Produce correct "dirty" marker for shell prompts, even when we
+   are on an orphan or an unborn branch.
+
+ * Some corner cases have been fixed in string-matching done in "git
+   status".
+
+ * Apple's common crypto implementation of SHA1_Update() does not take
+   more than 4GB at a time, and we now have a compile-time workaround
+   for it.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
diff --git a/Documentation/RelNotes/2.6.5.txt b/Documentation/RelNotes/2.6.5.txt
new file mode 100644 (file)
index 0000000..e1b75fb
--- /dev/null
@@ -0,0 +1,25 @@
+Git v2.6.5 Release Notes
+========================
+
+Fixes since v2.6.4
+------------------
+
+ * Because "test_when_finished" in our test framework queues the
+   clean-up tasks to be done in a shell variable, it should not be
+   used inside a subshell.  Add a mechanism to allow 'bash' to catch
+   such uses, and fix the ones that were found.
+
+ * Update "git subtree" (in contrib/) so that it can take whitespaces
+   in the pathnames, not only in the in-tree pathname but the name of
+   the directory that the repository is in.
+
+ * Cosmetic improvement to lock-file error messages.
+
+ * mark_tree_uninteresting() has code to handle the case where it gets
+   passed a NULL pointer in its 'tree' parameter, but the function had
+   'object = &tree->object' assignment before checking if tree is
+   NULL.  This gives a compiler an excuse to declare that tree will
+   never be NULL and apply a wrong optimization.  Avoid it.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
diff --git a/Documentation/RelNotes/2.7.0.txt b/Documentation/RelNotes/2.7.0.txt
new file mode 100644 (file)
index 0000000..29b4cfe
--- /dev/null
@@ -0,0 +1,367 @@
+Git 2.7 Release Notes
+=====================
+
+Updates since v2.6
+------------------
+
+UI, Workflows & Features
+
+ * "git remote" learned "get-url" subcommand to show the URL for a
+   given remote name used for fetching and pushing.
+
+ * There was no way to defeat a configured rebase.autostash variable
+   from the command line, as "git rebase --no-autostash" was missing.
+
+ * "git log --date=local" used to only show the normal (default)
+   format in the local timezone.  The command learned to take 'local'
+   as an instruction to use the local timezone with other formats,
+
+ * The refs used during a "git bisect" session is now per-worktree so
+   that independent bisect sessions can be done in different worktrees
+   created with "git worktree add".
+
+ * Users who are too busy to type three extra keystrokes to ask for
+   "git stash show -p" can now set stash.showPatch configuration
+   varible to true to always see the actual patch, not just the list
+   of paths affected with feel for the extent of damage via diffstat.
+
+ * "quiltimport" allows to specify the series file by honoring the
+   $QUILT_SERIES environment and also --series command line option.
+
+ * The use of 'good/bad' in "git bisect" made it confusing to use when
+   hunting for a state change that is not a regression (e.g. bugfix).
+   The command learned 'old/new' and then allows the end user to
+   say e.g. "bisect start --term-old=fast --term-new=slow" to find a
+   performance regression.
+
+ * "git interpret-trailers" can now run outside of a Git repository.
+
+ * "git p4" learned to reencode the pathname it uses to communicate
+   with the p4 depot with a new option.
+
+ * Give progress meter to "git filter-branch".
+
+ * Allow a later "!/abc/def" to override an earlier "/abc" that
+   appears in the same .gitignore file to make it easier to express
+   "everything in /abc directory is ignored, except for ...".
+
+ * Teach "git p4" to send large blobs outside the repository by
+   talking to Git LFS.
+
+ * Prepare for Git on-disk repository representation to undergo
+   backward incompatible changes by introducing a new repository
+   format version "1", with an extension mechanism.
+
+ * "git worktree" learned a "list" subcommand.
+
+ * "git clone --dissociate" learned that it can be used even when
+   "--reference" was not used at the same time.
+
+ * "git blame" learnt to take "--first-parent" and "--reverse" at the
+   same time when it makes sense.
+
+ * "git checkout" did not follow the usual "--[no-]progress"
+   convention and implemented only "--quiet" that is essentially
+   a superset of "--no-progress".  Extend the command to support the
+   usual "--[no-]progress".
+
+ * The semantics of tranfer.hideRefs configuration variable have been
+   extended to work better with the ref "namespace" feature that lets
+   you throw unrelated bunches of repositories in a single physical
+   repository and virtually serve them as separate ones.
+
+ * send-email config variables whose values are pathnames now go
+   through the ~username/ expansion.
+
+ * bash completion learnt to TAB-complete recipient addresses given
+   to send-email.
+
+ * The credential-cache daemon can be told to ignore SIGHUP to work
+   around issue when running Git from inside emacs.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * The infrastructure to rewrite "git submodule" in C is being built
+   incrementally.  Let's polish these early parts well enough and make
+   them graduate to 'next' and 'master', so that the more involved
+   follow-up can start cooking on a solid ground.
+
+ * Some features from "git tag -l" and "git branch -l" have been made
+   available to "git for-each-ref" so that eventually the unified
+   implementation can be shared across all three.  The version merged
+   to the 'master' branch earlier had a performance regression in "tag
+   --contains", which has since been corrected.
+
+ * Because "test_when_finished" in our test framework queues the
+   clean-up tasks to be done in a shell variable, it should not be
+   used inside a subshell.  Add a mechanism to allow 'bash' to catch
+   such uses, and fix the ones that were found.
+
+ * The debugging infrastructure for pkt-line based communication has
+   been improved to mark the side-band communication specifically.
+   (merge fd89433 jk/async-pkt-line later to maint).
+
+ * Update "git branch" that list existing branches, using the
+   ref-filter API that is shared with "git tag" and "git
+   for-each-ref".
+
+ * The test for various line-ending conversions has been enhanced.
+
+ * A few test scripts around "git p4" have been improved for
+   portability.
+
+ * Many allocations that is manually counted (correctly) that are
+   followed by strcpy/sprintf have been replaced with a less error
+   prone constructs such as xstrfmt.
+
+ * The internal stripspace() function has been moved to where it
+   logically belongs to, i.e. strbuf API, and the command line parser
+   of "git stripspace" has been updated to use the parse_options API.
+
+ * "git am" used to spawn "git mailinfo" via run_command() API once
+   per each patch, but learned to make a direct call to mailinfo()
+   instead.
+
+ * The implementation of "git mailinfo" was refactored so that a
+   mailinfo() function can be directly called from inside a process.
+
+ * With a "debug" helper, debugging of a single "git" invocation in
+   our test scripts has become a lot easier.
+
+ * The "configure" script did not test for -lpthread correctly, which
+   upset some linkers.
+
+ * Cross completed task off of subtree project's todo list.
+
+ * Test cleanups for the subtree project.
+
+ * Clean up style in an ancient test t9300.
+
+ * Work around some test flakiness with p4d.
+
+ * Fsck did not correctly detect a NUL-truncated header in a tag.
+
+ * Use a safer behavior when we hit errors verifying remote certificates.
+
+ * Speed up filter-branch for cases where we only care about rewriting
+   commits, not tree data.
+
+ * The parse-options API has been updated to make "-h" command line
+   option work more consistently in all commands.
+
+ * "git svn rebase/mkdirs" got optimized by keeping track of empty
+   directories better.
+
+ * Fix some racy client/server tests by treating SIGPIPE the same as a
+   normal non-zero exit.
+
+ * The necessary infrastructure to build topics using the free Travis
+   CI has been added. Developers forking from this topic (and enabling
+   Travis) can do their own builds, and we can turn on auto-builds for
+   git/git (including build-status for pull requests that people
+   open).
+
+
+Also contains various documentation updates and code clean-ups.
+
+
+Fixes since v2.6
+----------------
+
+Unless otherwise noted, all the fixes since v2.6 in the maintenance
+track are contained in this release (see the maintenance releases'
+notes for details).
+
+ * Very small number of options take a parameter that is optional
+   (which is not a great UI element as they can only appear at the end
+   of the command line).  Add notice to documentation of each and
+   every one of them.
+
+ * "git blame --first-parent v1.0..v2.0" was not rejected but did not
+   limit the blame to commits on the first parent chain.
+
+ * "git subtree" (in contrib/) now can take whitespaces in the
+   pathnames, not only in the in-tree pathname but the name of the
+   directory that the repository is in.
+
+ * The ssh transport, just like any other transport over the network,
+   did not clear GIT_* environment variables, but it is possible to
+   use SendEnv and AcceptEnv to leak them to the remote invocation of
+   Git, which is not a good idea at all.  Explicitly clear them just
+   like we do for the local transport.
+
+ * Correct "git p4 --detect-labels" so that it does not fail to create
+   a tag that points at a commit that is also being imported.
+
+ * The Makefile always runs the library archiver with hardcoded "crs"
+   options, which was inconvenient for exotic platforms on which
+   people want to use programs with totally different set of command
+   line options.
+
+ * Customization to change the behaviour with "make -w" and "make -s"
+   in our Makefile was broken when they were used together.
+
+ * Allocation related functions and stdio are unsafe things to call
+   inside a signal handler, and indeed killing the pager can cause
+   glibc to deadlock waiting on allocation mutex as our signal handler
+   tries to free() some data structures in wait_for_pager().  Reduce
+   these unsafe calls.
+
+ * The way how --ref/--notes to specify the notes tree reference are
+   DWIMmed was not clearly documented.
+
+ * "git gc" used to barf when a symbolic ref has gone dangling
+   (e.g. the branch that used to be your upstream's default when you
+   cloned from it is now gone, and you did "fetch --prune").
+
+ * "git clone --dissociate" runs a big "git repack" process at the
+   end, and it helps to close file descriptors that are open on the
+   packs and their idx files before doing so on filesystems that
+   cannot remove a file that is still open.
+
+ * Description of the "log.follow" configuration variable in "git log"
+   documentation is now also copied to "git config" documentation.
+
+ * "git rebase -i" had a minor regression recently, which stopped
+   considering a line that begins with an indented '#' in its insn
+   sheet not a comment. Further, the code was still too picky on
+   Windows where CRLF left by the editor is turned into a trailing CR
+   on the line read via the "read" built-in command of bash.  Both of
+   these issues are now fixed.
+
+ * After "git checkout --detach", "git status" reported a fairly
+   useless "HEAD detached at HEAD", instead of saying at which exact
+   commit.
+
+ * When "git send-email" wanted to talk over Net::SMTP::SSL,
+   Net::Cmd::datasend() did not like to be fed too many bytes at the
+   same time and failed to send messages.  Send the payload one line
+   at a time to work around the problem.
+
+ * When "git am" was rewritten as a built-in, it stopped paying
+   attention to user.signingkey, which was fixed.
+
+ * It was not possible to use a repository-lookalike created by "git
+   worktree add" as a local source of "git clone".
+
+ * On a case insensitive filesystems, setting GIT_WORK_TREE variable
+   using a random cases that does not agree with what the filesystem
+   thinks confused Git that it wasn't inside the working tree.
+
+ * Performance-measurement tests did not work without an installed Git.
+
+ * A test script for the HTTP service had a timing dependent bug,
+   which was fixed.
+
+ * There were some classes of errors that "git fsck" diagnosed to its
+   standard error that did not cause it to exit with non-zero status.
+
+ * Work around "git p4" failing when the P4 depot records the contents
+   in UTF-16 without UTF-16 BOM.
+
+ * When "git gc --auto" is backgrounded, its diagnosis message is
+   lost.  Save it to a file in $GIT_DIR and show it next time the "gc
+   --auto" is run.
+
+ * The submodule code has been taught to work better with separate
+   work trees created via "git worktree add".
+
+ * "git gc" is safe to run anytime only because it has the built-in
+   grace period to protect young objects.  In order to run with no
+   grace period, the user must make sure that the repository is
+   quiescent.
+
+ * A recent "filter-branch --msg-filter" broke skipping of the commit
+   object header, which is fixed.
+
+ * The normalize_ceiling_entry() function does not muck with the end
+   of the path it accepts, and the real world callers do rely on that,
+   but a test insisted that the function drops a trailing slash.
+
+ * A test for interaction between untracked cache and sparse checkout
+   added in Git 2.5 days were flaky.
+
+ * A couple of commands still showed "[options]" in their usage string
+   to note where options should come on their command line, but we
+   spell that "[<options>]" in most places these days.
+
+ * The synopsis text and the usage string of subcommands that read
+   list of things from the standard input are often shown as if they
+   only take input from a file on a filesystem, which was misleading.
+
+ * "git am -3" had a small regression where it is aborted in its error
+   handling codepath when underlying merge-recursive failed in certain
+   ways, as it assumed that the internal call to merge-recursive will
+   never die, which is not the case (yet).
+
+ * The linkage order of libraries was wrong in places around libcurl.
+
+ * The name-hash subsystem that is used to cope with case insensitive
+   filesystems keeps track of directories and their on-filesystem
+   cases for all the paths in the index by holding a pointer to a
+   randomly chosen cache entry that is inside the directory (for its
+   ce->ce_name component).  This pointer was not updated even when the
+   cache entry was removed from the index, leading to use after free.
+   This was fixed by recording the path for each directory instead of
+   borrowing cache entries and restructuring the API somewhat.
+
+ * "git merge-file" tried to signal how many conflicts it found, which
+   obviously would not work well when there are too many of them.
+
+ * The error message from "git blame --contents --reverse" incorrectly
+   talked about "--contents --children".
+
+ * "git imap-send" did not compile well with older version of cURL library.
+
+ * Merging a branch that removes a path and another that changes the
+   mode bits on the same path should have conflicted at the path, but
+   it didn't and silently favoured the removal.
+
+ * "git --literal-pathspecs add -u/-A" without any command line
+   argument misbehaved ever since Git 2.0.
+
+ * "git daemon" uses "run_command()" without "finish_command()", so it
+   needs to release resources itself, which it forgot to do.
+
+ * "git status --branch --short" accessed beyond the constant string
+   "HEAD", which has been corrected.
+
+ * We peek objects from submodule's object store by linking it to the
+   list of alternate object databases, but the code to do so forgot to
+   correctly initialize the list.
+
+ * The code to prepare the working tree side of temporary directory
+   for the "dir-diff" feature forgot that symbolic links need not be
+   copied (or symlinked) to the temporary area, as the code already
+   special cases and overwrites them.  Besides, it was wrong to try
+   computing the object name of the target of symbolic link, which may
+   not even exist or may be a directory.
+
+ * A Range: request can be responded with a full response and when
+   asked properly libcurl knows how to strip the result down to the
+   requested range.  However, we were hand-crafting a range request
+   and it did not kick in.
+
+ * Having a leftover .idx file without corresponding .pack file in
+   the repository hurts performance; "git gc" learned to prune them.
+
+ * Apple's common crypto implementation of SHA1_Update() does not take
+   more than 4GB at a time, and we now have a compile-time workaround
+   for it.
+
+ * Produce correct "dirty" marker for shell prompts, even when we
+   are on an orphan or an unborn branch.
+
+ * A build without NO_IPv6 used to use gethostbyname() when guessing
+   user's hostname, instead of getaddrinfo() that is used in other
+   codepaths in such a build.
+   (merge 00bce77 ep/ident-with-getaddrinfo later to maint).
+
+ * The exit code of git-fsck didnot reflect some types of errors found
+   in packed objects, which has been corrected.
+   (merge 8c24d83 dt/fsck-verify-pack-error later to maint).
+
+ * Code clean-up, minor fixes etc.
+   (merge 15ed07d jc/rerere later to maint).
+   (merge 147875f sb/submodule-config-parse later to maint).
index a09969b..760eab7 100644 (file)
@@ -63,11 +63,10 @@ include::line-range-format.txt[]
        `-` to make the command read from the standard input).
 
 --date <format>::
-       The value is one of the following alternatives:
-       {relative,local,default,iso,rfc,short}. If --date is not
+       Specifies the format used to output dates. If --date is not
        provided, the value of the blame.date config variable is
        used. If the blame.date config variable is also not set, the
-       iso format is used. For more information, See the discussion
+       iso format is used. For supported values, see the discussion
        of the --date option at linkgit:git-log[1].
 
 -M|<num>|::
index fec0dea..2d06b11 100644 (file)
@@ -1122,6 +1122,9 @@ credential.<url>.*::
        example.com. See linkgit:gitcredentials[7] for details on how URLs are
        matched.
 
+credentialCache.ignoreSIGHUP::
+       Tell git-credential-cache--daemon to ignore SIGHUP, instead of quitting.
+
 include::diff-config.txt[]
 
 difftool.<tool>.path::
@@ -1829,9 +1832,7 @@ log.abbrevCommit::
 log.date::
        Set the default date-time mode for the 'log' command.
        Setting a value for log.date is similar to using 'git log''s
-       `--date` option.  Possible values are `relative`, `local`,
-       `default`, `iso`, `rfc`, and `short`; see linkgit:git-log[1]
-       for details.
+       `--date` option.  See linkgit:git-log[1] for details.
 
 log.decorate::
        Print out the ref names of any commits that are shown by the log
@@ -2593,6 +2594,16 @@ status.submoduleSummary::
        submodule summary' command, which shows a similar output but does
        not honor these settings.
 
+stash.showPatch::
+       If this is set to true, the `git stash show` command without an
+       option will show the stash in patch form.  Defaults to false.
+       See description of 'show' command in linkgit:git-stash[1].
+
+stash.showStat::
+       If this is set to true, the `git stash show` command without an
+       option will show diffstat of the stash.  Defaults to true.
+       See description of 'show' command in linkgit:git-stash[1].
+
 submodule.<name>.path::
 submodule.<name>.url::
        The path within this project and URL for a submodule. These
@@ -2665,6 +2676,15 @@ You may also include a `!` in front of the ref name to negate the entry,
 explicitly exposing it, even if an earlier entry marked it as hidden.
 If you have multiple hideRefs values, later entries override earlier ones
 (and entries in more-specific config files override less-specific ones).
++
+If a namespace is in use, the namespace prefix is stripped from each
+reference before it is matched against `transfer.hiderefs` patterns.
+For example, if `refs/heads/master` is specified in `transfer.hideRefs` and
+the current namespace is `foo`, then `refs/namespaces/foo/refs/heads/master`
+is omitted from the advertisements but `refs/heads/master` and
+`refs/namespaces/bar/refs/heads/master` are still advertised as so-called
+"have" lines. In order to match refs before stripping, add a `^` in front of
+the ref name. If you combine `!` and `^`, `!` must be specified first.
 
 transfer.unpackLimit::
        When `fetch.unpackLimit` or `receive.unpackLimit` are
index d56ca90..306b7e3 100644 (file)
@@ -267,6 +267,9 @@ expression to make sure that it matches all non-whitespace characters.
 A match that contains a newline is silently truncated(!) at the
 newline.
 +
+For example, `--word-diff-regex=.` will treat each character as a word
+and, correspondingly, show differences character by character.
++
 The regex can also be set via a diff driver or configuration option, see
 linkgit:gitattributes[1] or linkgit:git-config[1].  Giving it explicitly
 overrides any diff driver or configuration setting.  Diff drivers
index e97f2de..7e79aae 100644 (file)
@@ -16,9 +16,11 @@ DESCRIPTION
 The command takes various subcommands, and different options depending
 on the subcommand:
 
- git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
- git bisect bad [<rev>]
- git bisect good [<rev>...]
+ git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
+                 [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
+ git bisect (bad|new) [<rev>]
+ git bisect (good|old) [<rev>...]
+ git bisect terms [--term-good | --term-bad]
  git bisect skip [(<rev>|<range>)...]
  git bisect reset [<commit>]
  git bisect visualize
@@ -36,6 +38,13 @@ whether the selected commit is "good" or "bad". It continues narrowing
 down the range until it finds the exact commit that introduced the
 change.
 
+In fact, `git bisect` can be used to find the commit that changed
+*any* property of your project; e.g., the commit that fixed a bug, or
+the commit that caused a benchmark's performance to improve. To
+support this more general usage, the terms "old" and "new" can be used
+in place of "good" and "bad", or you can choose your own terms. See
+section "Alternate terms" below for more information.
+
 Basic bisect commands: start, bad, good
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -111,6 +120,79 @@ bad revision, while `git bisect reset HEAD` will leave you on the
 current bisection commit and avoid switching commits at all.
 
 
+Alternate terms
+~~~~~~~~~~~~~~~
+
+Sometimes you are not looking for the commit that introduced a
+breakage, but rather for a commit that caused a change between some
+other "old" state and "new" state. For example, you might be looking
+for the commit that introduced a particular fix. Or you might be
+looking for the first commit in which the source-code filenames were
+finally all converted to your company's naming standard. Or whatever.
+
+In such cases it can be very confusing to use the terms "good" and
+"bad" to refer to "the state before the change" and "the state after
+the change". So instead, you can use the terms "old" and "new",
+respectively, in place of "good" and "bad". (But note that you cannot
+mix "good" and "bad" with "old" and "new" in a single session.)
+
+In this more general usage, you provide `git bisect` with a "new"
+commit has some property and an "old" commit that doesn't have that
+property. Each time `git bisect` checks out a commit, you test if that
+commit has the property. If it does, mark the commit as "new";
+otherwise, mark it as "old". When the bisection is done, `git bisect`
+will report which commit introduced the property.
+
+To use "old" and "new" instead of "good" and bad, you must run `git
+bisect start` without commits as argument and then run the following
+commands to add the commits:
+
+------------------------------------------------
+git bisect old [<rev>]
+------------------------------------------------
+
+to indicate that a commit was before the sought change, or
+
+------------------------------------------------
+git bisect new [<rev>...]
+------------------------------------------------
+
+to indicate that it was after.
+
+To get a reminder of the currently used terms, use
+
+------------------------------------------------
+git bisect terms
+------------------------------------------------
+
+You can get just the old (respectively new) term with `git bisect term
+--term-old` or `git bisect term --term-good`.
+
+If you would like to use your own terms instead of "bad"/"good" or
+"new"/"old", you can choose any names you like (except existing bisect
+subcommands like `reset`, `start`, ...) by starting the
+bisection using
+
+------------------------------------------------
+git bisect start --term-old <term-old> --term-new <term-new>
+------------------------------------------------
+
+For example, if you are looking for a commit that introduced a
+performance regression, you might use
+
+------------------------------------------------
+git bisect start --term-old fast --term-new slow
+------------------------------------------------
+
+Or if you are looking for the commit that fixed a bug, you might use
+
+------------------------------------------------
+git bisect start --term-new fixed --term-old broken
+------------------------------------------------
+
+Then, use `git bisect <term-old>` and `git bisect <term-new>` instead
+of `git bisect good` and `git bisect bad` to mark commits.
+
 Bisect visualize
 ~~~~~~~~~~~~~~~~
 
@@ -174,7 +256,7 @@ Then compile and test the chosen revision, and afterwards mark
 the revision as good or bad in the usual manner.
 
 Bisect skip
-~~~~~~~~~~~~
+~~~~~~~~~~~
 
 Instead of choosing a nearby commit by yourself, you can ask Git to do
 it for you by issuing the command:
@@ -253,7 +335,7 @@ cannot be tested. If the script exits with this code, the current
 revision will be skipped (see `git bisect skip` above). 125 was chosen
 as the highest sensible value to use for this purpose, because 126 and 127
 are used by POSIX shells to signal specific error status (127 is for
-command not found, 126 is for command found but not executable---these
+command not found, 126 is for command found but not executable--these
 details do not matter, as they are normal errors in the script, as far as
 `bisect run` is concerned).
 
@@ -387,6 +469,21 @@ In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit
 has at least one parent whose reachable graph is fully traversable in the sense
 required by 'git pack objects'.
 
+* Look for a fix instead of a regression in the code
++
+------------
+$ git bisect start
+$ git bisect new HEAD    # current commit is marked as new
+$ git bisect old HEAD~10 # the tenth commit from now is marked as old
+------------
++
+or:
+------------
+$ git bisect start --term-old broken --term-new fixed
+$ git bisect fixed
+$ git bisect broken HEAD~10
+------------
+
 Getting help
 ~~~~~~~~~~~~
 
index bbbade4..4a7037f 100644 (file)
@@ -11,7 +11,8 @@ SYNOPSIS
 'git branch' [--color[=<when>] | --no-color] [-r | -a]
        [--list] [-v [--abbrev=<length> | --no-abbrev]]
        [--column[=<options>] | --no-column]
-       [(--merged | --no-merged | --contains) [<commit>]] [<pattern>...]
+       [(--merged | --no-merged | --contains) [<commit>]] [--sort=<key>]
+       [--points-at <object>] [<pattern>...]
 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
 'git branch' --unset-upstream [<branchname>]
@@ -231,6 +232,19 @@ start-point is either a local or remote-tracking branch.
        The new name for an existing branch. The same restrictions as for
        <branchname> apply.
 
+--sort=<key>::
+       Sort based on the key given. Prefix `-` to sort in descending
+       order of the value. You may use the --sort=<key> option
+       multiple times, in which case the last key becomes the primary
+       key. The keys supported are the same as those in `git
+       for-each-ref`. Sort order defaults to sorting based on the
+       full refname (including `refs/...` prefix). This lists
+       detached HEAD (if present) first, then local branches and
+       finally remote-tracking branches.
+
+
+--points-at <object>::
+       Only list branches of the given object.
 
 Examples
 --------
index 3105fc0..eb3d694 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p | <type> | --textconv ) <object>
-'git cat-file' (--batch | --batch-check) [--follow-symlinks] < <list-of-objects>
+'git cat-file' (--batch | --batch-check) [--follow-symlinks]
 
 DESCRIPTION
 -----------
index 00e2aa2..aa3b2bf 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git check-attr' [-a | --all | attr...] [--] pathname...
-'git check-attr' --stdin [-z] [-a | --all | attr...] < <list-of-paths>
+'git check-attr' --stdin [-z] [-a | --all | attr...]
 
 DESCRIPTION
 -----------
@@ -28,7 +28,8 @@ OPTIONS
        Consider `.gitattributes` in the index only, ignoring the working tree.
 
 --stdin::
-       Read file names from stdin instead of from the command-line.
+       Read pathnames from the standard input, one per line,
+       instead of from the command-line.
 
 -z::
        The output format is modified to be machine-parseable.
index e35cd04..e94367a 100644 (file)
@@ -10,16 +10,15 @@ SYNOPSIS
 --------
 [verse]
 'git check-ignore' [options] pathname...
-'git check-ignore' [options] --stdin < <list-of-paths>
+'git check-ignore' [options] --stdin
 
 DESCRIPTION
 -----------
 
 For each pathname given via the command-line or from a file via
-`--stdin`, show the pattern from .gitignore (or other input files to
-the exclude mechanism) that decides if the pathname is excluded or
-included.  Later patterns within a file take precedence over earlier
-ones.
+`--stdin`, check whether the file is excluded by .gitignore (or other
+input files to the exclude mechanism) and output the path if it is
+excluded.
 
 By default, tracked files are not shown at all since they are not
 subject to exclude rules; but see `--no-index'.
@@ -32,10 +31,12 @@ OPTIONS
 
 -v, --verbose::
        Also output details about the matching pattern (if any)
-       for each given pathname.
+       for each given pathname. For precedence rules within and
+       between exclude sources, see linkgit:gitignore[5].
 
 --stdin::
-       Read file names from stdin instead of from the command-line.
+       Read pathnames from the standard input, one per line,
+       instead of from the command-line.
 
 -z::
        The output format is modified to be machine-parseable (see
index 9044dfa..91a3622 100644 (file)
@@ -60,7 +60,7 @@ Git imposes the following rules on how references are named:
 
 These rules make it easy for shell script based tools to parse
 reference names, pathname expansion by the shell when a reference name is used
-unquoted (by mistake), and also avoids ambiguities in certain
+unquoted (by mistake), and also avoid ambiguities in certain
 reference name expressions (see linkgit:gitrevisions[7]):
 
 . A double-dot `..` is often used as in `ref1..ref2`, and in some
index e269fb1..5e5273e 100644 (file)
@@ -107,6 +107,12 @@ OPTIONS
 --quiet::
        Quiet, suppress feedback messages.
 
+--[no-]progress::
+       Progress status is reported on the standard error stream
+       by default when it is attached to a terminal, unless `--quiet`
+       is specified. This flag enables progress reporting even if not
+       attached to a terminal, regardless of `--quiet`.
+
 -f::
 --force::
        When switching branches, proceed even if the index or the
index f1f2a3f..6bf000d 100644 (file)
@@ -104,8 +104,13 @@ objects from the source repository into a pack in the cloned repository.
 --dissociate::
        Borrow the objects from reference repositories specified
        with the `--reference` options only to reduce network
-       transfer and stop borrowing from them after a clone is made
-       by making necessary local copies of borrowed objects.
+       transfer, and stop borrowing from them after a clone is made
+       by making necessary local copies of borrowed objects.  This
+       option can also be used when cloning locally from a
+       repository that already borrows objects from another
+       repository--the new repository will borrow objects from the
+       same repository, and this option can be used to stop the
+       borrowing.
 
 --quiet::
 -q::
index a0b5457..48c33d7 100644 (file)
@@ -9,7 +9,7 @@ git-commit-tree - Create a new commit object
 SYNOPSIS
 --------
 [verse]
-'git commit-tree' <tree> [(-p <parent>)...] < changelog
+'git commit-tree' <tree> [(-p <parent>)...]
 'git commit-tree' [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]
                  [(-F <file>)...] <tree>
 
index e62d9a0..efe56e0 100644 (file)
@@ -71,7 +71,7 @@ This configuration is used in two ways:
 * When `git fetch` is run without specifying what branches
   and/or tags to fetch on the command line, e.g. `git fetch origin`
   or `git fetch`, `remote.<repository>.fetch` values are used as
-  the refspecs---they specify which refs to fetch and which local refs
+  the refspecs--they specify which refs to fetch and which local refs
   to update.  The example above will fetch
   all branches that exist in the `origin` (i.e. any ref that matches
   the left-hand side of the value, `refs/heads/*`) and update the
index 55a9a4b..6526b17 100644 (file)
@@ -9,7 +9,7 @@ git-fmt-merge-msg - Produce a merge commit message
 SYNOPSIS
 --------
 [verse]
-'git fmt-merge-msg' [-m <message>] [--log[=<n>] | --no-log] <$GIT_DIR/FETCH_HEAD
+'git fmt-merge-msg' [-m <message>] [--log[=<n>] | --no-log]
 'git fmt-merge-msg' [-m <message>] [--log[=<n>] | --no-log] -F <file>
 
 DESCRIPTION
@@ -57,6 +57,18 @@ merge.summary::
        Synonym to `merge.log`; this is deprecated and will be removed in
        the future.
 
+EXAMPLE
+-------
+
+--
+$ git fetch origin master
+$ git fmt-merge-msg --log <$GIT_DIR/FETCH_HEAD
+--
+
+Print a log message describing a merge of the "master" branch from
+the "origin" remote.
+
+
 SEE ALSO
 --------
 linkgit:git-merge[1]
index 7f8d9a5..c6f073c 100644 (file)
@@ -10,6 +10,8 @@ SYNOPSIS
 [verse]
 'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
                   [(--sort=<key>)...] [--format=<format>] [<pattern>...]
+                  [--points-at <object>] [(--merged | --no-merged) [<object>]]
+                  [--contains [<object>]]
 
 DESCRIPTION
 -----------
@@ -62,6 +64,20 @@ OPTIONS
        the specified host language.  This is meant to produce
        a scriptlet that can directly be `eval`ed.
 
+--points-at <object>::
+       Only list refs which points at the given object.
+
+--merged [<object>]::
+       Only list refs whose tips are reachable from the
+       specified commit (HEAD if not specified).
+
+--no-merged [<object>]::
+       Only list refs whose tips are not reachable from the
+       specified commit (HEAD if not specified).
+
+--contains [<object>]::
+       Only list tags which contain the specified commit (HEAD if not
+       specified).
 
 FIELD NAMES
 -----------
@@ -111,6 +127,17 @@ color::
        Change output color.  Followed by `:<colorname>`, where names
        are described in `color.branch.*`.
 
+align::
+       Left-, middle-, or right-align the content between
+       %(align:...) and %(end). The "align:" is followed by `<width>`
+       and `<position>` in any order separated by a comma, where the
+       `<position>` is either left, right or middle, default being
+       left and `<width>` is the total length of the content with
+       alignment. If the contents length is more than the width then
+       no alignment is performed. If used with '--quote' everything
+       in between %(align:...) and %(end) is quoted, but if nested
+       then only the topmost level performs quoting.
+
 In addition to the above, for commit and tag objects, the header
 field names (`tree`, `parent`, `object`, `type`, and `tag`) can
 be used to specify the value in the header field.
@@ -123,20 +150,23 @@ The complete message in a commit and tag object is `contents`.
 Its first line is `contents:subject`, where subject is the concatenation
 of all lines of the commit message up to the first blank line.  The next
 line is 'contents:body', where body is all of the lines after the first
-blank line.  Finally, the optional GPG signature is `contents:signature`.
+blank line.  The optional GPG signature is `contents:signature`.  The
+first `N` lines of the message is obtained using `contents:lines=N`.
 
 For sorting purposes, fields with numeric values sort in numeric
 order (`objectsize`, `authordate`, `committerdate`, `taggerdate`).
 All other fields are used to sort in their byte-value order.
 
+There is also an option to sort by versions, this can be done by using
+the fieldname `version:refname` or its alias `v:refname`.
+
 In any case, a field name that refers to a field inapplicable to
 the object referred by the ref does not cause an error.  It
 returns an empty string instead.
 
 As a special case for the date-type fields, you may specify a format for
-the date by adding one of `:default`, `:relative`, `:short`, `:local`,
-`:iso8601`, `:rfc2822` or `:raw` to the end of the fieldname; e.g.
-`%(taggerdate:relative)`.
+the date by adding `:` followed by date format name (see the
+values the `--date` option to linkgit::git-rev-list[1] takes).
 
 
 EXAMPLES
index 1e2a20d..ac44d85 100644 (file)
@@ -9,17 +9,19 @@ git-get-tar-commit-id - Extract commit ID from an archive created using git-arch
 SYNOPSIS
 --------
 [verse]
-'git get-tar-commit-id' < <tarfile>
+'git get-tar-commit-id'
 
 
 DESCRIPTION
 -----------
-Acts as a filter, extracting the commit ID stored in archives created by
-'git archive'.  It reads only the first 1024 bytes of input, thus its
-runtime is not influenced by the size of <tarfile> very much.
+
+Read a tar archive created by 'git archive' from the standard input
+and extract the commit ID stored in it.  It reads only the first
+1024 bytes of input, thus its runtime is not influenced by the size
+of the tar archive very much.
 
 If no commit ID is found, 'git get-tar-commit-id' quietly exists with a
-return code of 1.  This can happen if <tarfile> had not been created
+return code of 1.  This can happen if the archive had not been created
 using 'git archive' or if the first parameter of 'git archive' had been
 a tree ID instead of a commit ID or tag.
 
index 0c75f3b..814e744 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git hash-object' [-t <type>] [-w] [--path=<file>|--no-filters] [--stdin [--literally]] [--] <file>...
-'git hash-object' [-t <type>] [-w] --stdin-paths [--no-filters] < <list-of-paths>
+'git hash-object' [-t <type>] [-w] --stdin-paths [--no-filters]
 
 DESCRIPTION
 -----------
@@ -35,7 +35,8 @@ OPTIONS
        Read the object from standard input instead of from a file.
 
 --stdin-paths::
-       Read file names from stdin instead of from the command-line.
+       Read file names from the standard input, one per line, instead
+       of from the command-line.
 
 --path::
        Hash object as it were located at the given path. The location of
index d2fc12e..f856032 100644 (file)
@@ -41,7 +41,8 @@ lines from `<other-file>`, or lines from both respectively.  The length of the
 conflict markers can be given with the `--marker-size` option.
 
 The exit value of this program is negative on error, and the number of
-conflicts otherwise. If the merge was clean, the exit value is 0.
+conflicts otherwise (truncated to 127 if there are more than that many
+conflicts). If the merge was clean, the exit value is 0.
 
 'git merge-file' is designed to be a minimal clone of RCS 'merge'; that is, it
 implements all of RCS 'merge''s functionality which is needed by
index 3ca158b..fa6a756 100644 (file)
@@ -9,7 +9,7 @@ git-mktag - Creates a tag object
 SYNOPSIS
 --------
 [verse]
-'git mktag' < signature_file
+'git mktag'
 
 DESCRIPTION
 -----------
@@ -20,7 +20,8 @@ The output is the new tag's <object> identifier.
 
 Tag Format
 ----------
-A tag signature file has a very simple fixed format: four lines of
+A tag signature file, to be fed to this command's standard input,
+has a very simple fixed format: four lines of
 
   object <sha1>
   type <typename>
index 82aa5d6..738cfde 100644 (file)
@@ -510,6 +510,49 @@ git-p4.useClientSpec::
        option '--use-client-spec'.  See the "CLIENT SPEC" section above.
        This variable is a boolean, not the name of a p4 client.
 
+git-p4.pathEncoding::
+       Perforce keeps the encoding of a path as given by the originating OS.
+       Git expects paths encoded as UTF-8. Use this config to tell git-p4
+       what encoding Perforce had used for the paths. This encoding is used
+       to transcode the paths to UTF-8. As an example, Perforce on Windows
+       often uses “cp1252” to encode path names.
+
+git-p4.largeFileSystem::
+       Specify the system that is used for large (binary) files. Please note
+       that large file systems do not support the 'git p4 submit' command.
+       Only Git LFS [1] is implemented right now. Download
+       and install the Git LFS command line extension to use this option
+       and configure it like this:
++
+-------------
+git config       git-p4.largeFileSystem GitLFS
+-------------
++
+       [1] https://git-lfs.github.com/
+
+git-p4.largeFileExtensions::
+       All files matching a file extension in the list will be processed
+       by the large file system. Do not prefix the extensions with '.'.
+
+git-p4.largeFileThreshold::
+       All files with an uncompressed size exceeding the threshold will be
+       processed by the large file system. By default the threshold is
+       defined in bytes. Add the suffix k, m, or g to change the unit.
+
+git-p4.largeFileCompressedThreshold::
+       All files with a compressed size exceeding the threshold will be
+       processed by the large file system. This option might slow down
+       your clone/sync process. By default the threshold is defined in
+       bytes. Add the suffix k, m, or g to change the unit.
+
+git-p4.largeFilePush::
+       Boolean variable which defines if large files are automatically
+       pushed to a server.
+
+git-p4.keepEmptyCommits::
+       A changelist that contains only excluded files will be imported
+       as an empty commit if this boolean option is set to true.
+
 Submit variables
 ~~~~~~~~~~~~~~~~
 git-p4.detectRenames::
index 31efc58..cf71fba 100644 (file)
@@ -8,10 +8,12 @@ git-patch-id - Compute unique ID for a patch
 SYNOPSIS
 --------
 [verse]
-'git patch-id' [--stable | --unstable] < <patch>
+'git patch-id' [--stable | --unstable]
 
 DESCRIPTION
 -----------
+Read a patch from the standard input and compute the patch ID for it.
+
 A "patch ID" is nothing but a sum of SHA-1 of the file diffs associated with a
 patch, with whitespace and line numbers ignored.  As such, it's "reasonably
 stable", but at the same time also reasonably unique, i.e., two patches that
index 1495e34..85a4d7d 100644 (file)
@@ -62,7 +62,7 @@ be named.
 If `git push [<repository>]` without any `<refspec>` argument is set to
 update some ref at the destination with `<src>` with
 `remote.<repository>.push` configuration variable, `:<dst>` part can
-be omitted---such a push will update a ref that `<src>` normally updates
+be omitted--such a push will update a ref that `<src>` normally updates
 without any `<refspec>` on the command line.  Otherwise, missing
 `:<dst>` means to update the same ref as the `<src>`.
 +
index d64388c..ff633b0 100644 (file)
@@ -10,6 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git quiltimport' [--dry-run | -n] [--author <author>] [--patches <dir>]
+               [--series <file>]
 
 
 DESCRIPTION
@@ -42,13 +43,19 @@ OPTIONS
        information can be found in the patch description.
 
 --patches <dir>::
-       The directory to find the quilt patches and the
-       quilt series file.
+       The directory to find the quilt patches.
 +
 The default for the patch directory is patches
 or the value of the $QUILT_PATCHES environment
 variable.
 
+--series <file>::
+       The quilt series file.
++
+The default for the series file is <patches>/series
+or the value of the $QUILT_SERIES environment
+variable.
+
 GIT
 ---
 Part of the linkgit:git[1] suite
index bccfdf7..6cca8bb 100644 (file)
@@ -434,7 +434,8 @@ If the '--autosquash' option is enabled by default using the
 configuration variable `rebase.autoSquash`, this option can be
 used to override and disable this setting.
 
---[no-]autostash::
+--autostash::
+--no-autostash::
        Automatically create a temporary stash before the operation
        begins, and apply it after the operation ends.  This means
        that you can run rebase on a dirty worktree.  However, use
index 4c6d6de..1d7ecea 100644 (file)
@@ -1,5 +1,5 @@
 git-remote(1)
-============
+=============
 
 NAME
 ----
@@ -15,6 +15,7 @@ SYNOPSIS
 'git remote remove' <name>
 'git remote set-head' <name> (-a | --auto | -d | --delete | <branch>)
 'git remote set-branches' [--add] <name> <branch>...
+'git remote get-url' [--push] [--all] <name>
 'git remote set-url' [--push] <name> <newurl> [<oldurl>]
 'git remote set-url --add' [--push] <name> <newurl>
 'git remote set-url --delete' [--push] <name> <url>
@@ -131,6 +132,15 @@ The named branches will be interpreted as if specified with the
 With `--add`, instead of replacing the list of currently tracked
 branches, adds to that list.
 
+'get-url'::
+
+Retrieves the URLs for a remote. Configurations for `insteadOf` and
+`pushInsteadOf` are expanded here. By default, only the first URL is listed.
++
+With '--push', push URLs are queried rather than fetch URLs.
++
+With '--all', all URLs for the remote will be listed.
+
 'set-url'::
 
 Changes URLs for the remote. Sets first URL for remote <name> that matches
index 7b49c85..ef22f17 100644 (file)
@@ -45,7 +45,7 @@ SYNOPSIS
             [ --regexp-ignore-case | -i ]
             [ --extended-regexp | -E ]
             [ --fixed-strings | -F ]
-            [ --date=(local|relative|default|iso|iso-strict|rfc|short) ]
+            [ --date=<format>]
             [ [ --objects | --objects-edge | --objects-edge-aggressive ]
               [ --unpacked ] ]
             [ --pretty | --header ]
index b9134d2..771a7b5 100644 (file)
@@ -10,6 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git send-email' [options] <file|directory|rev-list options>...
+'git send-email' --dump-aliases
 
 
 DESCRIPTION
@@ -387,6 +388,16 @@ default to '--validate'.
        Send emails even if safety checks would prevent it.
 
 
+Information
+~~~~~~~~~~~
+
+--dump-aliases::
+       Instead of the normal operation, dump the shorthand alias names from
+       the configured alias file(s), one per line in alphabetical order. Note,
+       this only includes the alias name and not its expanded email addresses.
+       See 'sendemail.aliasesfile' for more information about aliases.
+
+
 CONFIGURATION
 -------------
 
index fbdc8ad..a8a9509 100644 (file)
@@ -9,13 +9,14 @@ git-show-index - Show packed archive index
 SYNOPSIS
 --------
 [verse]
-'git show-index' < idx-file
+'git show-index'
 
 
 DESCRIPTION
 -----------
-Reads given idx file for packed Git archive created with
-'git pack-objects' command, and dumps its contents.
+Read the idx file for a Git packfile created with
+'git pack-objects' command from the standard input, and
+dump its contents.
 
 The information it outputs is subset of what you can get from
 'git verify-pack -v'; this command only shows the packfile
index 2a6f89b..3a32451 100644 (file)
@@ -11,7 +11,7 @@ SYNOPSIS
 'git show-ref' [-q|--quiet] [--verify] [--head] [-d|--dereference]
             [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags]
             [--heads] [--] [<pattern>...]
-'git show-ref' --exclude-existing[=<pattern>] < ref-list
+'git show-ref' --exclude-existing[=<pattern>]
 
 DESCRIPTION
 -----------
@@ -23,8 +23,9 @@ particular ref exists.
 
 By default, shows the tags, heads, and remote refs.
 
-The --exclude-existing form is a filter that does the inverse, it shows the
-refs from stdin that don't exist in the local repository.
+The --exclude-existing form is a filter that does the inverse. It reads
+refs from stdin, one ref per line, and shows those that don't exist in
+the local repository.
 
 Use of this utility is encouraged in favor of directly accessing files under
 the `.git` directory.
index 375213f..92df596 100644 (file)
@@ -95,6 +95,8 @@ show [<stash>]::
        shows the latest one. By default, the command shows the diffstat, but
        it will accept any format known to 'git diff' (e.g., `git stash show
        -p stash@{1}` to view the second most recent stash in patch form).
+       You can use stash.showStat and/or stash.showPatch config variables
+       to change the default behavior.
 
 pop [--index] [-q|--quiet] [<stash>]::
 
index 60328d5..2438f76 100644 (file)
@@ -9,14 +9,15 @@ git-stripspace - Remove unnecessary whitespace
 SYNOPSIS
 --------
 [verse]
-'git stripspace' [-s | --strip-comments] < input
-'git stripspace' [-c | --comment-lines] < input
+'git stripspace' [-s | --strip-comments]
+'git stripspace' [-c | --comment-lines]
 
 DESCRIPTION
 -----------
 
-Clean the input in the manner used by Git for text such as commit
-messages, notes, tags and branch descriptions.
+Read text, such as commit messages, notes, tags and branch
+descriptions, from the standard input and clean it in the manner
+used by Git.
 
 With no arguments, this will:
 
index f17687e..1572f05 100644 (file)
@@ -237,6 +237,9 @@ sync::
 +
 "git submodule sync" synchronizes all submodules while
 "git submodule sync \-- A" synchronizes submodule "A" only.
++
+If `--recursive` is specified, this command will recurse into the
+registered submodules, and sync any nested submodules within.
 
 OPTIONS
 -------
@@ -364,7 +367,7 @@ the submodule itself.
 for linkgit:git-clone[1]'s `--reference` and `--shared` options carefully.
 
 --recursive::
-       This option is only valid for foreach, update and status commands.
+       This option is only valid for foreach, update, status and sync commands.
        Traverse submodules recursively. The operation is performed not
        only in the submodules of the current repo, but also
        in any nested submodules inside those submodules (and so on).
index 08b4dfb..7220e5e 100644 (file)
@@ -13,7 +13,8 @@ SYNOPSIS
        <tagname> [<commit> | <object>]
 'git tag' -d <tagname>...
 'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]
-       [--column[=<options>] | --no-column] [--create-reflog] [<pattern>...]
+       [--column[=<options>] | --no-column] [--create-reflog] [--sort=<key>]
+       [--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]
 'git tag' -v <tagname>...
 
 DESCRIPTION
@@ -94,14 +95,16 @@ OPTIONS
        using fnmatch(3)).  Multiple patterns may be given; if any of
        them matches, the tag is shown.
 
---sort=<type>::
-       Sort in a specific order. Supported type is "refname"
-       (lexicographic order), "version:refname" or "v:refname" (tag
+--sort=<key>::
+       Sort based on the key given.  Prefix `-` to sort in
+       descending order of the value. You may use the --sort=<key> option
+       multiple times, in which case the last key becomes the primary
+       key. Also supports "version:refname" or "v:refname" (tag
        names are treated as versions). The "version:refname" sort
        order can also be affected by the
-       "versionsort.prereleaseSuffix" configuration variable. Prepend
-       "-" to reverse sort order. When this option is not given, the
-       sort order defaults to the value configured for the 'tag.sort'
+       "versionsort.prereleaseSuffix" configuration variable.
+       The keys supported are the same as those in `git for-each-ref`.
+       Sort order defaults to the value configured for the 'tag.sort'
        variable if it exists, or lexicographic order otherwise. See
        linkgit:git-config[1].
 
@@ -156,6 +159,16 @@ This option is only applicable when listing tags without annotation lines.
        The object that the new tag will refer to, usually a commit.
        Defaults to HEAD.
 
+<format>::
+       A string that interpolates `%(fieldname)` from the object
+       pointed at by a ref being shown.  The format is the same as
+       that of linkgit:git-for-each-ref[1].  When unspecified,
+       defaults to `%(refname:short)`.
+
+--[no-]merged [<commit>]::
+       Only list tags whose tips are reachable, or not reachable
+       if '--no-merged' is used, from the specified commit ('HEAD'
+       if not specified).
 
 CONFIGURATION
 -------------
index 07d4329..3e887d1 100644 (file)
@@ -9,7 +9,7 @@ git-unpack-objects - Unpack objects from a packed archive
 SYNOPSIS
 --------
 [verse]
-'git unpack-objects' [-n] [-q] [-r] [--strict] < <packfile>
+'git unpack-objects' [-n] [-q] [-r] [--strict]
 
 
 DESCRIPTION
index 1a296bc..f4e5a85 100644 (file)
@@ -17,6 +17,8 @@ SYNOPSIS
             [--[no-]assume-unchanged]
             [--[no-]skip-worktree]
             [--ignore-submodules]
+            [--[no-]split-index]
+            [--[no-|force-]untracked-cache]
             [--really-refresh] [--unresolve] [--again | -g]
             [--info-only] [--index-info]
             [-z] [--stdin] [--index-version <n>]
index cbef61b..fba0f1c 100644 (file)
@@ -1,5 +1,5 @@
 git-upload-archive(1)
-====================
+=====================
 
 NAME
 ----
index fb68156..5b9ad04 100644 (file)
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git worktree add' [-f] [--detach] [-b <new-branch>] <path> [<branch>]
 'git worktree prune' [-n] [-v] [--expire <expire>]
+'git worktree list' [--porcelain]
 
 DESCRIPTION
 -----------
@@ -59,6 +60,13 @@ prune::
 
 Prune working tree information in $GIT_DIR/worktrees.
 
+list::
+
+List details of each worktree.  The main worktree is listed first, followed by
+each of the linked worktrees.  The output details include if the worktree is
+bare, the revision currently checked out, and the branch currently checked out
+(or 'detached HEAD' if none).
+
 OPTIONS
 -------
 
@@ -86,6 +94,11 @@ OPTIONS
        With `prune`, do not remove anything; just report what it would
        remove.
 
+--porcelain::
+       With `list`, output in an easy-to-parse format for scripts.
+       This format will remain stable across Git versions and regardless of user
+       configuration.  See below for details.
+
 -v::
 --verbose::
        With `prune`, report all removals.
@@ -134,6 +147,41 @@ to `/path/main/.git/worktrees/test-next` then a file named
 `test-next` entry from being pruned.  See
 linkgit:gitrepository-layout[5] for details.
 
+LIST OUTPUT FORMAT
+------------------
+The worktree list command has two output formats.  The default format shows the
+details on a single line with columns.  For example:
+
+------------
+S git worktree list
+/path/to/bare-source            (bare)
+/path/to/linked-worktree        abcd1234 [master]
+/path/to/other-linked-worktree  1234abc  (detached HEAD)
+------------
+
+Porcelain Format
+~~~~~~~~~~~~~~~~
+The porcelain format has a line per attribute.  Attributes are listed with a
+label and value separated by a single space.  Boolean attributes (like 'bare'
+and 'detached') are listed as a label only, and are only present if and only
+if the value is true.  An empty line indicates the end of a worktree.  For
+example:
+
+------------
+S git worktree list --porcelain
+worktree /path/to/bare-source
+bare
+
+worktree /path/to/linked-worktree
+HEAD abcd1234abcd1234abcd1234abcd1234abcd1234
+branch refs/heads/master
+
+worktree /path/to/other-linked-worktree
+HEAD 1234abc1234abc1234abc1234abc1234abc1234a
+detached
+
+------------
+
 EXAMPLES
 --------
 You are in the middle of a refactoring session and your boss comes in and
@@ -167,7 +215,6 @@ performed manually, such as:
 - `remove` to remove a linked working tree and its administrative files (and
   warn if the working tree is dirty)
 - `mv` to move or rename a working tree and update its administrative files
-- `list` to list linked working trees
 - `lock` to prevent automatic pruning of administrative files (for instance,
   for a working tree on a portable device)
 
index 4585103..cbf157b 100644 (file)
@@ -43,9 +43,11 @@ unreleased) version of Git, that is available from the 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.6.2/git.html[documentation for release 2.6.2]
+* link:v2.6.4/git.html[documentation for release 2.6.4]
 
 * release notes for
+  link:RelNotes/2.6.4.txt[2.6.4],
+  link:RelNotes/2.6.3.txt[2.6.3],
   link:RelNotes/2.6.2.txt[2.6.2],
   link:RelNotes/2.6.1.txt[2.6.1],
   link:RelNotes/2.6.0.txt[2.6].
@@ -1055,7 +1057,7 @@ of clones and fetches.
        cloning of shallow repositories.
        See 'GIT_TRACE' for available trace output options.
 
-GIT_LITERAL_PATHSPECS::
+'GIT_LITERAL_PATHSPECS'::
        Setting this variable to `1` will cause Git to treat all
        pathspecs literally, rather than as glob patterns. For example,
        running `GIT_LITERAL_PATHSPECS=1 git log -- '*.c'` will search
@@ -1064,15 +1066,15 @@ GIT_LITERAL_PATHSPECS::
        literal paths to Git (e.g., paths previously given to you by
        `git ls-tree`, `--raw` diff output, etc).
 
-GIT_GLOB_PATHSPECS::
+'GIT_GLOB_PATHSPECS'::
        Setting this variable to `1` will cause Git to treat all
        pathspecs as glob patterns (aka "glob" magic).
 
-GIT_NOGLOB_PATHSPECS::
+'GIT_NOGLOB_PATHSPECS'::
        Setting this variable to `1` will cause Git to treat all
        pathspecs as literal (aka "literal" magic).
 
-GIT_ICASE_PATHSPECS::
+'GIT_ICASE_PATHSPECS'::
        Setting this variable to `1` will cause Git to treat all
        pathspecs as case-insensitive.
 
@@ -1086,7 +1088,7 @@ GIT_ICASE_PATHSPECS::
        variable when it is invoked as the top level command by the
        end user, to be recorded in the body of the reflog.
 
-`GIT_REF_PARANOIA`::
+'GIT_REF_PARANOIA'::
        If set to `1`, include broken or badly named refs when iterating
        over lists of refs. In a normal, non-corrupted repository, this
        does nothing. However, enabling it may help git to detect and
@@ -1097,7 +1099,7 @@ GIT_ICASE_PATHSPECS::
        an operation has touched every ref (e.g., because you are
        cloning a repository to make a backup).
 
-`GIT_ALLOW_PROTOCOL`::
+'GIT_ALLOW_PROTOCOL'::
        If set, provide a colon-separated list of protocols which are
        allowed to be used with fetch/push/clone. This is useful to
        restrict recursive submodule initialization from an untrusted
index 7be6e64..35473ad 100644 (file)
@@ -1,5 +1,5 @@
 giteveryday(7)
-===============
+==============
 
 NAME
 ----
index 473623d..79a1948 100644 (file)
@@ -82,12 +82,12 @@ PATTERN FORMAT
 
  - An optional prefix "`!`" which negates the pattern; any
    matching file excluded by a previous pattern will become
-   included again. It is not possible to re-include a file if a parent
-   directory of that file is excluded. Git doesn't list excluded
-   directories for performance reasons, so any patterns on contained
-   files have no effect, no matter where they are defined.
+   included again.
    Put a backslash ("`\`") in front of the first "`!`" for patterns
    that begin with a literal "`!`", for example, "`\!important!.txt`".
+   It is possible to re-include a file if a parent directory of that
+   file is excluded if certain conditions are met. See section NOTES
+   for detail.
 
  - If the pattern ends with a slash, it is removed for the
    purpose of the following description, but it would only find
@@ -141,6 +141,21 @@ not tracked by Git remain untracked.
 To stop tracking a file that is currently tracked, use
 'git rm --cached'.
 
+To re-include files or directories when their parent directory is
+excluded, the following conditions must be met:
+
+ - The rules to exclude a directory and re-include a subset back must
+   be in the same .gitignore file.
+
+ - The directory part in the re-include rules must be literal (i.e. no
+   wildcards)
+
+ - The rules to exclude the parent directory must not end with a
+   trailing slash.
+
+ - The rules to exclude the parent directory must have at least one
+   slash.
+
 EXAMPLES
 --------
 
index c0ed6d1..e903eb7 100644 (file)
@@ -1,5 +1,5 @@
 gitrevisions(7)
-================
+===============
 
 NAME
 ----
index 8c6478b..e225974 100644 (file)
@@ -413,8 +413,9 @@ exclude;;
 
 [[def_per_worktree_ref]]per-worktree ref::
        Refs that are per-<<def_working_tree,worktree>>, rather than
-       global.  This is presently only <<def_HEAD,HEAD>>, but might
-       later include other unusual refs.
+       global.  This is presently only <<def_HEAD,HEAD>> and any refs
+       that start with `refs/bisect/`, but might later include other
+       unusual refs.
 
 [[def_pseudoref]]pseudoref::
        Pseudorefs are a class of files under `$GIT_DIR` which behave
index f1c5220..4f009d4 100644 (file)
@@ -701,15 +701,19 @@ include::pretty-options.txt[]
 --relative-date::
        Synonym for `--date=relative`.
 
---date=(relative|local|default|iso|iso-strict|rfc|short|raw)::
+--date=<format>::
        Only takes effect for dates shown in human-readable format, such
        as when using `--pretty`. `log.date` config variable sets a default
-       value for the log command's `--date` option.
+       value for the log command's `--date` option. By default, dates
+       are shown in the original time zone (either committer's or
+       author's). If `-local` is appended to the format (e.g.,
+       `iso-local`), the user's local time zone is used instead.
 +
 `--date=relative` shows dates relative to the current time,
-e.g. ``2 hours ago''.
+e.g. ``2 hours ago''. The `-local` option cannot be used with
+`--raw` or `--relative`.
 +
-`--date=local` shows timestamps in user's local time zone.
+`--date=local` is an alias for `--date=default-local`.
 +
 `--date=iso` (or `--date=iso8601`) shows timestamps in a ISO 8601-like format.
 The differences to the strict ISO 8601 format are:
@@ -732,10 +736,15 @@ format, often found in email messages.
 `--date=format:...` feeds the format `...` to your system `strftime`.
 Use `--date=format:%c` to show the date in your system locale's
 preferred format.  See the `strftime` manual for a complete list of
-format placeholders.
+format placeholders. When using `-local`, the correct syntax is
+`--date=format-local:...`.
 +
-`--date=default` shows timestamps in the original time zone
-(either committer's or author's).
+`--date=default` is the default format, and is similar to
+`--date=rfc2822`, with a few exceptions:
+
+       - there is no comma after the day-of-week
+
+       - the time zone is omitted when the local time zone is used
 
 ifdef::git-rev-list[]
 --header::
index a9fdb45..8bf3e37 100644 (file)
@@ -46,6 +46,13 @@ Functions
        The argument dir corresponds the member .dir. The argument env
        corresponds to the member .env.
 
+`child_process_clear`::
+
+       Release the memory associated with the struct child_process.
+       Most users of the run-command API don't need to call this
+       function explicitly because `start_command` invokes it on
+       failure and `finish_command` calls it automatically already.
+
 The functions above do the following:
 
 . If a system call failed, errno is set and -1 is returned. A diagnostic
index 7392ff6..ade0b0c 100644 (file)
@@ -170,7 +170,7 @@ Git index format
 
   The entries are written out in the top-down, depth-first order.  The
   first entry represents the root level of the repository, followed by the
-  first subtree---let's call this A---of the root level (with its name
+  first subtree--let's call this A--of the root level (with its name
   relative to the root level), followed by the first subtree of A (with
   its name relative to A), ...
 
diff --git a/Documentation/technical/repository-version.txt b/Documentation/technical/repository-version.txt
new file mode 100644 (file)
index 0000000..00ad379
--- /dev/null
@@ -0,0 +1,88 @@
+Git Repository Format Versions
+==============================
+
+Every git repository is marked with a numeric version in the
+`core.repositoryformatversion` key of its `config` file. This version
+specifies the rules for operating on the on-disk repository data. An
+implementation of git which does not understand a particular version
+advertised by an on-disk repository MUST NOT operate on that repository;
+doing so risks not only producing wrong results, but actually losing
+data.
+
+Because of this rule, version bumps should be kept to an absolute
+minimum. Instead, we generally prefer these strategies:
+
+  - bumping format version numbers of individual data files (e.g.,
+    index, packfiles, etc). This restricts the incompatibilities only to
+    those files.
+
+  - introducing new data that gracefully degrades when used by older
+    clients (e.g., pack bitmap files are ignored by older clients, which
+    simply do not take advantage of the optimization they provide).
+
+A whole-repository format version bump should only be part of a change
+that cannot be independently versioned. For instance, if one were to
+change the reachability rules for objects, or the rules for locking
+refs, that would require a bump of the repository format version.
+
+Note that this applies only to accessing the repository's disk contents
+directly. An older client which understands only format `0` may still
+connect via `git://` to a repository using format `1`, as long as the
+server process understands format `1`.
+
+The preferred strategy for rolling out a version bump (whether whole
+repository or for a single file) is to teach git to read the new format,
+and allow writing the new format with a config switch or command line
+option (for experimentation or for those who do not care about backwards
+compatibility with older gits). Then after a long period to allow the
+reading capability to become common, we may switch to writing the new
+format by default.
+
+The currently defined format versions are:
+
+Version `0`
+-----------
+
+This is the format defined by the initial version of git, including but
+not limited to the format of the repository directory, the repository
+configuration file, and the object and ref storage. Specifying the
+complete behavior of git is beyond the scope of this document.
+
+Version `1`
+-----------
+
+This format is identical to version `0`, with the following exceptions:
+
+  1. When reading the `core.repositoryformatversion` variable, a git
+     implementation which supports version 1 MUST also read any
+     configuration keys found in the `extensions` section of the
+     configuration file.
+
+  2. If a version-1 repository specifies any `extensions.*` keys that
+     the running git has not implemented, the operation MUST NOT
+     proceed. Similarly, if the value of any known key is not understood
+     by the implementation, the operation MUST NOT proceed.
+
+Note that if no extensions are specified in the config file, then
+`core.repositoryformatversion` SHOULD be set to `0` (setting it to `1`
+provides no benefit, and makes the repository incompatible with older
+implementations of git).
+
+This document will serve as the master list for extensions. Any
+implementation wishing to define a new extension should make a note of
+it here, in order to claim the name.
+
+The defined extensions are:
+
+`noop`
+~~~~~~
+
+This extension does not change git's behavior at all. It is useful only
+for testing format-1 compatibility.
+
+`preciousObjects`
+~~~~~~~~~~~~~~~~~
+
+When the config key `extensions.preciousObjects` is set to `true`,
+objects in the repository MUST NOT be deleted (e.g., by `git-prune` or
+`git repack -d`).
index 282758e..bd184cd 100644 (file)
@@ -36,7 +36,7 @@ The `<pushurl>` is used for pushes only. It is optional and defaults
 to `<url>`.
 
 Named file in `$GIT_DIR/remotes`
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 You can choose to provide the name of a
 file in `$GIT_DIR/remotes`.  The URL
index 1b7987e..1c790ac 100644 (file)
@@ -1431,11 +1431,11 @@ differently.  Normally, a merge results in a merge commit, with two
 parents, one pointing at each of the two lines of development that
 were merged.
 
-However, if the current branch is a descendant of the other--so every
-commit present in the one is already contained in the other--then Git
-just performs a "fast-forward"; the head of the current branch is moved
-forward to point at the head of the merged-in branch, without any new
-commits being created.
+However, if the current branch is an ancestor of the other--so every commit
+present in the current branch is already contained in the other branch--then Git
+just performs a "fast-forward"; the head of the current branch is moved forward
+to point at the head of the merged-in branch, without any new commits being
+created.
 
 [[fixing-mistakes]]
 Fixing mistakes
@@ -1491,7 +1491,7 @@ resolving a merge>>.
 
 [[fixing-a-mistake-by-rewriting-history]]
 Fixing a mistake by rewriting history
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 If the problematic commit is the most recent commit, and you have not
 yet made that commit public, then you may just
index 7876709..29c43c2 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.6.2
+DEF_VER=v2.7.0-rc0
 
 LF='
 '
index 04c2231..fd19b54 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -39,6 +39,9 @@ all::
 # Define CURLDIR=/foo/bar if your curl header and library files are in
 # /foo/bar/include and /foo/bar/lib directories.
 #
+# Define CURL_CONFIG to curl's configuration program that prints information
+# about the library (e.g., its version number).  The default is 'curl-config'.
+#
 # Define NO_EXPAT if you do not have expat installed.  git-http-push is
 # not built, and you cannot push using http:// and https:// transports (dumb).
 #
@@ -74,8 +77,6 @@ all::
 # Define HAVE_PATHS_H if you have paths.h and want to use the default PATH
 # it specifies.
 #
-# Define NO_D_INO_IN_DIRENT if you don't have d_ino in your struct dirent.
-#
 # Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
 # d_type in struct dirent (Cygwin 1.5, fixed in Cygwin 1.7).
 #
@@ -141,6 +142,10 @@ all::
 # Define PPC_SHA1 environment variable when running make to make use of
 # a bundled SHA1 routine optimized for PowerPC.
 #
+# Define SHA1_MAX_BLOCK_SIZE to limit the amount of data that will be hashed
+# in one call to the platform's SHA1_Update(). e.g. APPLE_COMMON_CRYPTO
+# wants 'SHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L' defined.
+#
 # Define NEEDS_CRYPTO_WITH_SSL if you need -lcrypto when using -lssl (Darwin).
 #
 # Define NEEDS_SSL_WITH_CRYPTO if you need -lssl when using -lcrypto (Darwin).
@@ -428,6 +433,7 @@ TCL_PATH = tclsh
 TCLTK_PATH = wish
 XGETTEXT = xgettext
 MSGFMT = msgfmt
+CURL_CONFIG = curl-config
 PTHREAD_LIBS = -lpthread
 PTHREAD_CFLAGS =
 GCOV = gcov
@@ -729,6 +735,7 @@ LIB_OBJS += list-objects.o
 LIB_OBJS += ll-merge.o
 LIB_OBJS += lockfile.o
 LIB_OBJS += log-tree.o
+LIB_OBJS += mailinfo.o
 LIB_OBJS += mailmap.o
 LIB_OBJS += match-trees.o
 LIB_OBJS += merge.o
@@ -765,6 +772,7 @@ LIB_OBJS += reachable.o
 LIB_OBJS += read-cache.o
 LIB_OBJS += reflog-walk.o
 LIB_OBJS += refs.o
+LIB_OBJS += refs/files-backend.o
 LIB_OBJS += ref-filter.o
 LIB_OBJS += remote.o
 LIB_OBJS += replace_object.o
@@ -810,6 +818,7 @@ LIB_OBJS += version.o
 LIB_OBJS += versioncmp.o
 LIB_OBJS += walker.o
 LIB_OBJS += wildmatch.o
+LIB_OBJS += worktree.o
 LIB_OBJS += wrapper.o
 LIB_OBJS += write_or_die.o
 LIB_OBJS += ws.o
@@ -905,6 +914,7 @@ BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
 BUILTIN_OBJS += builtin/show-ref.o
 BUILTIN_OBJS += builtin/stripspace.o
+BUILTIN_OBJS += builtin/submodule--helper.o
 BUILTIN_OBJS += builtin/symbolic-ref.o
 BUILTIN_OBJS += builtin/tag.o
 BUILTIN_OBJS += builtin/unpack-file.o
@@ -1036,7 +1046,7 @@ ifdef HAVE_ALLOCA_H
 endif
 
 IMAP_SEND_BUILDDEPS =
-IMAP_SEND_LDFLAGS = $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)
+IMAP_SEND_LDFLAGS =
 
 ifdef NO_CURL
        BASIC_CFLAGS += -DNO_CURL
@@ -1066,13 +1076,13 @@ else
        REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES)
        PROGRAM_OBJS += http-fetch.o
        PROGRAMS += $(REMOTE_CURL_NAMES)
-       curl_check := $(shell (echo 070908; curl-config --vernum | sed -e '/^70[BC]/s/^/0/') 2>/dev/null | sort -r | sed -ne 2p)
+       curl_check := $(shell (echo 070908; $(CURL_CONFIG) --vernum | sed -e '/^70[BC]/s/^/0/') 2>/dev/null | sort -r | sed -ne 2p)
        ifeq "$(curl_check)" "070908"
                ifndef NO_EXPAT
                        PROGRAM_OBJS += http-push.o
                endif
        endif
-       curl_check := $(shell (echo 072200; curl-config --vernum | sed -e '/^70[BC]/s/^/0/') 2>/dev/null | sort -r | sed -ne 2p)
+       curl_check := $(shell (echo 072200; $(CURL_CONFIG) --vernum | sed -e '/^70[BC]/s/^/0/') 2>/dev/null | sort -r | sed -ne 2p)
        ifeq "$(curl_check)" "072200"
                USE_CURL_FOR_IMAP_SEND = YesPlease
        endif
@@ -1093,6 +1103,7 @@ else
                endif
        endif
 endif
+IMAP_SEND_LDFLAGS += $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)
 
 ifdef ZLIB_PATH
        BASIC_CFLAGS += -I$(ZLIB_PATH)/include
@@ -1163,9 +1174,6 @@ endif
 ifdef NO_D_TYPE_IN_DIRENT
        BASIC_CFLAGS += -DNO_D_TYPE_IN_DIRENT
 endif
-ifdef NO_D_INO_IN_DIRENT
-       BASIC_CFLAGS += -DNO_D_INO_IN_DIRENT
-endif
 ifdef NO_GECOS_IN_PWENT
        BASIC_CFLAGS += -DNO_GECOS_IN_PWENT
 endif
@@ -1335,6 +1343,11 @@ ifdef NO_POSIX_GOODIES
        BASIC_CFLAGS += -DNO_POSIX_GOODIES
 endif
 
+ifdef APPLE_COMMON_CRYPTO
+       # Apple CommonCrypto requires chunking
+       SHA1_MAX_BLOCK_SIZE = 1024L*1024L*1024L
+endif
+
 ifdef BLK_SHA1
        SHA1_HEADER = "block-sha1/sha1.h"
        LIB_OBJS += block-sha1/sha1.o
@@ -1353,6 +1366,10 @@ endif
 endif
 endif
 
+ifdef SHA1_MAX_BLOCK_SIZE
+       LIB_OBJS += compat/sha1-chunked.o
+       BASIC_CFLAGS += -DSHA1_MAX_BLOCK_SIZE="$(SHA1_MAX_BLOCK_SIZE)"
+endif
 ifdef NO_PERL_MAKEMAKER
        export NO_PERL_MAKEMAKER
 endif
@@ -1978,10 +1995,10 @@ git-imap-send$X: imap-send.o $(IMAP_SEND_BUILDDEPS) GIT-LDFLAGS $(GITLIBS)
 
 git-http-fetch$X: http.o http-walker.o http-fetch.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
-               $(LIBS) $(CURL_LIBCURL)
+               $(CURL_LIBCURL) $(LIBS)
 git-http-push$X: http.o http-push.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
-               $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
+               $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS)
 
 git-remote-testsvn$X: remote-testsvn.o GIT-LDFLAGS $(GITLIBS) $(VCSSVN_LIB)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) \
@@ -1995,7 +2012,7 @@ $(REMOTE_CURL_ALIASES): $(REMOTE_CURL_PRIMARY)
 
 $(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
-               $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
+               $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS)
 
 $(LIB_FILE): $(LIB_OBJS)
        $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
@@ -2416,7 +2433,7 @@ profile-clean:
        $(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
 
 clean: profile-clean coverage-clean
-       $(RM) *.o *.res block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o
+       $(RM) *.o *.res refs/*.o block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o
        $(RM) xdiff/*.o vcs-svn/*.o ewah/*.o builtin/*.o
        $(RM) $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
        $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
index 0223580..3ba13ce 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.6.2.txt
\ No newline at end of file
+Documentation/RelNotes/2.7.0.txt
\ No newline at end of file
index 0d1e6bd..501ca97 100644 (file)
@@ -167,21 +167,21 @@ static void prepare_header(struct archiver_args *args,
                           struct ustar_header *header,
                           unsigned int mode, unsigned long size)
 {
-       sprintf(header->mode, "%07o", mode & 07777);
-       sprintf(header->size, "%011lo", S_ISREG(mode) ? size : 0);
-       sprintf(header->mtime, "%011lo", (unsigned long) args->time);
+       xsnprintf(header->mode, sizeof(header->mode), "%07o", mode & 07777);
+       xsnprintf(header->size, sizeof(header->size), "%011lo", S_ISREG(mode) ? size : 0);
+       xsnprintf(header->mtime, sizeof(header->mtime), "%011lo", (unsigned long) args->time);
 
-       sprintf(header->uid, "%07o", 0);
-       sprintf(header->gid, "%07o", 0);
+       xsnprintf(header->uid, sizeof(header->uid), "%07o", 0);
+       xsnprintf(header->gid, sizeof(header->gid), "%07o", 0);
        strlcpy(header->uname, "root", sizeof(header->uname));
        strlcpy(header->gname, "root", sizeof(header->gname));
-       sprintf(header->devmajor, "%07o", 0);
-       sprintf(header->devminor, "%07o", 0);
+       xsnprintf(header->devmajor, sizeof(header->devmajor), "%07o", 0);
+       xsnprintf(header->devminor, sizeof(header->devminor), "%07o", 0);
 
        memcpy(header->magic, "ustar", 6);
        memcpy(header->version, "00", 2);
 
-       sprintf(header->chksum, "%07o", ustar_header_chksum(header));
+       snprintf(header->chksum, sizeof(header->chksum), "%07o", ustar_header_chksum(header));
 }
 
 static int write_extended_header(struct archiver_args *args,
@@ -193,7 +193,7 @@ static int write_extended_header(struct archiver_args *args,
        memset(&header, 0, sizeof(header));
        *header.typeflag = TYPEFLAG_EXT_HEADER;
        mode = 0100666;
-       sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1));
+       xsnprintf(header.name, sizeof(header.name), "%s.paxheader", sha1_to_hex(sha1));
        prepare_header(args, &header, mode, size);
        write_blocked(&header, sizeof(header));
        write_blocked(buffer, size);
@@ -233,10 +233,10 @@ static int write_tar_entry(struct archiver_args *args,
                size_t rest = pathlen - plen - 1;
                if (plen > 0 && rest <= sizeof(header.name)) {
                        memcpy(header.prefix, path, plen);
-                               memcpy(header.name, path + plen + 1, rest);
+                       memcpy(header.name, path + plen + 1, rest);
                } else {
-                       sprintf(header.name, "%s.data",
-                               sha1_to_hex(sha1));
+                       xsnprintf(header.name, sizeof(header.name), "%s.data",
+                                 sha1_to_hex(sha1));
                        strbuf_append_ext_header(&ext_header, "path",
                                                 path, pathlen);
                }
@@ -259,8 +259,8 @@ static int write_tar_entry(struct archiver_args *args,
 
        if (S_ISLNK(mode)) {
                if (size > sizeof(header.linkname)) {
-                       sprintf(header.linkname, "see %s.paxheader",
-                               sha1_to_hex(sha1));
+                       xsnprintf(header.linkname, sizeof(header.linkname),
+                                 "see %s.paxheader", sha1_to_hex(sha1));
                        strbuf_append_ext_header(&ext_header, "linkpath",
                                                 buffer, size);
                } else
@@ -301,7 +301,7 @@ static int write_global_extended_header(struct archiver_args *args)
        memset(&header, 0, sizeof(header));
        *header.typeflag = TYPEFLAG_GLOBAL_HEADER;
        mode = 0100666;
-       strcpy(header.name, "pax_global_header");
+       xsnprintf(header.name, sizeof(header.name), "pax_global_header");
        prepare_header(args, &header, mode, ext_header.len);
        write_blocked(&header, sizeof(header));
        write_blocked(ext_header.buf, ext_header.len);
index 01b0899..0687afa 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -171,13 +171,14 @@ static void queue_directory(const unsigned char *sha1,
                unsigned mode, int stage, struct archiver_context *c)
 {
        struct directory *d;
-       d = xmallocz(sizeof(*d) + base->len + 1 + strlen(filename));
+       size_t len = base->len + 1 + strlen(filename) + 1;
+       d = xmalloc(sizeof(*d) + len);
        d->up      = c->bottom;
        d->baselen = base->len;
        d->mode    = mode;
        d->stage   = stage;
        c->bottom  = d;
-       d->len = sprintf(d->path, "%.*s%s/", (int)base->len, base->buf, filename);
+       d->len = xsnprintf(d->path, len, "%.*s%s/", (int)base->len, base->buf, filename);
        hashcpy(d->oid.hash, sha1);
 }
 
@@ -240,7 +241,7 @@ int write_archive_entries(struct archiver_args *args,
                        len--;
                if (args->verbose)
                        fprintf(stderr, "%.*s\n", (int)len, args->base);
-               err = write_entry(args, args->tree->object.sha1, args->base,
+               err = write_entry(args, args->tree->object.oid.hash, args->base,
                                  len, 040777);
                if (err)
                        return err;
@@ -373,7 +374,7 @@ static void parse_treeish_arg(const char **argv,
 
        commit = lookup_commit_reference_gently(oid.hash, 1);
        if (commit) {
-               commit_sha1 = commit->object.sha1;
+               commit_sha1 = commit->object.oid.hash;
                archive_time = commit->date;
        } else {
                commit_sha1 = NULL;
@@ -389,7 +390,7 @@ static void parse_treeish_arg(const char **argv,
                unsigned int mode;
                int err;
 
-               err = get_tree_entry(tree->object.sha1, prefix,
+               err = get_tree_entry(tree->object.oid.hash, prefix,
                                     tree_oid.hash, &mode);
                if (err || !S_ISDIR(mode))
                        die("current working directory is untracked");
index 041a13d..42aa7aa 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -193,7 +193,7 @@ static int compare_commit_dist(const void *a_, const void *b_)
        b = (struct commit_dist *)b_;
        if (a->distance != b->distance)
                return b->distance - a->distance; /* desc sort */
-       return hashcmp(a->commit->object.sha1, b->commit->object.sha1);
+       return oidcmp(&a->commit->object.oid, &b->commit->object.oid);
 }
 
 static struct commit_list *best_bisection_sorted(struct commit_list *list, int nr)
@@ -500,7 +500,7 @@ struct commit_list *filter_skipped(struct commit_list *list,
                struct commit_list *next = list->next;
                list->next = NULL;
                if (0 <= sha1_array_lookup(&skipped_revs,
-                                          list->item->object.sha1)) {
+                                          list->item->object.oid.hash)) {
                        if (skipped_first && !*skipped_first)
                                *skipped_first = 1;
                        /* Move current to tried list */
@@ -575,7 +575,7 @@ static struct commit_list *skip_away(struct commit_list *list, int count)
 
        for (i = 0; cur; cur = cur->next, i++) {
                if (i == index) {
-                       if (hashcmp(cur->item->object.sha1, current_bad_oid->hash))
+                       if (oidcmp(&cur->item->object.oid, current_bad_oid))
                                return cur;
                        if (previous)
                                return previous;
@@ -730,6 +730,11 @@ static void handle_bad_merge_base(void)
                                "This means the bug has been fixed "
                                "between %s and [%s].\n",
                                bad_hex, bad_hex, good_hex);
+               } else if (!strcmp(term_bad, "new") && !strcmp(term_good, "old")) {
+                       fprintf(stderr, "The merge base %s is new.\n"
+                               "The property has changed "
+                               "between %s and [%s].\n",
+                               bad_hex, bad_hex, good_hex);
                } else {
                        fprintf(stderr, "The merge base %s is %s.\n"
                                "This means the first '%s' commit is "
@@ -762,11 +767,11 @@ static void handle_skipped_merge_base(const unsigned char *mb)
 }
 
 /*
- * "check_merge_bases" checks that merge bases are not "bad".
+ * "check_merge_bases" checks that merge bases are not "bad" (or "new").
  *
- * - If one is "bad", it means the user assumed something wrong
+ * - If one is "bad" (or "new"), it means the user assumed something wrong
  * and we must exit with a non 0 error code.
- * - If one is "good", that's good, we have nothing to do.
+ * - If one is "good" (or "old"), that's good, we have nothing to do.
  * - If one is "skipped", we can't know but we should warn.
  * - If we don't know, we should check it out and ask the user to test.
  */
@@ -779,7 +784,7 @@ static void check_merge_bases(int no_checkout)
        result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1);
 
        for (; result; result = result->next) {
-               const unsigned char *mb = result->item->object.sha1;
+               const unsigned char *mb = result->item->object.oid.hash;
                if (!hashcmp(mb, current_bad_oid->hash)) {
                        handle_bad_merge_base();
                } else if (0 <= sha1_array_lookup(&good_revs, mb)) {
@@ -968,7 +973,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
                exit(4);
        }
 
-       bisect_rev = revs.commits->item->object.sha1;
+       bisect_rev = revs.commits->item->object.oid.hash;
 
        if (!hashcmp(bisect_rev, current_bad_oid->hash)) {
                exit_if_skipped_commits(tried, current_bad_oid);
index b864df6..4df6747 100644 (file)
@@ -16,7 +16,7 @@ void blk_SHA1_Init(blk_SHA_CTX *ctx);
 void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, unsigned long len);
 void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx);
 
-#define git_SHA_CTX    blk_SHA_CTX
-#define git_SHA1_Init  blk_SHA1_Init
-#define git_SHA1_Update        blk_SHA1_Update
-#define git_SHA1_Final blk_SHA1_Final
+#define platform_SHA_CTX       blk_SHA_CTX
+#define platform_SHA1_Init     blk_SHA1_Init
+#define platform_SHA1_Update   blk_SHA1_Update
+#define platform_SHA1_Final    blk_SHA1_Final
index d013374..7ff3f20 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -4,6 +4,7 @@
 #include "refs.h"
 #include "remote.h"
 #include "commit.h"
+#include "worktree.h"
 
 struct tracking {
        struct refspec spec;
@@ -266,7 +267,7 @@ void create_branch(const char *head,
 
        if ((commit = lookup_commit_reference(sha1)) == NULL)
                die(_("Not a valid branch point: '%s'."), start_name);
-       hashcpy(sha1, commit->object.sha1);
+       hashcpy(sha1, commit->object.oid.hash);
 
        if (forcing)
                snprintf(msg, sizeof msg, "branch: Reset to %s",
@@ -311,84 +312,6 @@ void remove_branch_state(void)
        unlink(git_path_squash_msg());
 }
 
-static char *find_linked_symref(const char *symref, const char *branch,
-                               const char *id)
-{
-       struct strbuf sb = STRBUF_INIT;
-       struct strbuf path = STRBUF_INIT;
-       struct strbuf gitdir = STRBUF_INIT;
-       char *existing = NULL;
-
-       /*
-        * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside
-        * $GIT_DIR so resolve_ref_unsafe() won't work (it uses
-        * git_path). Parse the ref ourselves.
-        */
-       if (id)
-               strbuf_addf(&path, "%s/worktrees/%s/%s", get_git_common_dir(), id, symref);
-       else
-               strbuf_addf(&path, "%s/%s", get_git_common_dir(), symref);
-
-       if (!strbuf_readlink(&sb, path.buf, 0)) {
-               if (!starts_with(sb.buf, "refs/") ||
-                   check_refname_format(sb.buf, 0))
-                       goto done;
-       } else if (strbuf_read_file(&sb, path.buf, 0) >= 0 &&
-           starts_with(sb.buf, "ref:")) {
-               strbuf_remove(&sb, 0, strlen("ref:"));
-               strbuf_trim(&sb);
-       } else
-               goto done;
-       if (strcmp(sb.buf, branch))
-               goto done;
-       if (id) {
-               strbuf_reset(&path);
-               strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id);
-               if (strbuf_read_file(&gitdir, path.buf, 0) <= 0)
-                       goto done;
-               strbuf_rtrim(&gitdir);
-       } else
-               strbuf_addstr(&gitdir, get_git_common_dir());
-       strbuf_strip_suffix(&gitdir, ".git");
-
-       existing = strbuf_detach(&gitdir, NULL);
-done:
-       strbuf_release(&path);
-       strbuf_release(&sb);
-       strbuf_release(&gitdir);
-
-       return existing;
-}
-
-char *find_shared_symref(const char *symref, const char *target)
-{
-       struct strbuf path = STRBUF_INIT;
-       DIR *dir;
-       struct dirent *d;
-       char *existing;
-
-       if ((existing = find_linked_symref(symref, target, NULL)))
-               return existing;
-
-       strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
-       dir = opendir(path.buf);
-       strbuf_release(&path);
-       if (!dir)
-               return NULL;
-
-       while ((d = readdir(dir)) != NULL) {
-               if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
-                       continue;
-               existing = find_linked_symref(symref, target, d->d_name);
-               if (existing)
-                       goto done;
-       }
-done:
-       closedir(dir);
-
-       return existing;
-}
-
 void die_if_checked_out(const char *branch)
 {
        char *existing;
index d3446ed..58aa45f 100644 (file)
--- a/branch.h
+++ b/branch.h
@@ -59,12 +59,4 @@ extern int read_branch_desc(struct strbuf *, const char *branch_name);
  */
 extern void die_if_checked_out(const char *branch);
 
-/*
- * Check if a per-worktree symref points to a ref in the main worktree
- * or any linked worktree, and return the path to the exising worktree
- * if it is.  Returns NULL if there is no existing ref.  The caller is
- * responsible for freeing the returned path.
- */
-extern char *find_shared_symref(const char *symref, const char *target);
-
 #endif
index 79aaf0a..6b95006 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -120,6 +120,7 @@ extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
 extern int cmd_status(int argc, const char **argv, const char *prefix);
 extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
+extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
 extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_tag(int argc, const char **argv, const char *prefix);
 extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
index b2a5c57..145f06e 100644 (file)
@@ -336,14 +336,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
        if (!show_only && ignore_missing)
                die(_("Option --ignore-missing can only be used together with --dry-run"));
 
-       if ((0 < addremove_explicit || take_worktree_changes) && !argc) {
-               static const char *whole[2] = { ":/", NULL };
-               argc = 1;
-               argv = whole;
-       }
-
        add_new_files = !take_worktree_changes && !refresh_only;
-       require_pathspec = !take_worktree_changes;
+       require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
 
        hold_locked_index(&lock_file, 1);
 
index 3bd4fd7..9fb42fd 100644 (file)
@@ -27,6 +27,7 @@
 #include "notes-utils.h"
 #include "rerere.h"
 #include "prompt.h"
+#include "mailinfo.h"
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -1258,58 +1259,61 @@ static void am_append_signoff(struct am_state *state)
 static int parse_mail(struct am_state *state, const char *mail)
 {
        FILE *fp;
-       struct child_process cp = CHILD_PROCESS_INIT;
        struct strbuf sb = STRBUF_INIT;
        struct strbuf msg = STRBUF_INIT;
        struct strbuf author_name = STRBUF_INIT;
        struct strbuf author_date = STRBUF_INIT;
        struct strbuf author_email = STRBUF_INIT;
        int ret = 0;
+       struct mailinfo mi;
 
-       cp.git_cmd = 1;
-       cp.in = xopen(mail, O_RDONLY, 0);
-       cp.out = xopen(am_path(state, "info"), O_WRONLY | O_CREAT, 0777);
+       setup_mailinfo(&mi);
 
-       argv_array_push(&cp.args, "mailinfo");
-       argv_array_push(&cp.args, state->utf8 ? "-u" : "-n");
+       if (state->utf8)
+               mi.metainfo_charset = get_commit_output_encoding();
+       else
+               mi.metainfo_charset = NULL;
 
        switch (state->keep) {
        case KEEP_FALSE:
                break;
        case KEEP_TRUE:
-               argv_array_push(&cp.args, "-k");
+               mi.keep_subject = 1;
                break;
        case KEEP_NON_PATCH:
-               argv_array_push(&cp.args, "-b");
+               mi.keep_non_patch_brackets_in_subject = 1;
                break;
        default:
                die("BUG: invalid value for state->keep");
        }
 
        if (state->message_id)
-               argv_array_push(&cp.args, "-m");
+               mi.add_message_id = 1;
 
        switch (state->scissors) {
        case SCISSORS_UNSET:
                break;
        case SCISSORS_FALSE:
-               argv_array_push(&cp.args, "--no-scissors");
+               mi.use_scissors = 0;
                break;
        case SCISSORS_TRUE:
-               argv_array_push(&cp.args, "--scissors");
+               mi.use_scissors = 1;
                break;
        default:
                die("BUG: invalid value for state->scissors");
        }
 
-       argv_array_push(&cp.args, am_path(state, "msg"));
-       argv_array_push(&cp.args, am_path(state, "patch"));
-
-       if (run_command(&cp) < 0)
+       mi.input = fopen(mail, "r");
+       if (!mi.input)
+               die("could not open input");
+       mi.output = fopen(am_path(state, "info"), "w");
+       if (!mi.output)
+               die("could not open output 'info'");
+       if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
                die("could not parse patch");
 
-       close(cp.in);
-       close(cp.out);
+       fclose(mi.input);
+       fclose(mi.output);
 
        /* Extract message and author information */
        fp = xfopen(am_path(state, "info"), "r");
@@ -1341,9 +1345,8 @@ static int parse_mail(struct am_state *state, const char *mail)
        }
 
        strbuf_addstr(&msg, "\n\n");
-       if (strbuf_read_file(&msg, am_path(state, "msg"), 0) < 0)
-               die_errno(_("could not read '%s'"), am_path(state, "msg"));
-       stripspace(&msg, 0);
+       strbuf_addbuf(&msg, &mi.log_message);
+       strbuf_stripspace(&msg, 0);
 
        if (state->signoff)
                am_signoff(&msg);
@@ -1366,6 +1369,7 @@ finish:
        strbuf_release(&author_email);
        strbuf_release(&author_name);
        strbuf_release(&sb);
+       clear_mailinfo(&mi);
        return ret;
 }
 
@@ -1437,7 +1441,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit)
        assert(!state->msg);
        msg = strstr(buffer, "\n\n");
        if (!msg)
-               die(_("unable to parse commit %s"), sha1_to_hex(commit->object.sha1));
+               die(_("unable to parse commit %s"), oid_to_hex(&commit->object.oid));
        state->msg = xstrdup(msg + 2);
        state->msg_len = strlen(state->msg);
 }
@@ -1589,6 +1593,38 @@ static int build_fake_ancestor(const struct am_state *state, const char *index_f
        return 0;
 }
 
+/**
+ * Do the three-way merge using fake ancestor, his tree constructed
+ * from the fake ancestor and the postimage of the patch, and our
+ * state.
+ */
+static int run_fallback_merge_recursive(const struct am_state *state,
+                                       unsigned char *orig_tree,
+                                       unsigned char *our_tree,
+                                       unsigned char *his_tree)
+{
+       struct child_process cp = CHILD_PROCESS_INIT;
+       int status;
+
+       cp.git_cmd = 1;
+
+       argv_array_pushf(&cp.env_array, "GITHEAD_%s=%.*s",
+                        sha1_to_hex(his_tree), linelen(state->msg), state->msg);
+       if (state->quiet)
+               argv_array_push(&cp.env_array, "GIT_MERGE_VERBOSITY=0");
+
+       argv_array_push(&cp.args, "merge-recursive");
+       argv_array_push(&cp.args, sha1_to_hex(orig_tree));
+       argv_array_push(&cp.args, "--");
+       argv_array_push(&cp.args, sha1_to_hex(our_tree));
+       argv_array_push(&cp.args, sha1_to_hex(his_tree));
+
+       status = run_command(&cp) ? (-1) : 0;
+       discard_cache();
+       read_cache();
+       return status;
+}
+
 /**
  * Attempt a threeway merge, using index_path as the temporary index.
  */
@@ -1596,10 +1632,6 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
 {
        unsigned char orig_tree[GIT_SHA1_RAWSZ], his_tree[GIT_SHA1_RAWSZ],
                      our_tree[GIT_SHA1_RAWSZ];
-       const unsigned char *bases[1] = {orig_tree};
-       struct merge_options o;
-       struct commit *result;
-       char *his_tree_name;
 
        if (get_sha1("HEAD", our_tree) < 0)
                hashcpy(our_tree, EMPTY_TREE_SHA1_BIN);
@@ -1651,22 +1683,11 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
         * changes.
         */
 
-       init_merge_options(&o);
-
-       o.branch1 = "HEAD";
-       his_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
-       o.branch2 = his_tree_name;
-
-       if (state->quiet)
-               o.verbosity = 0;
-
-       if (merge_recursive_generic(&o, our_tree, his_tree, 1, bases, &result)) {
+       if (run_fallback_merge_recursive(state, orig_tree, our_tree, his_tree)) {
                rerere(state->allow_rerere_autoupdate);
-               free(his_tree_name);
                return error(_("Failed to merge in the changes."));
        }
 
-       free(his_tree_name);
        return 0;
 }
 
@@ -2229,8 +2250,8 @@ int cmd_am(int argc, const char **argv, const char *prefix)
        int in_progress;
 
        const char * const usage[] = {
-               N_("git am [options] [(<mbox>|<Maildir>)...]"),
-               N_("git am [options] (--continue | --skip | --abort)"),
+               N_("git am [<options>] [(<mbox>|<Maildir>)...]"),
+               N_("git am [<options>] (--continue | --skip | --abort)"),
                NULL
        };
 
index 4aa53f7..deb1364 100644 (file)
@@ -77,8 +77,7 @@ static enum ws_ignore {
 
 
 static const char *patch_input_file;
-static const char *root;
-static int root_len;
+static struct strbuf root = STRBUF_INIT;
 static int read_stdin = 1;
 static int options;
 
@@ -494,8 +493,8 @@ static char *find_name_gnu(const char *line, const char *def, int p_value)
        }
 
        strbuf_remove(&name, 0, cp - name.buf);
-       if (root)
-               strbuf_insert(&name, 0, root, root_len);
+       if (root.len)
+               strbuf_insert(&name, 0, root.buf, root.len);
        return squash_slash(strbuf_detach(&name, NULL));
 }
 
@@ -697,11 +696,8 @@ static char *find_name_common(const char *line, const char *def,
                        return squash_slash(xstrdup(def));
        }
 
-       if (root) {
-               char *ret = xmalloc(root_len + len + 1);
-               strcpy(ret, root);
-               memcpy(ret + root_len, start, len);
-               ret[root_len + len] = '\0';
+       if (root.len) {
+               char *ret = xstrfmt("%s%.*s", root.buf, len, start);
                return squash_slash(ret);
        }
 
@@ -1277,8 +1273,8 @@ static int parse_git_header(const char *line, int len, unsigned int size, struct
         * the default name from the header.
         */
        patch->def_name = git_header_name(line, len);
-       if (patch->def_name && root) {
-               char *s = xstrfmt("%s%s", root, patch->def_name);
+       if (patch->def_name && root.len) {
+               char *s = xstrfmt("%s%s", root.buf, patch->def_name);
                free(patch->def_name);
                patch->def_name = s;
        }
@@ -4501,14 +4497,9 @@ static int option_parse_whitespace(const struct option *opt,
 static int option_parse_directory(const struct option *opt,
                                  const char *arg, int unset)
 {
-       root_len = strlen(arg);
-       if (root_len && arg[root_len - 1] != '/') {
-               char *new_root;
-               root = new_root = xmalloc(root_len + 2);
-               strcpy(new_root, arg);
-               strcpy(new_root + root_len++, "/");
-       } else
-               root = arg;
+       strbuf_reset(&root);
+       strbuf_addstr(&root, arg);
+       strbuf_complete(&root, '/');
        return 0;
 }
 
index 295ce92..1df13cf 100644 (file)
@@ -459,12 +459,13 @@ static void queue_blames(struct scoreboard *sb, struct origin *porigin,
 static struct origin *make_origin(struct commit *commit, const char *path)
 {
        struct origin *o;
-       o = xcalloc(1, sizeof(*o) + strlen(path) + 1);
+       size_t pathlen = strlen(path) + 1;
+       o = xcalloc(1, sizeof(*o) + pathlen);
        o->commit = commit;
        o->refcnt = 1;
        o->next = commit->util;
        commit->util = o;
-       strcpy(o->path, path);
+       memcpy(o->path, path, pathlen); /* includes NUL */
        return o;
 }
 
@@ -505,7 +506,7 @@ static int fill_blob_sha1_and_mode(struct origin *origin)
 {
        if (!is_null_sha1(origin->blob_sha1))
                return 0;
-       if (get_tree_entry(origin->commit->object.sha1,
+       if (get_tree_entry(origin->commit->object.oid.hash,
                           origin->path,
                           origin->blob_sha1, &origin->mode))
                goto error_out;
@@ -556,11 +557,11 @@ static struct origin *find_origin(struct scoreboard *sb,
                       PATHSPEC_LITERAL_PATH, "", paths);
        diff_setup_done(&diff_opts);
 
-       if (is_null_sha1(origin->commit->object.sha1))
-               do_diff_cache(parent->tree->object.sha1, &diff_opts);
+       if (is_null_oid(&origin->commit->object.oid))
+               do_diff_cache(parent->tree->object.oid.hash, &diff_opts);
        else
-               diff_tree_sha1(parent->tree->object.sha1,
-                              origin->commit->tree->object.sha1,
+               diff_tree_sha1(parent->tree->object.oid.hash,
+                              origin->commit->tree->object.oid.hash,
                               "", &diff_opts);
        diffcore_std(&diff_opts);
 
@@ -626,11 +627,11 @@ static struct origin *find_rename(struct scoreboard *sb,
        diff_opts.single_follow = origin->path;
        diff_setup_done(&diff_opts);
 
-       if (is_null_sha1(origin->commit->object.sha1))
-               do_diff_cache(parent->tree->object.sha1, &diff_opts);
+       if (is_null_oid(&origin->commit->object.oid))
+               do_diff_cache(parent->tree->object.oid.hash, &diff_opts);
        else
-               diff_tree_sha1(parent->tree->object.sha1,
-                              origin->commit->tree->object.sha1,
+               diff_tree_sha1(parent->tree->object.oid.hash,
+                              origin->commit->tree->object.oid.hash,
                               "", &diff_opts);
        diffcore_std(&diff_opts);
 
@@ -976,8 +977,8 @@ static void pass_blame_to_parent(struct scoreboard *sb,
 
        if (diff_hunks(&file_p, &file_o, 0, blame_chunk_cb, &d))
                die("unable to generate diff (%s -> %s)",
-                   sha1_to_hex(parent->commit->object.sha1),
-                   sha1_to_hex(target->commit->object.sha1));
+                   oid_to_hex(&parent->commit->object.oid),
+                   oid_to_hex(&target->commit->object.oid));
        /* The rest are the same as the parent */
        blame_chunk(&d.dstq, &d.srcq, INT_MAX, d.offset, INT_MAX, parent);
        *d.dstq = NULL;
@@ -1125,7 +1126,7 @@ static void find_copy_in_blob(struct scoreboard *sb,
        memset(split, 0, sizeof(struct blame_entry [3]));
        if (diff_hunks(file_p, &file_o, 1, handle_split_cb, &d))
                die("unable to generate diff (%s)",
-                   sha1_to_hex(parent->commit->object.sha1));
+                   oid_to_hex(&parent->commit->object.oid));
        /* remainder, if any, all match the preimage */
        handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split);
 }
@@ -1274,11 +1275,11 @@ static void find_copy_in_parent(struct scoreboard *sb,
                && (!porigin || strcmp(target->path, porigin->path))))
                DIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER);
 
-       if (is_null_sha1(target->commit->object.sha1))
-               do_diff_cache(parent->tree->object.sha1, &diff_opts);
+       if (is_null_oid(&target->commit->object.oid))
+               do_diff_cache(parent->tree->object.oid.hash, &diff_opts);
        else
-               diff_tree_sha1(parent->tree->object.sha1,
-                              target->commit->tree->object.sha1,
+               diff_tree_sha1(parent->tree->object.oid.hash,
+                              target->commit->tree->object.oid.hash,
                               "", &diff_opts);
 
        if (!DIFF_OPT_TST(&diff_opts, FIND_COPIES_HARDER))
@@ -1689,7 +1690,7 @@ static void get_commit_info(struct commit *commit,
        if (len)
                strbuf_add(&ret->summary, subject, len);
        else
-               strbuf_addf(&ret->summary, "(%s)", sha1_to_hex(commit->object.sha1));
+               strbuf_addf(&ret->summary, "(%s)", oid_to_hex(&commit->object.oid));
 
        unuse_commit_buffer(commit, message);
 }
@@ -1732,7 +1733,7 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat)
                printf("boundary\n");
        if (suspect->previous) {
                struct origin *prev = suspect->previous;
-               printf("previous %s ", sha1_to_hex(prev->commit->object.sha1));
+               printf("previous %s ", oid_to_hex(&prev->commit->object.oid));
                write_name_quoted(prev->path, stdout, '\n');
        }
 
@@ -1751,7 +1752,7 @@ static void found_guilty_entry(struct blame_entry *ent)
                struct origin *suspect = ent->suspect;
 
                printf("%s %d %d %d\n",
-                      sha1_to_hex(suspect->commit->object.sha1),
+                      oid_to_hex(&suspect->commit->object.oid),
                       ent->s_lno + 1, ent->lno + 1, ent->num_lines);
                emit_one_suspect_detail(suspect, 0);
                write_filename_info(suspect->path);
@@ -1879,9 +1880,9 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent,
        int cnt;
        const char *cp;
        struct origin *suspect = ent->suspect;
-       char hex[41];
+       char hex[GIT_SHA1_HEXSZ + 1];
 
-       strcpy(hex, sha1_to_hex(suspect->commit->object.sha1));
+       sha1_to_hex_r(hex, suspect->commit->object.oid.hash);
        printf("%s %d %d %d\n",
               hex,
               ent->s_lno + 1,
@@ -1917,11 +1918,11 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt)
        const char *cp;
        struct origin *suspect = ent->suspect;
        struct commit_info ci;
-       char hex[41];
+       char hex[GIT_SHA1_HEXSZ + 1];
        int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP);
 
        get_commit_info(suspect->commit, &ci, 1);
-       strcpy(hex, sha1_to_hex(suspect->commit->object.sha1));
+       sha1_to_hex_r(hex, suspect->commit->object.oid.hash);
 
        cp = nth_line(sb, ent->lno);
        for (cnt = 0; cnt < ent->num_lines; cnt++) {
@@ -2076,7 +2077,7 @@ static int read_ancestry(const char *graft_file)
 
 static int update_auto_abbrev(int auto_abbrev, struct origin *suspect)
 {
-       const char *uniq = find_unique_abbrev(suspect->commit->object.sha1,
+       const char *uniq = find_unique_abbrev(suspect->commit->object.oid.hash,
                                              auto_abbrev);
        int len = strlen(uniq);
        if (auto_abbrev < len)
@@ -2152,7 +2153,7 @@ static void sanity_check_refcnt(struct scoreboard *sb)
                if (ent->suspect->refcnt <= 0) {
                        fprintf(stderr, "%s in %s has negative refcnt %d\n",
                                ent->suspect->path,
-                               sha1_to_hex(ent->suspect->commit->object.sha1),
+                               oid_to_hex(&ent->suspect->commit->object.oid),
                                ent->suspect->refcnt);
                        baa = 1;
                }
@@ -2215,7 +2216,7 @@ static void verify_working_tree_path(struct commit *work_tree, const char *path)
        struct commit_list *parents;
 
        for (parents = work_tree->parents; parents; parents = parents->next) {
-               const unsigned char *commit_sha1 = parents->item->object.sha1;
+               const unsigned char *commit_sha1 = parents->item->object.oid.hash;
                unsigned char blob_sha1[20];
                unsigned mode;
 
@@ -2309,7 +2310,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
        strbuf_addstr(&msg, "tree 0000000000000000000000000000000000000000\n");
        for (parent = commit->parents; parent; parent = parent->next)
                strbuf_addf(&msg, "parent %s\n",
-                           sha1_to_hex(parent->item->object.sha1));
+                           oid_to_hex(&parent->item->object.oid));
        strbuf_addf(&msg,
                    "author %s\n"
                    "committer %s\n\n"
@@ -2401,16 +2402,13 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
        return commit;
 }
 
-static char *prepare_final(struct scoreboard *sb)
+static struct commit *find_single_final(struct rev_info *revs,
+                                       const char **name_p)
 {
        int i;
-       const char *final_commit_name = NULL;
-       struct rev_info *revs = sb->revs;
+       struct commit *found = NULL;
+       const char *name = NULL;
 
-       /*
-        * There must be one and only one positive commit in the
-        * revs->pending array.
-        */
        for (i = 0; i < revs->pending.nr; i++) {
                struct object *obj = revs->pending.objects[i].item;
                if (obj->flags & UNINTERESTING)
@@ -2419,14 +2417,22 @@ static char *prepare_final(struct scoreboard *sb)
                        obj = deref_tag(obj, NULL, 0);
                if (obj->type != OBJ_COMMIT)
                        die("Non commit %s?", revs->pending.objects[i].name);
-               if (sb->final)
+               if (found)
                        die("More than one commit to dig from %s and %s?",
-                           revs->pending.objects[i].name,
-                           final_commit_name);
-               sb->final = (struct commit *) obj;
-               final_commit_name = revs->pending.objects[i].name;
+                           revs->pending.objects[i].name, name);
+               found = (struct commit *)obj;
+               name = revs->pending.objects[i].name;
        }
-       return xstrdup_or_null(final_commit_name);
+       if (name_p)
+               *name_p = name;
+       return found;
+}
+
+static char *prepare_final(struct scoreboard *sb)
+{
+       const char *name;
+       sb->final = find_single_final(sb->revs, &name);
+       return xstrdup_or_null(name);
 }
 
 static char *prepare_initial(struct scoreboard *sb)
@@ -2502,6 +2508,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        long dashdash_pos, lno;
        char *final_commit_name = NULL;
        enum object_type type;
+       struct commit *final_commit = NULL;
 
        static struct string_list range_list;
        static int output_option = 0, opt = 0;
@@ -2612,7 +2619,6 @@ parse_done:
                   fewer display columns. */
                blame_date_width = utf8_strwidth(_("4 years, 11 months ago")) + 1; /* add the null */
                break;
-       case DATE_LOCAL:
        case DATE_NORMAL:
                blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700");
                break;
@@ -2691,12 +2697,12 @@ parse_done:
                sb.commits.compare = compare_commits_by_commit_date;
        }
        else if (contents_from)
-               die("--contents and --children do not blend well.");
-       else if (revs.first_parent_only)
-               die("combining --first-parent and --reverse is not supported");
+               die("--contents and --reverse do not blend well.");
        else {
                final_commit_name = prepare_initial(&sb);
                sb.commits.compare = compare_commits_by_reverse_commit_date;
+               if (revs.first_parent_only)
+                       revs.children.name = NULL;
        }
 
        if (!sb.final) {
@@ -2713,6 +2719,12 @@ parse_done:
        else if (contents_from)
                die("Cannot use --contents with final commit object name");
 
+       if (reverse && revs.first_parent_only) {
+               final_commit = find_single_final(sb.revs, NULL);
+               if (!final_commit)
+                       die("--reverse and --first-parent together require specified latest commit");
+       }
+
        /*
         * If we have bottom, this will mark the ancestors of the
         * bottom commits we would reach while traversing as
@@ -2721,7 +2733,26 @@ parse_done:
        if (prepare_revision_walk(&revs))
                die(_("revision walk setup failed"));
 
-       if (is_null_sha1(sb.final->object.sha1)) {
+       if (reverse && revs.first_parent_only) {
+               struct commit *c = final_commit;
+
+               sb.revs->children.name = "children";
+               while (c->parents &&
+                      oidcmp(&c->object.oid, &sb.final->object.oid)) {
+                       struct commit_list *l = xcalloc(1, sizeof(*l));
+
+                       l->item = c;
+                       if (add_decoration(&sb.revs->children,
+                                          &c->parents->item->object, l))
+                               die("BUG: not unique item in first-parent chain");
+                       c = c->parents->item;
+               }
+
+               if (oidcmp(&c->object.oid, &sb.final->object.oid))
+                       die("--reverse --first-parent together require range along first-parent chain");
+       }
+
+       if (is_null_oid(&sb.final->object.oid)) {
                o = sb.final->util;
                sb.final_buf = xmemdupz(o->file.ptr, o->file.size);
                sb.final_buf_size = o->file.size;
index ff05869..3f6c825 100644 (file)
 #include "column.h"
 #include "utf8.h"
 #include "wt-status.h"
+#include "ref-filter.h"
 
 static const char * const builtin_branch_usage[] = {
        N_("git branch [<options>] [-r | -a] [--merged | --no-merged]"),
        N_("git branch [<options>] [-l] [-f] <branch-name> [<start-point>]"),
        N_("git branch [<options>] [-r] (-d | -D) <branch-name>..."),
        N_("git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"),
+       N_("git branch [<options>] [-r | -a] [--points-at]"),
        NULL
 };
 
-#define REF_LOCAL_BRANCH    0x01
-#define REF_REMOTE_BRANCH   0x02
-
 static const char *head;
 static unsigned char head_sha1[20];
 
@@ -52,13 +51,6 @@ enum color_branch {
        BRANCH_COLOR_UPSTREAM = 5
 };
 
-static enum merge_filter {
-       NO_FILTER = 0,
-       SHOW_NOT_MERGED,
-       SHOW_MERGED
-} merge_filter;
-static unsigned char merge_filter_ref[20];
-
 static struct string_list output = STRING_LIST_INIT_DUP;
 static unsigned int colopts;
 
@@ -121,7 +113,7 @@ static int branch_merged(int kind, const char *name,
        void *reference_name_to_free = NULL;
        int merged;
 
-       if (kind == REF_LOCAL_BRANCH) {
+       if (kind == FILTER_REFS_BRANCHES) {
                struct branch *branch = branch_get(name);
                const char *upstream = branch_get_upstream(branch, NULL);
                unsigned char sha1[20];
@@ -199,14 +191,14 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
        struct strbuf bname = STRBUF_INIT;
 
        switch (kinds) {
-       case REF_REMOTE_BRANCH:
+       case FILTER_REFS_REMOTES:
                fmt = "refs/remotes/%s";
                /* For subsequent UI messages */
                remote_branch = 1;
 
                force = 1;
                break;
-       case REF_LOCAL_BRANCH:
+       case FILTER_REFS_BRANCHES:
                fmt = "refs/heads/%s";
                break;
        default:
@@ -223,7 +215,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
                int flags = 0;
 
                strbuf_branchname(&bname, argv[i]);
-               if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {
+               if (kinds == FILTER_REFS_BRANCHES && !strcmp(head, bname.buf)) {
                        error(_("Cannot delete the branch '%s' "
                              "which you are currently on."), bname.buf);
                        ret = 1;
@@ -279,147 +271,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
        return(ret);
 }
 
-struct ref_item {
-       char *name;
-       char *dest;
-       unsigned int kind, width;
-       struct commit *commit;
-       int ignore;
-};
-
-struct ref_list {
-       struct rev_info revs;
-       int index, alloc, maxwidth, verbose, abbrev;
-       struct ref_item *list;
-       struct commit_list *with_commit;
-       int kinds;
-};
-
-static char *resolve_symref(const char *src, const char *prefix)
-{
-       unsigned char sha1[20];
-       int flag;
-       const char *dst;
-
-       dst = resolve_ref_unsafe(src, 0, sha1, &flag);
-       if (!(dst && (flag & REF_ISSYMREF)))
-               return NULL;
-       if (prefix)
-               skip_prefix(dst, prefix, &dst);
-       return xstrdup(dst);
-}
-
-struct append_ref_cb {
-       struct ref_list *ref_list;
-       const char **pattern;
-       int ret;
-};
-
-static int match_patterns(const char **pattern, const char *refname)
-{
-       if (!*pattern)
-               return 1; /* no pattern always matches */
-       while (*pattern) {
-               if (!wildmatch(*pattern, refname, 0, NULL))
-                       return 1;
-               pattern++;
-       }
-       return 0;
-}
-
-static int append_ref(const char *refname, const struct object_id *oid, int flags, void *cb_data)
-{
-       struct append_ref_cb *cb = (struct append_ref_cb *)(cb_data);
-       struct ref_list *ref_list = cb->ref_list;
-       struct ref_item *newitem;
-       struct commit *commit;
-       int kind, i;
-       const char *prefix, *orig_refname = refname;
-
-       static struct {
-               int kind;
-               const char *prefix;
-       } ref_kind[] = {
-               { REF_LOCAL_BRANCH, "refs/heads/" },
-               { REF_REMOTE_BRANCH, "refs/remotes/" },
-       };
-
-       /* Detect kind */
-       for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
-               prefix = ref_kind[i].prefix;
-               if (skip_prefix(refname, prefix, &refname)) {
-                       kind = ref_kind[i].kind;
-                       break;
-               }
-       }
-       if (ARRAY_SIZE(ref_kind) <= i)
-               return 0;
-
-       /* Don't add types the caller doesn't want */
-       if ((kind & ref_list->kinds) == 0)
-               return 0;
-
-       if (!match_patterns(cb->pattern, refname))
-               return 0;
-
-       commit = NULL;
-       if (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) {
-               commit = lookup_commit_reference_gently(oid->hash, 1);
-               if (!commit) {
-                       cb->ret = error(_("branch '%s' does not point at a commit"), refname);
-                       return 0;
-               }
-
-               /* Filter with with_commit if specified */
-               if (!is_descendant_of(commit, ref_list->with_commit))
-                       return 0;
-
-               if (merge_filter != NO_FILTER)
-                       add_pending_object(&ref_list->revs,
-                                          (struct object *)commit, refname);
-       }
-
-       ALLOC_GROW(ref_list->list, ref_list->index + 1, ref_list->alloc);
-
-       /* Record the new item */
-       newitem = &(ref_list->list[ref_list->index++]);
-       newitem->name = xstrdup(refname);
-       newitem->kind = kind;
-       newitem->commit = commit;
-       newitem->width = utf8_strwidth(refname);
-       newitem->dest = resolve_symref(orig_refname, prefix);
-       newitem->ignore = 0;
-       /* adjust for "remotes/" */
-       if (newitem->kind == REF_REMOTE_BRANCH &&
-           ref_list->kinds != REF_REMOTE_BRANCH)
-               newitem->width += 8;
-       if (newitem->width > ref_list->maxwidth)
-               ref_list->maxwidth = newitem->width;
-
-       return 0;
-}
-
-static void free_ref_list(struct ref_list *ref_list)
-{
-       int i;
-
-       for (i = 0; i < ref_list->index; i++) {
-               free(ref_list->list[i].name);
-               free(ref_list->list[i].dest);
-       }
-       free(ref_list->list);
-}
-
-static int ref_cmp(const void *r1, const void *r2)
-{
-       struct ref_item *c1 = (struct ref_item *)(r1);
-       struct ref_item *c2 = (struct ref_item *)(r2);
-
-       if (c1->kind != c2->kind)
-               return c1->kind - c2->kind;
-       return strcmp(c1->name, c2->name);
-}
-
 static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
                int show_upstream_ref)
 {
@@ -482,8 +333,8 @@ static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
        free(ref);
 }
 
-static void add_verbose_info(struct strbuf *out, struct ref_item *item,
-                            int verbose, int abbrev)
+static void add_verbose_info(struct strbuf *out, struct ref_array_item *item,
+                            struct ref_filter *filter, const char *refname)
 {
        struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
        const char *sub = _(" **** invalid ref ****");
@@ -494,32 +345,74 @@ static void add_verbose_info(struct strbuf *out, struct ref_item *item,
                sub = subject.buf;
        }
 
-       if (item->kind == REF_LOCAL_BRANCH)
-               fill_tracking_info(&stat, item->name, verbose > 1);
+       if (item->kind == FILTER_REFS_BRANCHES)
+               fill_tracking_info(&stat, refname, filter->verbose > 1);
 
        strbuf_addf(out, " %s %s%s",
-               find_unique_abbrev(item->commit->object.sha1, abbrev),
+               find_unique_abbrev(item->commit->object.oid.hash, filter->abbrev),
                stat.buf, sub);
        strbuf_release(&stat);
        strbuf_release(&subject);
 }
 
-static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
-                          int abbrev, int current, char *prefix)
+static char *get_head_description(void)
+{
+       struct strbuf desc = STRBUF_INIT;
+       struct wt_status_state state;
+       memset(&state, 0, sizeof(state));
+       wt_status_get_state(&state, 1);
+       if (state.rebase_in_progress ||
+           state.rebase_interactive_in_progress)
+               strbuf_addf(&desc, _("(no branch, rebasing %s)"),
+                           state.branch);
+       else if (state.bisect_in_progress)
+               strbuf_addf(&desc, _("(no branch, bisect started on %s)"),
+                           state.branch);
+       else if (state.detached_from) {
+               /* TRANSLATORS: make sure these match _("HEAD detached at ")
+                  and _("HEAD detached from ") in wt-status.c */
+               if (state.detached_at)
+                       strbuf_addf(&desc, _("(HEAD detached at %s)"),
+                               state.detached_from);
+               else
+                       strbuf_addf(&desc, _("(HEAD detached from %s)"),
+                               state.detached_from);
+       }
+       else
+               strbuf_addstr(&desc, _("(no branch)"));
+       free(state.branch);
+       free(state.onto);
+       free(state.detached_from);
+       return strbuf_detach(&desc, NULL);
+}
+
+static void format_and_print_ref_item(struct ref_array_item *item, int maxwidth,
+                                     struct ref_filter *filter, const char *remote_prefix)
 {
        char c;
+       int current = 0;
        int color;
        struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;
-
-       if (item->ignore)
-               return;
+       const char *prefix = "";
+       const char *desc = item->refname;
+       char *to_free = NULL;
 
        switch (item->kind) {
-       case REF_LOCAL_BRANCH:
-               color = BRANCH_COLOR_LOCAL;
+       case FILTER_REFS_BRANCHES:
+               skip_prefix(desc, "refs/heads/", &desc);
+               if (!filter->detached && !strcmp(desc, head))
+                       current = 1;
+               else
+                       color = BRANCH_COLOR_LOCAL;
                break;
-       case REF_REMOTE_BRANCH:
+       case FILTER_REFS_REMOTES:
+               skip_prefix(desc, "refs/remotes/", &desc);
                color = BRANCH_COLOR_REMOTE;
+               prefix = remote_prefix;
+               break;
+       case FILTER_REFS_DETACHED_HEAD:
+               desc = to_free = get_head_description();
+               current = 1;
                break;
        default:
                color = BRANCH_COLOR_PLAIN;
@@ -532,8 +425,8 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
                color = BRANCH_COLOR_CURRENT;
        }
 
-       strbuf_addf(&name, "%s%s", prefix, item->name);
-       if (verbose) {
+       strbuf_addf(&name, "%s%s", prefix, desc);
+       if (filter->verbose) {
                int utf8_compensation = strlen(name.buf) - utf8_strwidth(name.buf);
                strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color),
                            maxwidth + utf8_compensation, name.buf,
@@ -542,155 +435,82 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
                strbuf_addf(&out, "%c %s%s%s", c, branch_get_color(color),
                            name.buf, branch_get_color(BRANCH_COLOR_RESET));
 
-       if (item->dest)
-               strbuf_addf(&out, " -> %s", item->dest);
-       else if (verbose)
+       if (item->symref) {
+               skip_prefix(item->symref, "refs/remotes/", &desc);
+               strbuf_addf(&out, " -> %s", desc);
+       }
+       else if (filter->verbose)
                /* " f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h" */
-               add_verbose_info(&out, item, verbose, abbrev);
+               add_verbose_info(&out, item, filter, desc);
        if (column_active(colopts)) {
-               assert(!verbose && "--column and --verbose are incompatible");
+               assert(!filter->verbose && "--column and --verbose are incompatible");
                string_list_append(&output, out.buf);
        } else {
                printf("%s\n", out.buf);
        }
        strbuf_release(&name);
        strbuf_release(&out);
+       free(to_free);
 }
 
-static int calc_maxwidth(struct ref_list *refs)
-{
-       int i, w = 0;
-       for (i = 0; i < refs->index; i++) {
-               if (refs->list[i].ignore)
-                       continue;
-               if (refs->list[i].width > w)
-                       w = refs->list[i].width;
-       }
-       return w;
-}
-
-static char *get_head_description(void)
-{
-       struct strbuf desc = STRBUF_INIT;
-       struct wt_status_state state;
-       memset(&state, 0, sizeof(state));
-       wt_status_get_state(&state, 1);
-       if (state.rebase_in_progress ||
-           state.rebase_interactive_in_progress)
-               strbuf_addf(&desc, _("(no branch, rebasing %s)"),
-                           state.branch);
-       else if (state.bisect_in_progress)
-               strbuf_addf(&desc, _("(no branch, bisect started on %s)"),
-                           state.branch);
-       else if (state.detached_from) {
-               /* TRANSLATORS: make sure these match _("HEAD detached at ")
-                  and _("HEAD detached from ") in wt-status.c */
-               if (state.detached_at)
-                       strbuf_addf(&desc, _("(HEAD detached at %s)"),
-                               state.detached_from);
-               else
-                       strbuf_addf(&desc, _("(HEAD detached from %s)"),
-                               state.detached_from);
-       }
-       else
-               strbuf_addstr(&desc, _("(no branch)"));
-       free(state.branch);
-       free(state.onto);
-       free(state.detached_from);
-       return strbuf_detach(&desc, NULL);
-}
-
-static void show_detached(struct ref_list *ref_list)
+static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
 {
-       struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);
-
-       if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) {
-               struct ref_item item;
-               item.name = get_head_description();
-               item.width = utf8_strwidth(item.name);
-               item.kind = REF_LOCAL_BRANCH;
-               item.dest = NULL;
-               item.commit = head_commit;
-               item.ignore = 0;
-               if (item.width > ref_list->maxwidth)
-                       ref_list->maxwidth = item.width;
-               print_ref_item(&item, ref_list->maxwidth, ref_list->verbose, ref_list->abbrev, 1, "");
-               free(item.name);
+       int i, max = 0;
+       for (i = 0; i < refs->nr; i++) {
+               struct ref_array_item *it = refs->items[i];
+               const char *desc = it->refname;
+               int w;
+
+               skip_prefix(it->refname, "refs/heads/", &desc);
+               skip_prefix(it->refname, "refs/remotes/", &desc);
+               w = utf8_strwidth(desc);
+
+               if (it->kind == FILTER_REFS_REMOTES)
+                       w += remote_bonus;
+               if (w > max)
+                       max = w;
        }
+       return max;
 }
 
-static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern)
+static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting)
 {
        int i;
-       struct append_ref_cb cb;
-       struct ref_list ref_list;
-
-       memset(&ref_list, 0, sizeof(ref_list));
-       ref_list.kinds = kinds;
-       ref_list.verbose = verbose;
-       ref_list.abbrev = abbrev;
-       ref_list.with_commit = with_commit;
-       if (merge_filter != NO_FILTER)
-               init_revisions(&ref_list.revs, NULL);
-       cb.ref_list = &ref_list;
-       cb.pattern = pattern;
-       cb.ret = 0;
-       for_each_rawref(append_ref, &cb);
-       if (merge_filter != NO_FILTER) {
-               struct commit *filter;
-               filter = lookup_commit_reference_gently(merge_filter_ref, 0);
-               if (!filter)
-                       die(_("object '%s' does not point to a commit"),
-                           sha1_to_hex(merge_filter_ref));
-
-               filter->object.flags |= UNINTERESTING;
-               add_pending_object(&ref_list.revs,
-                                  (struct object *) filter, "");
-               ref_list.revs.limited = 1;
-
-               if (prepare_revision_walk(&ref_list.revs))
-                       die(_("revision walk setup failed"));
-
-               for (i = 0; i < ref_list.index; i++) {
-                       struct ref_item *item = &ref_list.list[i];
-                       struct commit *commit = item->commit;
-                       int is_merged = !!(commit->object.flags & UNINTERESTING);
-                       item->ignore = is_merged != (merge_filter == SHOW_MERGED);
-               }
+       struct ref_array array;
+       int maxwidth = 0;
+       const char *remote_prefix = "";
 
-               for (i = 0; i < ref_list.index; i++) {
-                       struct ref_item *item = &ref_list.list[i];
-                       clear_commit_marks(item->commit, ALL_REV_FLAGS);
-               }
-               clear_commit_marks(filter, ALL_REV_FLAGS);
+       /*
+        * If we are listing more than just remote branches,
+        * then remote branches will have a "remotes/" prefix.
+        * We need to account for this in the width.
+        */
+       if (filter->kind != FILTER_REFS_REMOTES)
+               remote_prefix = "remotes/";
 
-               if (verbose)
-                       ref_list.maxwidth = calc_maxwidth(&ref_list);
-       }
+       memset(&array, 0, sizeof(array));
 
-       qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
-
-       detached = (detached && (kinds & REF_LOCAL_BRANCH));
-       if (detached && match_patterns(pattern, "HEAD"))
-               show_detached(&ref_list);
-
-       for (i = 0; i < ref_list.index; i++) {
-               int current = !detached &&
-                       (ref_list.list[i].kind == REF_LOCAL_BRANCH) &&
-                       !strcmp(ref_list.list[i].name, head);
-               char *prefix = (kinds != REF_REMOTE_BRANCH &&
-                               ref_list.list[i].kind == REF_REMOTE_BRANCH)
-                               ? "remotes/" : "";
-               print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,
-                              abbrev, current, prefix);
-       }
+       verify_ref_format("%(refname)%(symref)");
+       filter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN);
 
-       free_ref_list(&ref_list);
+       if (filter->verbose)
+               maxwidth = calc_maxwidth(&array, strlen(remote_prefix));
 
-       if (cb.ret)
-               error(_("some refs could not be read"));
+       /*
+        * If no sorting parameter is given then we default to sorting
+        * by 'refname'. This would give us an alphabetically sorted
+        * array with the 'HEAD' ref at the beginning followed by
+        * local branches 'refs/heads/...' and finally remote-tacking
+        * branches 'refs/remotes/...'.
+        */
+       if (!sorting)
+               sorting = ref_default_sorting();
+       ref_array_sort(sorting, &array);
+
+       for (i = 0; i < array.nr; i++)
+               format_and_print_ref_item(array.items[i], maxwidth, filter, remote_prefix);
 
-       return cb.ret;
+       ref_array_clear(&array);
 }
 
 static void rename_branch(const char *oldname, const char *newname, int force)
@@ -746,20 +566,6 @@ static void rename_branch(const char *oldname, const char *newname, int force)
        strbuf_release(&newsection);
 }
 
-static int opt_parse_merge_filter(const struct option *opt, const char *arg, int unset)
-{
-       merge_filter = ((opt->long_name[0] == 'n')
-                       ? SHOW_NOT_MERGED
-                       : SHOW_MERGED);
-       if (unset)
-               merge_filter = SHOW_NOT_MERGED; /* b/c for --no-merged */
-       if (!arg)
-               arg = "HEAD";
-       if (get_sha1(arg, merge_filter_ref))
-               die(_("malformed object name %s"), arg);
-       return 0;
-}
-
 static const char edit_description[] = "BRANCH_DESCRIPTION";
 
 static int edit_branch_description(const char *branch_name)
@@ -786,7 +592,7 @@ static int edit_branch_description(const char *branch_name)
                strbuf_release(&buf);
                return -1;
        }
-       stripspace(&buf, 1);
+       strbuf_stripspace(&buf, 1);
 
        strbuf_addf(&name, "branch.%s.description", branch_name);
        status = git_config_set(name.buf, buf.len ? buf.buf : NULL);
@@ -799,17 +605,16 @@ static int edit_branch_description(const char *branch_name)
 int cmd_branch(int argc, const char **argv, const char *prefix)
 {
        int delete = 0, rename = 0, force = 0, list = 0;
-       int verbose = 0, abbrev = -1, detached = 0;
        int reflog = 0, edit_description = 0;
        int quiet = 0, unset_upstream = 0;
        const char *new_upstream = NULL;
        enum branch_track track;
-       int kinds = REF_LOCAL_BRANCH;
-       struct commit_list *with_commit = NULL;
+       struct ref_filter filter;
+       static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
 
        struct option options[] = {
                OPT_GROUP(N_("Generic options")),
-               OPT__VERBOSE(&verbose,
+               OPT__VERBOSE(&filter.verbose,
                        N_("show hash and subject, give twice for upstream branch")),
                OPT__QUIET(&quiet, N_("suppress informational messages")),
                OPT_SET_INT('t', "track",  &track, N_("set up tracking mode (see git-pull(1))"),
@@ -819,25 +624,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                OPT_STRING('u', "set-upstream-to", &new_upstream, "upstream", "change the upstream info"),
                OPT_BOOL(0, "unset-upstream", &unset_upstream, "Unset the upstream info"),
                OPT__COLOR(&branch_use_color, N_("use colored output")),
-               OPT_SET_INT('r', "remotes",     &kinds, N_("act on remote-tracking branches"),
-                       REF_REMOTE_BRANCH),
-               {
-                       OPTION_CALLBACK, 0, "contains", &with_commit, N_("commit"),
-                       N_("print only branches that contain the commit"),
-                       PARSE_OPT_LASTARG_DEFAULT,
-                       parse_opt_with_commit, (intptr_t)"HEAD",
-               },
-               {
-                       OPTION_CALLBACK, 0, "with", &with_commit, N_("commit"),
-                       N_("print only branches that contain the commit"),
-                       PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
-                       parse_opt_with_commit, (intptr_t) "HEAD",
-               },
-               OPT__ABBREV(&abbrev),
+               OPT_SET_INT('r', "remotes",     &filter.kind, N_("act on remote-tracking branches"),
+                       FILTER_REFS_REMOTES),
+               OPT_CONTAINS(&filter.with_commit, N_("print only branches that contain the commit")),
+               OPT_WITH(&filter.with_commit, N_("print only branches that contain the commit")),
+               OPT__ABBREV(&filter.abbrev),
 
                OPT_GROUP(N_("Specific git-branch actions:")),
-               OPT_SET_INT('a', "all", &kinds, N_("list both remote-tracking and local branches"),
-                       REF_REMOTE_BRANCH | REF_LOCAL_BRANCH),
+               OPT_SET_INT('a', "all", &filter.kind, N_("list both remote-tracking and local branches"),
+                       FILTER_REFS_REMOTES | FILTER_REFS_BRANCHES),
                OPT_BIT('d', "delete", &delete, N_("delete fully merged branch"), 1),
                OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
                OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
@@ -847,22 +642,22 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                OPT_BOOL(0, "edit-description", &edit_description,
                         N_("edit the description for the branch")),
                OPT__FORCE(&force, N_("force creation, move/rename, deletion")),
+               OPT_MERGED(&filter, N_("print only branches that are merged")),
+               OPT_NO_MERGED(&filter, N_("print only branches that are not merged")),
+               OPT_COLUMN(0, "column", &colopts, N_("list branches in columns")),
+               OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
+                            N_("field name to sort on"), &parse_opt_ref_sorting),
                {
-                       OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
-                       N_("commit"), N_("print only not merged branches"),
-                       PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
-                       opt_parse_merge_filter, (intptr_t) "HEAD",
-               },
-               {
-                       OPTION_CALLBACK, 0, "merged", &merge_filter_ref,
-                       N_("commit"), N_("print only merged branches"),
-                       PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
-                       opt_parse_merge_filter, (intptr_t) "HEAD",
+                       OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"),
+                       N_("print only branches of the object"), 0, parse_opt_object_name
                },
-               OPT_COLUMN(0, "column", &colopts, N_("list branches in columns")),
                OPT_END(),
        };
 
+       memset(&filter, 0, sizeof(filter));
+       filter.kind = FILTER_REFS_BRANCHES;
+       filter.abbrev = -1;
+
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage_with_options(builtin_branch_usage, options);
 
@@ -874,11 +669,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        if (!head)
                die(_("Failed to resolve HEAD as a valid ref."));
        if (!strcmp(head, "HEAD"))
-               detached = 1;
+               filter.detached = 1;
        else if (!skip_prefix(head, "refs/heads/", &head))
                die(_("HEAD not found below refs/heads!"));
-       hashcpy(merge_filter_ref, head_sha1);
-
 
        argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
                             0);
@@ -886,17 +679,17 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)
                list = 1;
 
-       if (with_commit || merge_filter != NO_FILTER)
+       if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr)
                list = 1;
 
        if (!!delete + !!rename + !!new_upstream +
            list + unset_upstream > 1)
                usage_with_options(builtin_branch_usage, options);
 
-       if (abbrev == -1)
-               abbrev = DEFAULT_ABBREV;
+       if (filter.abbrev == -1)
+               filter.abbrev = DEFAULT_ABBREV;
        finalize_colopts(&colopts, -1);
-       if (verbose) {
+       if (filter.verbose) {
                if (explicitly_enable_column(colopts))
                        die(_("--column and --verbose are incompatible"));
                colopts = 0;
@@ -910,20 +703,23 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        if (delete) {
                if (!argc)
                        die(_("branch name required"));
-               return delete_branches(argc, argv, delete > 1, kinds, quiet);
+               return delete_branches(argc, argv, delete > 1, filter.kind, quiet);
        } else if (list) {
-               int ret = print_ref_list(kinds, detached, verbose, abbrev,
-                                        with_commit, argv);
+               /*  git branch --local also shows HEAD when it is detached */
+               if ((filter.kind & FILTER_REFS_BRANCHES) && filter.detached)
+                       filter.kind |= FILTER_REFS_DETACHED_HEAD;
+               filter.name_patterns = argv;
+               print_ref_list(&filter, sorting);
                print_columns(&output, colopts, NULL);
                string_list_clear(&output, 0);
-               return ret;
+               return 0;
        }
        else if (edit_description) {
                const char *branch_name;
                struct strbuf branch_ref = STRBUF_INIT;
 
                if (!argc) {
-                       if (detached)
+                       if (filter.detached)
                                die(_("Cannot give description to detached HEAD"));
                        branch_name = head;
                } else if (argc == 1)
@@ -1011,7 +807,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                if (!branch)
                        die(_("no such branch '%s'"), argv[0]);
 
-               if (kinds != REF_LOCAL_BRANCH)
+               if (filter.kind != FILTER_REFS_BRANCHES)
                        die(_("-a and -r options to 'git branch' do not make sense with a branch name"));
 
                if (track == BRANCH_TRACK_OVERRIDE)
index 07baad1..c0fd8db 100644 (file)
@@ -426,7 +426,7 @@ static int batch_objects(struct batch_options *opt)
 
 static const char * const cat_file_usage[] = {
        N_("git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p|<type>|--textconv) <object>"),
-       N_("git cat-file (--batch | --batch-check) [--follow-symlinks] < <list-of-objects>"),
+       N_("git cat-file (--batch | --batch-check) [--follow-symlinks]"),
        NULL
 };
 
index 21d2bed..265c9ba 100644 (file)
@@ -9,7 +9,7 @@ static int cached_attrs;
 static int stdin_paths;
 static const char * const check_attr_usage[] = {
 N_("git check-attr [-a | --all | <attr>...] [--] <pathname>..."),
-N_("git check-attr --stdin [-z] [-a | --all | <attr>...] < <list-of-paths>"),
+N_("git check-attr --stdin [-z] [-a | --all | <attr>...]"),
 NULL
 };
 
index dc8d97c..43f3617 100644 (file)
@@ -8,7 +8,7 @@
 static int quiet, verbose, stdin_paths, show_non_matching, no_index;
 static const char * const check_ignore_usage[] = {
 "git check-ignore [<options>] <pathname>...",
-"git check-ignore [<options>] --stdin < <list-of-paths>",
+"git check-ignore [<options>] --stdin",
 NULL
 };
 
index bc703c0..e8110a9 100644 (file)
@@ -37,6 +37,7 @@ struct checkout_opts {
        int overwrite_ignore;
        int ignore_skipworktree;
        int ignore_other_worktrees;
+       int show_progress;
 
        const char *new_branch;
        const char *new_branch_force;
@@ -55,8 +56,8 @@ static int post_checkout_hook(struct commit *old, struct commit *new,
                              int changed)
 {
        return run_hook_le(NULL, "post-checkout",
-                          sha1_to_hex(old ? old->object.sha1 : null_sha1),
-                          sha1_to_hex(new ? new->object.sha1 : null_sha1),
+                          sha1_to_hex(old ? old->object.oid.hash : null_sha1),
+                          sha1_to_hex(new ? new->object.oid.hash : null_sha1),
                           changed ? "1" : "0", NULL);
        /* "new" can be NULL when checking out from the index before
           a commit exists. */
@@ -400,7 +401,7 @@ static void describe_detached_head(const char *msg, struct commit *commit)
        if (!parse_commit(commit))
                pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);
        fprintf(stderr, "%s %s... %s\n", msg,
-               find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV), sb.buf);
+               find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV), sb.buf);
        strbuf_release(&sb);
 }
 
@@ -417,7 +418,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
        opts.reset = 1;
        opts.merge = 1;
        opts.fn = oneway_merge;
-       opts.verbose_update = !o->quiet && isatty(2);
+       opts.verbose_update = o->show_progress;
        opts.src_index = &the_index;
        opts.dst_index = &the_index;
        parse_tree(tree);
@@ -501,7 +502,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
                topts.update = 1;
                topts.merge = 1;
                topts.gently = opts->merge && old->commit;
-               topts.verbose_update = !opts->quiet && isatty(2);
+               topts.verbose_update = opts->show_progress;
                topts.fn = twoway_merge;
                if (opts->overwrite_ignore) {
                        topts.dir = xcalloc(1, sizeof(*topts.dir));
@@ -509,10 +510,10 @@ static int merge_working_tree(const struct checkout_opts *opts,
                        setup_standard_excludes(topts.dir);
                }
                tree = parse_tree_indirect(old->commit ?
-                                          old->commit->object.sha1 :
+                                          old->commit->object.oid.hash :
                                           EMPTY_TREE_SHA1_BIN);
                init_tree_desc(&trees[0], tree->buffer, tree->size);
-               tree = parse_tree_indirect(new->commit->object.sha1);
+               tree = parse_tree_indirect(new->commit->object.oid.hash);
                init_tree_desc(&trees[1], tree->buffer, tree->size);
 
                ret = unpack_trees(2, trees, &topts);
@@ -640,7 +641,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
 
        old_desc = old->name;
        if (!old_desc && old->commit)
-               old_desc = sha1_to_hex(old->commit->object.sha1);
+               old_desc = oid_to_hex(&old->commit->object.oid);
 
        reflog_msg = getenv("GIT_REFLOG_ACTION");
        if (!reflog_msg)
@@ -652,7 +653,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
        if (!strcmp(new->name, "HEAD") && !new->path && !opts->force_detach) {
                /* Nothing to do. */
        } else if (opts->force_detach || !new->path) {  /* No longer on any branch. */
-               update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL,
+               update_ref(msg.buf, "HEAD", new->commit->object.oid.hash, NULL,
                           REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
                if (!opts->quiet) {
                        if (old->path && advice_detached_head)
@@ -703,7 +704,7 @@ static void describe_one_orphan(struct strbuf *sb, struct commit *commit)
 {
        strbuf_addstr(sb, "  ");
        strbuf_addstr(sb,
-               find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
+               find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));
        strbuf_addch(sb, ' ');
        if (!parse_commit(commit))
                pp_commit_easy(CMIT_FMT_ONELINE, commit, sb);
@@ -761,7 +762,7 @@ static void suggest_reattach(struct commit *commit, struct rev_info *revs)
                        " git branch <new-branch-name> %s\n\n",
                        /* Give ngettext() the count */
                        lost),
-                       find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
+                       find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));
 }
 
 /*
@@ -779,10 +780,10 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new)
        setup_revisions(0, NULL, &revs, NULL);
 
        object->flags &= ~UNINTERESTING;
-       add_pending_object(&revs, object, sha1_to_hex(object->sha1));
+       add_pending_object(&revs, object, oid_to_hex(&object->oid));
 
        for_each_ref(add_pending_uninteresting_ref, &revs);
-       add_pending_sha1(&revs, "HEAD", new->object.sha1, UNINTERESTING);
+       add_pending_sha1(&revs, "HEAD", new->object.oid.hash, UNINTERESTING);
 
        refs = revs.pending;
        revs.leak_pending = 1;
@@ -1156,6 +1157,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                                N_("second guess 'git checkout <no-such-branch>'")),
                OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
                         N_("do not check if another worktree is holding the given ref")),
+               OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
                OPT_END(),
        };
 
@@ -1163,6 +1165,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        memset(&new, 0, sizeof(new));
        opts.overwrite_ignore = 1;
        opts.prefix = prefix;
+       opts.show_progress = -1;
 
        gitmodules_config();
        git_config(git_checkout_config, &opts);
@@ -1172,6 +1175,13 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, options, checkout_usage,
                             PARSE_OPT_KEEP_DASHDASH);
 
+       if (opts.show_progress < 0) {
+               if (opts.quiet)
+                       opts.show_progress = 0;
+               else
+                       opts.show_progress = isatty(2);
+       }
+
        if (conflict_style) {
                opts.merge = 1; /* implied */
                git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
index df53def..d7acb94 100644 (file)
@@ -159,8 +159,7 @@ static int is_git_repository(struct strbuf *path)
        int gitfile_error;
        size_t orig_path_len = path->len;
        assert(orig_path_len != 0);
-       if (path->buf[orig_path_len - 1] != '/')
-               strbuf_addch(path, '/');
+       strbuf_complete(path, '/');
        strbuf_addstr(path, ".git");
        if (read_gitfile_gently(path->buf, &gitfile_error) || is_git_directory(path->buf))
                ret = 1;
@@ -206,8 +205,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
                return res;
        }
 
-       if (path->buf[original_len - 1] != '/')
-               strbuf_addch(path, '/');
+       strbuf_complete(path, '/');
 
        len = path->len;
        while ((e = readdir(dir)) != NULL) {
index 578da85..a0b3cd9 100644 (file)
@@ -294,9 +294,14 @@ static int add_one_reference(struct string_list_item *item, void *cb_data)
                char *ref_git_git = mkpathdup("%s/.git", ref_git);
                free(ref_git);
                ref_git = ref_git_git;
-       } else if (!is_directory(mkpath("%s/objects", ref_git)))
+       } else if (!is_directory(mkpath("%s/objects", ref_git))) {
+               struct strbuf sb = STRBUF_INIT;
+               if (get_common_dir(&sb, ref_git))
+                       die(_("reference repository '%s' as a linked checkout is not supported yet."),
+                           item->string);
                die(_("reference repository '%s' is not a local repository."),
                    item->string);
+       }
 
        if (!access(mkpath("%s/shallow", ref_git), F_OK))
                die(_("reference repository '%s' is shallow"), item->string);
@@ -424,8 +429,10 @@ static void clone_local(const char *src_repo, const char *dest_repo)
        } else {
                struct strbuf src = STRBUF_INIT;
                struct strbuf dest = STRBUF_INIT;
-               strbuf_addf(&src, "%s/objects", src_repo);
-               strbuf_addf(&dest, "%s/objects", dest_repo);
+               get_common_dir(&src, src_repo);
+               get_common_dir(&dest, dest_repo);
+               strbuf_addstr(&src, "/objects");
+               strbuf_addstr(&dest, "/objects");
                copy_or_link_directory(&src, &dest, src_repo, src.len);
                strbuf_release(&src);
                strbuf_release(&dest);
@@ -552,7 +559,7 @@ static void write_remote_refs(const struct ref *local_refs)
        for (r = local_refs; r; r = r->next) {
                if (!r->peer_ref)
                        continue;
-               if (ref_transaction_create(t, r->peer_ref->name, r->old_sha1,
+               if (ref_transaction_create(t, r->peer_ref->name, r->old_oid.hash,
                                           0, NULL, &err))
                        die("%s", err.buf);
        }
@@ -572,9 +579,9 @@ static void write_followtags(const struct ref *refs, const char *msg)
                        continue;
                if (ends_with(ref->name, "^{}"))
                        continue;
-               if (!has_sha1_file(ref->old_sha1))
+               if (!has_object_file(&ref->old_oid))
                        continue;
-               update_ref(msg, ref->name, ref->old_sha1,
+               update_ref(msg, ref->name, ref->old_oid.hash,
                           NULL, 0, UPDATE_REFS_DIE_ON_ERR);
        }
 }
@@ -594,7 +601,7 @@ static int iterate_ref_map(void *cb_data, unsigned char sha1[20])
        if (!ref)
                return -1;
 
-       hashcpy(sha1, ref->old_sha1);
+       hashcpy(sha1, ref->old_oid.hash);
        *rm = ref->next;
        return 0;
 }
@@ -643,14 +650,14 @@ static void update_head(const struct ref *our, const struct ref *remote,
                /* Local default branch link */
                create_symref("HEAD", our->name, NULL);
                if (!option_bare) {
-                       update_ref(msg, "HEAD", our->old_sha1, NULL, 0,
+                       update_ref(msg, "HEAD", our->old_oid.hash, NULL, 0,
                                   UPDATE_REFS_DIE_ON_ERR);
                        install_branch_config(0, head, option_origin, our->name);
                }
        } else if (our) {
-               struct commit *c = lookup_commit_reference(our->old_sha1);
+               struct commit *c = lookup_commit_reference(our->old_oid.hash);
                /* --branch specifies a non-branch (i.e. tags), detach HEAD */
-               update_ref(msg, "HEAD", c->object.sha1,
+               update_ref(msg, "HEAD", c->object.oid.hash,
                           NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
        } else if (remote) {
                /*
@@ -658,7 +665,7 @@ static void update_head(const struct ref *our, const struct ref *remote,
                 * HEAD points to a branch but we don't know which one.
                 * Detach HEAD in all these cases.
                 */
-               update_ref(msg, "HEAD", remote->old_sha1,
+               update_ref(msg, "HEAD", remote->old_oid.hash,
                           NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
        }
 }
@@ -794,11 +801,15 @@ static void write_refspec_config(const char *src_ref_prefix,
 static void dissociate_from_references(void)
 {
        static const char* argv[] = { "repack", "-a", "-d", NULL };
+       char *alternates = git_pathdup("objects/info/alternates");
 
-       if (run_command_v_opt(argv, RUN_GIT_CMD|RUN_COMMAND_NO_STDIN))
-               die(_("cannot repack to clean up"));
-       if (unlink(git_path("objects/info/alternates")) && errno != ENOENT)
-               die_errno(_("cannot unlink temporary alternates file"));
+       if (!access(alternates, F_OK)) {
+               if (run_command_v_opt(argv, RUN_GIT_CMD|RUN_COMMAND_NO_STDIN))
+                       die(_("cannot repack to clean up"));
+               if (unlink(alternates) && errno != ENOENT)
+                       die_errno(_("cannot unlink temporary alternates file"));
+       }
+       free(alternates);
 }
 
 int cmd_clone(int argc, const char **argv, const char *prefix)
@@ -947,10 +958,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
        if (option_reference.nr)
                setup_reference();
-       else if (option_dissociate) {
-               warning(_("--dissociate given, but there is no --reference"));
-               option_dissociate = 0;
-       }
 
        fetch_pattern = value.buf;
        refspec = parse_fetch_refspec(1, &fetch_pattern);
@@ -1009,7 +1016,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                 * remote HEAD check.
                 */
                for (ref = refs; ref; ref = ref->next)
-                       if (is_null_sha1(ref->old_sha1)) {
+                       if (is_null_oid(&ref->old_oid)) {
                                complete_refs_before_fetch = 0;
                                break;
                        }
@@ -1064,8 +1071,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        transport_unlock_pack(transport);
        transport_disconnect(transport);
 
-       if (option_dissociate)
+       if (option_dissociate) {
+               close_all_packs();
                dissociate_from_references();
+       }
 
        junk_mode = JUNK_LEAVE_REPO;
        err = checkout();
index 25aa2cd..3feeffe 100644 (file)
 #include "utf8.h"
 #include "gpg-interface.h"
 
-static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S[<keyid>]] [-m <message>] [-F <file>] <sha1> <changelog";
+static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S[<keyid>]] [-m <message>] [-F <file>] <sha1>";
 
 static const char *sign_commit;
 
 static void new_parent(struct commit *parent, struct commit_list **parents_p)
 {
-       unsigned char *sha1 = parent->object.sha1;
+       struct object_id *oid = &parent->object.oid;
        struct commit_list *parents;
        for (parents = *parents_p; parents; parents = parents->next) {
                if (parents->item == parent) {
-                       error("duplicate parent %s ignored", sha1_to_hex(sha1));
+                       error("duplicate parent %s ignored", oid_to_hex(oid));
                        return;
                }
                parents_p = &parents->next;
index 63772d0..d054f84 100644 (file)
@@ -32,6 +32,7 @@
 #include "sequencer.h"
 #include "notes-utils.h"
 #include "mailmap.h"
+#include "sigchain.h"
 
 static const char * const builtin_commit_usage[] = {
        N_("git commit [<options>] [--] <pathspec>..."),
@@ -299,7 +300,7 @@ static void create_base_index(const struct commit *current_head)
        opts.dst_index = &the_index;
 
        opts.fn = oneway_merge;
-       tree = parse_tree_indirect(current_head->object.sha1);
+       tree = parse_tree_indirect(current_head->object.oid.hash);
        if (!tree)
                die(_("failed to unpack HEAD tree object"));
        parse_tree(tree);
@@ -775,7 +776,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
        s->hints = 0;
 
        if (clean_message_contents)
-               stripspace(&sb, 0);
+               strbuf_stripspace(&sb, 0);
 
        if (signoff)
                append_signoff(&sb, ignore_non_trailer(&sb), 0);
@@ -1014,7 +1015,7 @@ static int template_untouched(struct strbuf *sb)
        if (!template_file || strbuf_read_file(&tmpl, template_file, 0) <= 0)
                return 0;
 
-       stripspace(&tmpl, cleanup_mode == CLEANUP_ALL);
+       strbuf_stripspace(&tmpl, cleanup_mode == CLEANUP_ALL);
        if (!skip_prefix(sb->buf, tmpl.buf, &start))
                start = sb->buf;
        strbuf_release(&tmpl);
@@ -1537,8 +1538,10 @@ static int run_rewrite_hook(const unsigned char *oldsha1,
                return code;
        n = snprintf(buf, sizeof(buf), "%s %s\n",
                     sha1_to_hex(oldsha1), sha1_to_hex(newsha1));
+       sigchain_push(SIGPIPE, SIG_IGN);
        write_in_full(proc.in, buf, n);
        close(proc.in);
+       sigchain_pop(SIGPIPE);
        return finish_command(&proc);
 }
 
@@ -1726,7 +1729,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                wt_status_truncate_message_at_cut_line(&sb);
 
        if (cleanup_mode != CLEANUP_NONE)
-               stripspace(&sb, cleanup_mode == CLEANUP_ALL);
+               strbuf_stripspace(&sb, cleanup_mode == CLEANUP_ALL);
        if (template_untouched(&sb) && !allow_empty_message) {
                rollback_index_files();
                fprintf(stderr, _("Aborting commit; you did not edit the message.\n"));
@@ -1766,7 +1769,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        if (!transaction ||
            ref_transaction_update(transaction, "HEAD", sha1,
                                   current_head
-                                  ? current_head->object.sha1 : null_sha1,
+                                  ? current_head->object.oid.hash : null_sha1,
                                   0, sb.buf, &err) ||
            ref_transaction_commit(transaction, &err)) {
                rollback_index_files();
@@ -1793,10 +1796,10 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                cfg = init_copy_notes_for_rewrite("amend");
                if (cfg) {
                        /* we are amending, so current_head is not NULL */
-                       copy_note_for_rewrite(cfg, current_head->object.sha1, sha1);
+                       copy_note_for_rewrite(cfg, current_head->object.oid.hash, sha1);
                        finish_copy_notes_for_rewrite(cfg, "Notes added by 'git commit --amend'");
                }
-               run_rewrite_hook(current_head->object.sha1, sha1);
+               run_rewrite_hook(current_head->object.oid.hash, sha1);
        }
        if (!quiet)
                print_summary(prefix, sha1, !current_head);
index 71acc44..adc7727 100644 (file)
@@ -246,8 +246,6 @@ free_strings:
 
 static char *normalize_value(const char *key, const char *value)
 {
-       char *normalized;
-
        if (!value)
                return NULL;
 
@@ -258,27 +256,21 @@ static char *normalize_value(const char *key, const char *value)
                 * "~/foobar/" in the config file, and to expand the ~
                 * when retrieving the value.
                 */
-               normalized = xstrdup(value);
-       else {
-               normalized = xmalloc(64);
-               if (types == TYPE_INT) {
-                       int64_t v = git_config_int64(key, value);
-                       sprintf(normalized, "%"PRId64, v);
-               }
-               else if (types == TYPE_BOOL)
-                       sprintf(normalized, "%s",
-                               git_config_bool(key, value) ? "true" : "false");
-               else if (types == TYPE_BOOL_OR_INT) {
-                       int is_bool, v;
-                       v = git_config_bool_or_int(key, value, &is_bool);
-                       if (!is_bool)
-                               sprintf(normalized, "%d", v);
-                       else
-                               sprintf(normalized, "%s", v ? "true" : "false");
-               }
+               return xstrdup(value);
+       if (types == TYPE_INT)
+               return xstrfmt("%"PRId64, git_config_int64(key, value));
+       if (types == TYPE_BOOL)
+               return xstrdup(git_config_bool(key, value) ?  "true" : "false");
+       if (types == TYPE_BOOL_OR_INT) {
+               int is_bool, v;
+               v = git_config_bool_or_int(key, value, &is_bool);
+               if (!is_bool)
+                       return xstrfmt("%d", v);
+               else
+                       return xstrdup(v ? "true" : "false");
        }
 
-       return normalized;
+       die("BUG: cannot normalize type %d", types);
 }
 
 static int get_color_found;
index ad0c799..ba92919 100644 (file)
@@ -15,9 +15,31 @@ static int verbose;
 static unsigned long loose, packed, packed_loose;
 static off_t loose_size;
 
-static void real_report_garbage(const char *desc, const char *path)
+static const char *bits_to_msg(unsigned seen_bits)
+{
+       switch (seen_bits) {
+       case 0:
+               return "no corresponding .idx or .pack";
+       case PACKDIR_FILE_GARBAGE:
+               return "garbage found";
+       case PACKDIR_FILE_PACK:
+               return "no corresponding .idx";
+       case PACKDIR_FILE_IDX:
+               return "no corresponding .pack";
+       case PACKDIR_FILE_PACK|PACKDIR_FILE_IDX:
+       default:
+               return NULL;
+       }
+}
+
+static void real_report_garbage(unsigned seen_bits, const char *path)
 {
        struct stat st;
+       const char *desc = bits_to_msg(seen_bits);
+
+       if (!desc)
+               return;
+
        if (!stat(path, &st))
                size_garbage += st.st_size;
        warning("%s: %s", desc, path);
@@ -27,7 +49,7 @@ static void real_report_garbage(const char *desc, const char *path)
 static void loose_garbage(const char *path)
 {
        if (verbose)
-               report_garbage("garbage found", path);
+               report_garbage(PACKDIR_FILE_GARBAGE, path);
 }
 
 static int count_loose(const unsigned char *sha1, const char *path, void *data)
index 7df5543..8a25abe 100644 (file)
@@ -252,14 +252,14 @@ static void describe(const char *arg, int last_one)
        if (!cmit)
                die(_("%s is not a valid '%s' object"), arg, commit_type);
 
-       n = find_commit_name(cmit->object.sha1);
+       n = find_commit_name(cmit->object.oid.hash);
        if (n && (tags || all || n->prio == 2)) {
                /*
                 * Exact match to an existing ref.
                 */
                display_name(n);
                if (longformat)
-                       show_suffix(0, n->tag ? n->tag->tagged->sha1 : sha1);
+                       show_suffix(0, n->tag ? n->tag->tagged->oid.hash : sha1);
                if (dirty)
                        printf("%s", dirty);
                printf("\n");
@@ -267,7 +267,7 @@ static void describe(const char *arg, int last_one)
        }
 
        if (!max_candidates)
-               die(_("no tag exactly matches '%s'"), sha1_to_hex(cmit->object.sha1));
+               die(_("no tag exactly matches '%s'"), oid_to_hex(&cmit->object.oid));
        if (debug)
                fprintf(stderr, _("searching to describe %s\n"), arg);
 
@@ -317,7 +317,7 @@ static void describe(const char *arg, int last_one)
                if (annotated_cnt && !list) {
                        if (debug)
                                fprintf(stderr, _("finished search at %s\n"),
-                                       sha1_to_hex(c->object.sha1));
+                                       oid_to_hex(&c->object.oid));
                        break;
                }
                while (parents) {
@@ -334,9 +334,9 @@ static void describe(const char *arg, int last_one)
        }
 
        if (!match_cnt) {
-               const unsigned char *sha1 = cmit->object.sha1;
+               struct object_id *oid = &cmit->object.oid;
                if (always) {
-                       printf("%s", find_unique_abbrev(sha1, abbrev));
+                       printf("%s", find_unique_abbrev(oid->hash, abbrev));
                        if (dirty)
                                printf("%s", dirty);
                        printf("\n");
@@ -345,11 +345,11 @@ static void describe(const char *arg, int last_one)
                if (unannotated_cnt)
                        die(_("No annotated tags can describe '%s'.\n"
                            "However, there were unannotated tags: try --tags."),
-                           sha1_to_hex(sha1));
+                           oid_to_hex(oid));
                else
                        die(_("No tags can describe '%s'.\n"
                            "Try --always, or create some tags."),
-                           sha1_to_hex(sha1));
+                           oid_to_hex(oid));
        }
 
        qsort(all_matches, match_cnt, sizeof(all_matches[0]), compare_pt);
@@ -374,13 +374,13 @@ static void describe(const char *arg, int last_one)
                                _("more than %i tags found; listed %i most recent\n"
                                "gave up search at %s\n"),
                                max_candidates, max_candidates,
-                               sha1_to_hex(gave_up_on->object.sha1));
+                               oid_to_hex(&gave_up_on->object.oid));
                }
        }
 
        display_name(all_matches[0].name);
        if (abbrev)
-               show_suffix(all_matches[0].depth, cmit->object.sha1);
+               show_suffix(all_matches[0].depth, cmit->object.oid.hash);
        if (dirty)
                printf("%s", dirty);
        printf("\n");
index 12b683d..2a12b81 100644 (file)
@@ -49,9 +49,9 @@ static int stdin_diff_trees(struct tree *tree1, char *line, int len)
        tree2 = lookup_tree(sha1);
        if (!tree2 || parse_tree(tree2))
                return -1;
-       printf("%s %s\n", sha1_to_hex(tree1->object.sha1),
-                         sha1_to_hex(tree2->object.sha1));
-       diff_tree_sha1(tree1->object.sha1, tree2->object.sha1,
+       printf("%s %s\n", oid_to_hex(&tree1->object.oid),
+                         oid_to_hex(&tree2->object.oid));
+       diff_tree_sha1(tree1->object.oid.hash, tree2->object.oid.hash,
                       "", &log_tree_opt.diffopt);
        log_tree_diff_flush(&log_tree_opt);
        return 0;
@@ -139,7 +139,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
                break;
        case 1:
                tree1 = opt->pending.objects[0].item;
-               diff_tree_commit_sha1(tree1->sha1);
+               diff_tree_commit_sha1(tree1->oid.hash);
                break;
        case 2:
                tree1 = opt->pending.objects[0].item;
@@ -149,8 +149,8 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
                        tree2 = tree1;
                        tree1 = tmp;
                }
-               diff_tree_sha1(tree1->sha1,
-                              tree2->sha1,
+               diff_tree_sha1(tree1->oid.hash,
+                              tree2->oid.hash,
                               "", &opt->diffopt);
                log_tree_diff_flush(opt);
                break;
index 4326fa5..ed0acca 100644 (file)
@@ -175,8 +175,8 @@ static int builtin_diff_tree(struct rev_info *revs,
         */
        if (ent1->item->flags & UNINTERESTING)
                swap = 1;
-       sha1[swap] = ent0->item->sha1;
-       sha1[1 - swap] = ent1->item->sha1;
+       sha1[swap] = ent0->item->oid.hash;
+       sha1[1 - swap] = ent1->item->oid.hash;
        diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt);
        log_tree_diff_flush(revs);
        return 0;
@@ -196,8 +196,8 @@ static int builtin_diff_combined(struct rev_info *revs,
        if (!revs->dense_combined_merges && !revs->combine_merges)
                revs->dense_combined_merges = revs->combine_merges = 1;
        for (i = 1; i < ents; i++)
-               sha1_array_append(&parents, ent[i].item->sha1);
-       diff_tree_combined(ent[0].item->sha1, &parents,
+               sha1_array_append(&parents, ent[i].item->oid.hash);
+       diff_tree_combined(ent[0].item->oid.hash, &parents,
                           revs->dense_combined_merges, revs);
        sha1_array_clear(&parents);
        return 0;
@@ -395,7 +395,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
                const char *name = entry->name;
                int flags = (obj->flags & UNINTERESTING);
                if (!obj->parsed)
-                       obj = parse_object(obj->sha1);
+                       obj = parse_object(obj->oid.hash);
                obj = deref_tag(obj, NULL, 0);
                if (!obj)
                        die(_("invalid object '%s' given."), name);
@@ -408,7 +408,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
                } else if (obj->type == OBJ_BLOB) {
                        if (2 <= blobs)
                                die(_("more than two blobs given: '%s'"), name);
-                       hashcpy(blob[blobs].sha1, obj->sha1);
+                       hashcpy(blob[blobs].sha1, obj->oid.hash);
                        blob[blobs].name = name;
                        blob[blobs].mode = entry->mode;
                        blobs++;
index d23f3be..d9ac5d8 100644 (file)
@@ -544,13 +544,13 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
        author = strstr(commit_buffer, "\nauthor ");
        if (!author)
                die ("Could not find author in commit %s",
-                    sha1_to_hex(commit->object.sha1));
+                    oid_to_hex(&commit->object.oid));
        author++;
        author_end = strchrnul(author, '\n');
        committer = strstr(author_end, "\ncommitter ");
        if (!committer)
                die ("Could not find committer in commit %s",
-                    sha1_to_hex(commit->object.sha1));
+                    oid_to_hex(&commit->object.oid));
        committer++;
        committer_end = strchrnul(committer, '\n');
        message = strstr(committer_end, "\n\n");
@@ -562,11 +562,11 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
            get_object_mark(&commit->parents->item->object) != 0 &&
            !full_tree) {
                parse_commit_or_die(commit->parents->item);
-               diff_tree_sha1(commit->parents->item->tree->object.sha1,
-                              commit->tree->object.sha1, "", &rev->diffopt);
+               diff_tree_sha1(commit->parents->item->tree->object.oid.hash,
+                              commit->tree->object.oid.hash, "", &rev->diffopt);
        }
        else
-               diff_root_tree_sha1(commit->tree->object.sha1,
+               diff_root_tree_sha1(commit->tree->object.oid.hash,
                                    "", &rev->diffopt);
 
        /* Export the referenced blobs, and remember the marks. */
@@ -661,13 +661,13 @@ static void handle_tag(const char *name, struct tag *tag)
        }
        if (tagged->type == OBJ_TREE) {
                warning("Omitting tag %s,\nsince tags of trees (or tags of tags of trees, etc.) are not supported.",
-                       sha1_to_hex(tag->object.sha1));
+                       oid_to_hex(&tag->object.oid));
                return;
        }
 
-       buf = read_sha1_file(tag->object.sha1, &type, &size);
+       buf = read_sha1_file(tag->object.oid.hash, &type, &size);
        if (!buf)
-               die ("Could not read tag %s", sha1_to_hex(tag->object.sha1));
+               die ("Could not read tag %s", oid_to_hex(&tag->object.oid));
        message = memmem(buf, size, "\n\n", 2);
        if (message) {
                message += 2;
@@ -706,16 +706,16 @@ static void handle_tag(const char *name, struct tag *tag)
                        case ABORT:
                                die ("Encountered signed tag %s; use "
                                     "--signed-tags=<mode> to handle it.",
-                                    sha1_to_hex(tag->object.sha1));
+                                    oid_to_hex(&tag->object.oid));
                        case WARN:
                                warning ("Exporting signed tag %s",
-                                        sha1_to_hex(tag->object.sha1));
+                                        oid_to_hex(&tag->object.oid));
                                /* fallthru */
                        case VERBATIM:
                                break;
                        case WARN_STRIP:
                                warning ("Stripping signature from tag %s",
-                                        sha1_to_hex(tag->object.sha1));
+                                        oid_to_hex(&tag->object.oid));
                                /* fallthru */
                        case STRIP:
                                message_size = signature + 1 - message;
@@ -731,14 +731,14 @@ static void handle_tag(const char *name, struct tag *tag)
                case ABORT:
                        die ("Tag %s tags unexported object; use "
                             "--tag-of-filtered-object=<mode> to handle it.",
-                            sha1_to_hex(tag->object.sha1));
+                            oid_to_hex(&tag->object.oid));
                case DROP:
                        /* Ignore this tag altogether */
                        return;
                case REWRITE:
                        if (tagged->type != OBJ_COMMIT) {
                                die ("Tag %s tags unexported %s!",
-                                    sha1_to_hex(tag->object.sha1),
+                                    oid_to_hex(&tag->object.oid),
                                     typename(tagged->type));
                        }
                        p = (struct commit *)tagged;
@@ -751,7 +751,7 @@ static void handle_tag(const char *name, struct tag *tag)
                                        break;
                                if (!p->parents)
                                        die ("Can't find replacement commit for tag %s\n",
-                                            sha1_to_hex(tag->object.sha1));
+                                            oid_to_hex(&tag->object.oid));
                                p = p->parents->item;
                        }
                        tagged_mark = get_object_mark(&p->object);
@@ -777,7 +777,7 @@ static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)
 
                /* handle nested tags */
                while (tag && tag->object.type == OBJ_TAG) {
-                       parse_object(tag->object.sha1);
+                       parse_object(tag->object.oid.hash);
                        string_list_append(&extra_refs, full_name)->util = tag;
                        tag = (struct tag *)tag->tagged;
                }
@@ -828,7 +828,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
                case OBJ_COMMIT:
                        break;
                case OBJ_BLOB:
-                       export_blob(commit->object.sha1);
+                       export_blob(commit->object.oid.hash);
                        continue;
                default: /* OBJ_TAG (nested tags) is already handled */
                        warning("Tag points to object of unexpected type %s, skipping.",
@@ -888,7 +888,7 @@ static void export_marks(char *file)
                if (deco->base && deco->base->type == 1) {
                        mark = ptr_to_mark(deco->decoration);
                        if (fprintf(f, ":%"PRIu32" %s\n", mark,
-                               sha1_to_hex(deco->base->sha1)) < 0) {
+                               oid_to_hex(&deco->base->oid)) < 0) {
                            e = 1;
                            break;
                        }
index 4a6b340..cf3019e 100644 (file)
@@ -14,12 +14,14 @@ static void add_sought_entry_mem(struct ref ***sought, int *nr, int *alloc,
                                 const char *name, int namelen)
 {
        struct ref *ref = xcalloc(1, sizeof(*ref) + namelen + 1);
-       unsigned char sha1[20];
-
-       if (namelen > 41 && name[40] == ' ' && !get_sha1_hex(name, sha1)) {
-               hashcpy(ref->old_sha1, sha1);
-               name += 41;
-               namelen -= 41;
+       struct object_id oid;
+       const int chunksz = GIT_SHA1_HEXSZ + 1;
+
+       if (namelen > chunksz && name[chunksz - 1] == ' ' &&
+               !get_oid_hex(name, &oid)) {
+               oidcpy(&ref->old_oid, &oid);
+               name += chunksz;
+               namelen -= chunksz;
        }
 
        memcpy(ref->name, name, namelen);
@@ -210,7 +212,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 
        while (ref) {
                printf("%s %s\n",
-                      sha1_to_hex(ref->old_sha1), ref->name);
+                      oid_to_hex(&ref->old_oid), ref->name);
                ref = ref->next;
        }
 
index 9a3869f..c85f347 100644 (file)
@@ -196,7 +196,7 @@ static int will_fetch(struct ref **head, const unsigned char *sha1)
 {
        struct ref *rm = *head;
        while (rm) {
-               if (!hashcmp(rm->old_sha1, sha1))
+               if (!hashcmp(rm->old_oid.hash, sha1))
                        return 1;
                rm = rm->next;
        }
@@ -224,8 +224,8 @@ static void find_non_local_tags(struct transport *transport,
                 * as one to ignore by setting util to NULL.
                 */
                if (ends_with(ref->name, "^{}")) {
-                       if (item && !has_sha1_file(ref->old_sha1) &&
-                           !will_fetch(head, ref->old_sha1) &&
+                       if (item && !has_object_file(&ref->old_oid) &&
+                           !will_fetch(head, ref->old_oid.hash) &&
                            !has_sha1_file(item->util) &&
                            !will_fetch(head, item->util))
                                item->util = NULL;
@@ -251,7 +251,7 @@ static void find_non_local_tags(struct transport *transport,
                        continue;
 
                item = string_list_insert(&remote_refs, ref->name);
-               item->util = (void *)ref->old_sha1;
+               item->util = (void *)&ref->old_oid;
        }
        string_list_clear(&existing_refs, 1);
 
@@ -273,7 +273,7 @@ static void find_non_local_tags(struct transport *transport,
                {
                        struct ref *rm = alloc_ref(item->string);
                        rm->peer_ref = alloc_ref(item->string);
-                       hashcpy(rm->old_sha1, item->util);
+                       oidcpy(&rm->old_oid, item->util);
                        **tail = rm;
                        *tail = &rm->next;
                }
@@ -419,8 +419,8 @@ static int s_update_ref(const char *action,
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
            ref_transaction_update(transaction, ref->name,
-                                  ref->new_sha1,
-                                  check_old ? ref->old_sha1 : NULL,
+                                  ref->new_oid.hash,
+                                  check_old ? ref->old_oid.hash : NULL,
                                   0, msg, &err))
                goto fail;
 
@@ -453,11 +453,11 @@ static int update_local_ref(struct ref *ref,
        struct branch *current_branch = branch_get(NULL);
        const char *pretty_ref = prettify_refname(ref->name);
 
-       type = sha1_object_info(ref->new_sha1, NULL);
+       type = sha1_object_info(ref->new_oid.hash, NULL);
        if (type < 0)
-               die(_("object %s not found"), sha1_to_hex(ref->new_sha1));
+               die(_("object %s not found"), oid_to_hex(&ref->new_oid));
 
-       if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
+       if (!oidcmp(&ref->old_oid, &ref->new_oid)) {
                if (verbosity > 0)
                        strbuf_addf(display, "= %-*s %-*s -> %s",
                                    TRANSPORT_SUMMARY(_("[up to date]")),
@@ -468,7 +468,7 @@ static int update_local_ref(struct ref *ref,
        if (current_branch &&
            !strcmp(ref->name, current_branch->name) &&
            !(update_head_ok || is_bare_repository()) &&
-           !is_null_sha1(ref->old_sha1)) {
+           !is_null_oid(&ref->old_oid)) {
                /*
                 * If this is the head, and it's not okay to update
                 * the head, and the old value of the head isn't empty...
@@ -480,7 +480,7 @@ static int update_local_ref(struct ref *ref,
                return 1;
        }
 
-       if (!is_null_sha1(ref->old_sha1) &&
+       if (!is_null_oid(&ref->old_oid) &&
            starts_with(ref->name, "refs/tags/")) {
                int r;
                r = s_update_ref("updating tag", ref, 0);
@@ -492,8 +492,8 @@ static int update_local_ref(struct ref *ref,
                return r;
        }
 
-       current = lookup_commit_reference_gently(ref->old_sha1, 1);
-       updated = lookup_commit_reference_gently(ref->new_sha1, 1);
+       current = lookup_commit_reference_gently(ref->old_oid.hash, 1);
+       updated = lookup_commit_reference_gently(ref->new_oid.hash, 1);
        if (!current || !updated) {
                const char *msg;
                const char *what;
@@ -517,7 +517,7 @@ static int update_local_ref(struct ref *ref,
 
                if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
                    (recurse_submodules != RECURSE_SUBMODULES_ON))
-                       check_for_new_submodule_commits(ref->new_sha1);
+                       check_for_new_submodule_commits(ref->new_oid.hash);
                r = s_update_ref(msg, ref, 0);
                strbuf_addf(display, "%c %-*s %-*s -> %s%s",
                            r ? '!' : '*',
@@ -528,36 +528,38 @@ static int update_local_ref(struct ref *ref,
        }
 
        if (in_merge_bases(current, updated)) {
-               char quickref[83];
+               struct strbuf quickref = STRBUF_INIT;
                int r;
-               strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
-               strcat(quickref, "..");
-               strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
+               strbuf_add_unique_abbrev(&quickref, current->object.oid.hash, DEFAULT_ABBREV);
+               strbuf_addstr(&quickref, "..");
+               strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV);
                if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
                    (recurse_submodules != RECURSE_SUBMODULES_ON))
-                       check_for_new_submodule_commits(ref->new_sha1);
+                       check_for_new_submodule_commits(ref->new_oid.hash);
                r = s_update_ref("fast-forward", ref, 1);
                strbuf_addf(display, "%c %-*s %-*s -> %s%s",
                            r ? '!' : ' ',
-                           TRANSPORT_SUMMARY_WIDTH, quickref,
+                           TRANSPORT_SUMMARY_WIDTH, quickref.buf,
                            REFCOL_WIDTH, remote, pretty_ref,
                            r ? _("  (unable to update local ref)") : "");
+               strbuf_release(&quickref);
                return r;
        } else if (force || ref->force) {
-               char quickref[84];
+               struct strbuf quickref = STRBUF_INIT;
                int r;
-               strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
-               strcat(quickref, "...");
-               strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
+               strbuf_add_unique_abbrev(&quickref, current->object.oid.hash, DEFAULT_ABBREV);
+               strbuf_addstr(&quickref, "...");
+               strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV);
                if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
                    (recurse_submodules != RECURSE_SUBMODULES_ON))
-                       check_for_new_submodule_commits(ref->new_sha1);
+                       check_for_new_submodule_commits(ref->new_oid.hash);
                r = s_update_ref("forced-update", ref, 1);
                strbuf_addf(display, "%c %-*s %-*s -> %s  (%s)",
                            r ? '!' : '+',
-                           TRANSPORT_SUMMARY_WIDTH, quickref,
+                           TRANSPORT_SUMMARY_WIDTH, quickref.buf,
                            REFCOL_WIDTH, remote, pretty_ref,
                            r ? _("unable to update local ref") : _("forced update"));
+               strbuf_release(&quickref);
                return r;
        } else {
                strbuf_addf(display, "! %-*s %-*s -> %s  %s",
@@ -578,7 +580,7 @@ static int iterate_ref_map(void *cb_data, unsigned char sha1[20])
        if (!ref)
                return -1; /* end of the list */
        *rm = ref->next;
-       hashcpy(sha1, ref->old_sha1);
+       hashcpy(sha1, ref->old_oid.hash);
        return 0;
 }
 
@@ -629,7 +631,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
                                continue;
                        }
 
-                       commit = lookup_commit_reference_gently(rm->old_sha1, 1);
+                       commit = lookup_commit_reference_gently(rm->old_oid.hash, 1);
                        if (!commit)
                                rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE;
 
@@ -637,10 +639,9 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
                                continue;
 
                        if (rm->peer_ref) {
-                               ref = xcalloc(1, sizeof(*ref) + strlen(rm->peer_ref->name) + 1);
-                               strcpy(ref->name, rm->peer_ref->name);
-                               hashcpy(ref->old_sha1, rm->peer_ref->old_sha1);
-                               hashcpy(ref->new_sha1, rm->old_sha1);
+                               ref = alloc_ref(rm->peer_ref->name);
+                               oidcpy(&ref->old_oid, &rm->peer_ref->old_oid);
+                               oidcpy(&ref->new_oid, &rm->old_oid);
                                ref->force = rm->peer_ref->force;
                        }
 
@@ -685,7 +686,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
                                /* fall-through */
                        case FETCH_HEAD_MERGE:
                                fprintf(fp, "%s\t%s\t%s",
-                                       sha1_to_hex(rm->old_sha1),
+                    &n