Merge branch 'ep/worktree-quiet-option'
authorJunio C Hamano <gitster@pobox.com>
Mon, 27 Aug 2018 21:33:42 +0000 (14:33 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 27 Aug 2018 21:33:42 +0000 (14:33 -0700)
"git worktree" command learned "--quiet" option to make it less
verbose.

* ep/worktree-quiet-option:
  worktree: add --quiet option

282 files changed:
.gitignore
Documentation/.gitignore
Documentation/Makefile
Documentation/RelNotes/2.19.0.txt
Documentation/config.txt
Documentation/doc-diff [new file with mode: 0755]
Documentation/fetch-options.txt
Documentation/git-branch.txt
Documentation/git-cat-file.txt
Documentation/git-config.txt
Documentation/git-range-diff.txt [new file with mode: 0644]
Documentation/git-repack.txt
Documentation/git-update-index.txt
Documentation/pull-fetch-param.txt
Documentation/technical/hash-function-transition.txt
Documentation/technical/partial-clone.txt
GIT-VERSION-GEN
Makefile
alloc.c
alloc.h
apply.c
apply.h
archive-tar.c
archive-zip.c
archive.c
archive.h
attr.c
attr.h
bisect.h
blame.c
blame.h
branch.h
builtin.h
builtin/add.c
builtin/am.c
builtin/apply.c
builtin/archive.c
builtin/blame.c
builtin/branch.c
builtin/cat-file.c
builtin/check-attr.c
builtin/checkout-index.c
builtin/checkout.c
builtin/clean.c
builtin/commit.c
builtin/diff-tree.c
builtin/difftool.c
builtin/grep.c
builtin/ls-files.c
builtin/pack-objects.c
builtin/prune-packed.c
builtin/pull.c
builtin/push.c
builtin/range-diff.c [new file with mode: 0644]
builtin/read-tree.c
builtin/repack.c
builtin/revert.c
builtin/rm.c
builtin/send-pack.c
builtin/shortlog.c
builtin/show-branch.c
builtin/submodule--helper.c
builtin/update-index.c
builtin/upload-archive.c
builtin/write-tree.c
bulk-checkin.h
cache-tree.c
cache-tree.h
cache.h
ci/run-build-and-tests.sh
color.c
color.h
column.h
command-list.txt
commit-graph.c
commit-graph.h
compat/mingw.c
compat/precompose_utf8.h
config.c
config.h
connected.h
contrib/completion/git-completion.bash
convert.c
convert.h
csum-file.h
diff-lib.c
diff.c
diff.h
diffcore.h
dir-iterator.h
dir.c
dir.h
entry.c
environment.c
fetch-negotiator.c
fetch-pack.c
fsck.h
fsmonitor.h
git-compat-util.h
git-instaweb.sh
git-mergetool.sh
git-submodule.sh
git.c
gpg-interface.c
gpg-interface.h
help.c
help.h
http-backend.c
khash.h
line-range.h
linear-assignment.c [new file with mode: 0644]
linear-assignment.h [new file with mode: 0644]
list-objects-filter.h
list-objects.h
ll-merge.c
ll-merge.h
mailinfo.h
mailmap.h
match-trees.c
merge-recursive.c
merge-recursive.h
notes-merge.h
notes-utils.h
notes.h
object-store.h
object.h
oidmap.h
pack-bitmap.h
pack-objects.c
pack-objects.h
packfile.c
packfile.h
parse-options.c
patch-ids.h
path.h
pathspec.c
pathspec.h
preload-index.c
pretty.h
range-diff.c [new file with mode: 0644]
range-diff.h [new file with mode: 0644]
reachable.h
read-cache.c
ref-filter.c
reflog-walk.h
refs.c
refs.h
remote-curl.c
remote.c
remote.h
repository.h
rerere.c
rerere.h
resolve-undo.c
resolve-undo.h
revision.c
revision.h
send-pack.h
sequencer.c
sequencer.h
sha1-file.c
sha1collisiondetection
sha1dc/sha1.c
shortlog.h
sideband.c
submodule.c
submodule.h
t/.gitattributes
t/README
t/chainlint.sed
t/chainlint/here-doc-close-subshell.expect [new file with mode: 0644]
t/chainlint/here-doc-close-subshell.test [new file with mode: 0644]
t/chainlint/here-doc-multi-line-command-subst.expect [new file with mode: 0644]
t/chainlint/here-doc-multi-line-command-subst.test [new file with mode: 0644]
t/chainlint/here-doc-multi-line-string.expect [new file with mode: 0644]
t/chainlint/here-doc-multi-line-string.test [new file with mode: 0644]
t/chainlint/here-doc.expect
t/chainlint/here-doc.test
t/chainlint/multi-line-nested-command-substitution.expect
t/chainlint/multi-line-nested-command-substitution.test
t/chainlint/multi-line-string.expect
t/chainlint/multi-line-string.test
t/chainlint/nested-here-doc.expect
t/chainlint/nested-here-doc.test
t/chainlint/subshell-here-doc.expect
t/chainlint/subshell-here-doc.test
t/chainlint/t7900-subtree.expect [new file with mode: 0644]
t/chainlint/t7900-subtree.test [new file with mode: 0644]
t/t0008-ignores.sh
t/t0030-stripspace.sh
t/t0060-path-utils.sh
t/t0300-credentials.sh
t/t0410-partial-clone.sh
t/t1006-cat-file.sh
t/t1011-read-tree-sparse-checkout.sh
t/t1015-read-index-unmerged.sh [new file with mode: 0755]
t/t1300-config.sh
t/t1306-xdg-files.sh
t/t1403-show-ref.sh
t/t1507-rev-parse-upstream.sh
t/t2024-checkout-dwim.sh
t/t2025-worktree-add.sh
t/t2202-add-addremove.sh
t/t3001-ls-files-others-exclude.sh
t/t3031-merge-criscross.sh
t/t3070-wildmatch.sh
t/t3200-branch.sh
t/t3201-branch-contains.sh
t/t3206-range-diff.sh [new file with mode: 0755]
t/t3206/history.export [new file with mode: 0644]
t/t3404-rebase-interactive.sh
t/t3418-rebase-continue.sh
t/t3430-rebase-merges.sh
t/t3510-cherry-pick-sequence.sh
t/t3600-rm.sh
t/t3700-add.sh
t/t3910-mac-os-precompose.sh
t/t4010-diff-pathspec.sh
t/t4015-diff-whitespace.sh
t/t4039-diff-assume-unchanged.sh
t/t4135-apply-weird-filenames.sh
t/t4150-am.sh
t/t4200-rerere.sh
t/t4202-log.sh
t/t4210-log-i18n.sh
t/t5310-pack-bitmaps.sh
t/t5313-pack-bounds-checks.sh
t/t5318-commit-graph.sh
t/t5409-colorize-remote-messages.sh [new file with mode: 0755]
t/t5504-fetch-receive-strict.sh
t/t5505-remote.sh
t/t5510-fetch.sh
t/t5512-ls-remote.sh
t/t5514-fetch-multiple.sh
t/t5516-fetch-push.sh
t/t5520-pull.sh
t/t5533-push-cas.sh
t/t5552-skipping-fetch-negotiator.sh
t/t5562-http-backend-content-length.sh [new file with mode: 0755]
t/t5562/invoke-with-content-length.pl [new file with mode: 0755]
t/t5612-clone-refspec.sh
t/t6000-rev-list-misc.sh
t/t6009-rev-list-parent.sh
t/t6018-rev-list-glob.sh
t/t6019-rev-list-ancestry-path.sh
t/t6020-merge-df.sh
t/t6022-merge-rename.sh
t/t6029-merge-subtree.sh
t/t6042-merge-rename-corner-cases.sh
t/t6060-merge-index.sh
t/t6300-for-each-ref.sh
t/t7004-tag.sh
t/t7006-pager.sh
t/t7030-verify-tag.sh
t/t7063-status-untracked-cache.sh
t/t7102-reset.sh
t/t7106-reset-unborn-branch.sh
t/t7401-submodule-summary.sh
t/t7406-submodule-update.sh
t/t7410-submodule-checkout-to.sh
t/t7502-commit.sh
t/t7610-mergetool.sh
t/t7810-grep.sh
t/t9001-send-email.sh
t/t9300-fast-import.sh
t/t9902-completion.sh
t/t9903-bash-prompt.sh
t/test-lib-functions.sh
t/test-lib.sh
tempfile.h
trailer.h
tree-walk.h
unpack-trees.c
unpack-trees.h
url.h
urlmatch.h
userdiff.c
utf8.h
worktree.h
ws.c
wt-status.c
xdiff/xdiffi.c

index 3524803..ffceea7 100644 (file)
 /git-pull
 /git-push
 /git-quiltimport
+/git-range-diff
 /git-read-tree
 /git-rebase
 /git-rebase--am
index c7096f1..3ef54e0 100644 (file)
@@ -12,3 +12,4 @@ cmds-*.txt
 mergetools-*.txt
 manpage-base-url.xsl
 SubmittingPatches.txt
+tmp-doc-diff/
index d079d7c..a42dcfc 100644 (file)
@@ -76,6 +76,7 @@ TECH_DOCS += technical/long-running-process-protocol
 TECH_DOCS += technical/pack-format
 TECH_DOCS += technical/pack-heuristics
 TECH_DOCS += technical/pack-protocol
+TECH_DOCS += technical/partial-clone
 TECH_DOCS += technical/protocol-capabilities
 TECH_DOCS += technical/protocol-common
 TECH_DOCS += technical/protocol-v2
index 5075bad..bcbfbc2 100644 (file)
@@ -65,6 +65,24 @@ UI, Workflows & Features
  * "git p4 submit" learns to ask its own pre-submit hook if it should
    continue with submitting.
 
+ * The test performed at the receiving end of "git push" to prevent
+   bad objects from entering repository can be customized via
+   receive.fsck.* configuration variables; we now have gained a
+   counterpart to do the same on the "git fetch" side, with
+   fetch.fsck.* configuration variables.
+
+ * "git pull --rebase=interactive" learned "i" as a short-hand for
+   "interactive".
+
+ * "git instaweb" has been adjusted to run better with newer Apache on
+   RedHat based distros.
+
+ * "git range-diff" is a reimplementation of "git tbdiff" that lets us
+   compare individual patches in two iterations of a topic.
+
+ * The sideband code learned to optionally paint selected keywords at
+   the beginning of incoming lines on the receiving end.
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -193,6 +211,46 @@ Performance, Internal Implementation, Development Support etc.
    failed tests.
    (merge aea8879a6a sg/travis-retrieve-trash-upon-failure later to maint).
 
+ * The parse-options machinery learned to refrain from enclosing
+   placeholder string inside a "<bra" and "ket>" pair automatically
+   without PARSE_OPT_LITERAL_ARGHELP.  Existing help text for option
+   arguments that are not formatted correctly have been identified and
+   fixed.
+   (merge 5f0df44cd7 rs/parse-opt-lithelp later to maint).
+
+ * Noiseword "extern" has been removed from function decls in the
+   header files.
+
+ * A few atoms like %(objecttype) and %(objectsize) in the format
+   specifier of "for-each-ref --format=<format>" can be filled without
+   getting the full contents of the object, but just with the object
+   header.  These cases have been optimized by calling
+   oid_object_info() API (instead of reading and inspecting the data).
+
+ * The end result of documentation update has been made to be
+   inspected more easily to help developers.
+
+ * The API to iterate over all objects learned to optionally list
+   objects in the order they appear in packfiles, which helps locality
+   of access if the caller accesses these objects while as objects are
+   enumerated.
+
+ * Improve built-in facility to catch broken &&-chain in the tests.
+
+ * The more library-ish parts of the codebase learned to work on the
+   in-core index-state instance that is passed in by their callers,
+   instead of always working on the singleton "the_index" instance.
+
+ * A test prerequisite defined by various test scripts with slightly
+   different semantics has been consolidated into a single copy and
+   made into a lazily defined one.
+   (merge 6ec633059a wc/make-funnynames-shared-lazy-prereq later to maint).
+
+ * After a partial clone, repeated fetches from promisor remote would
+   have accumulated many packfiles marked with .promisor bit without
+   getting them coalesced into fewer packfiles, hurting performance.
+   "git repack" now learned to repack them.
+
 
 Fixes since v2.18
 -----------------
@@ -399,6 +457,82 @@ Fixes since v2.18
    bit (and not materializing the file in the working tree).
    (merge 2b75fb601c en/merge-recursive-skip-fix later to maint).
 
+ * The "author-script" file "git rebase -i" creates got broken when
+   we started to move the command away from shell script, which is
+   getting fixed now.
+   (merge 5522bbac20 es/rebase-i-author-script-fix later to maint).
+
+ * The automatic tree-matching in "git merge -s subtree" was broken 5
+   years ago and nobody has noticed since then, which is now fixed.
+   (merge 2ec4150713 jk/merge-subtree-heuristics later to maint).
+
+ * "git fetch $there refs/heads/s" ought to fetch the tip of the
+   branch 's', but when "refs/heads/refs/heads/s", i.e. a branch whose
+   name is "refs/heads/s" exists at the same time, fetched that one
+   instead by mistake.  This has been corrected to honor the usual
+   disambiguation rules for abbreviated refnames.
+   (merge 60650a48c0 jt/refspec-dwim-precedence-fix later to maint).
+
+ * Futureproofing a helper function that can easily be misused.
+   (merge 65bb21e77e es/want-color-fd-defensive later to maint).
+
+ * The http-backend (used for smart-http transport) used to slurp the
+   whole input until EOF, without paying attention to CONTENT_LENGTH
+   that is supplied in the environment and instead expecting the Web
+   server to close the input stream.  This has been fixed.
+   (merge eebfe40962 mk/http-backend-content-length later to maint).
+
+ * "git merge --abort" etc. did not clean things up properly when
+   there were conflicted entries in the index in certain order that
+   are involved in D/F conflicts.  This has been corrected.
+   (merge ad3762042a en/abort-df-conflict-fixes later to maint).
+
+ * "git diff --indent-heuristic" had a bad corner case performance.
+   (merge 301ef85401 sb/indent-heuristic-optim later to maint).
+
+ * The "--exec" option to "git rebase --rebase-merges" placed the exec
+   commands at wrong places, which has been corrected.
+
+ * "git verify-tag" and "git verify-commit" have been taught to use
+   the exit status of underlying "gpg --verify" to signal bad or
+   untrusted signature they found.
+   (merge 4e5dc9ca17 jc/gpg-status later to maint).
+
+ * "git mergetool" stopped and gave an extra prompt to continue after
+   the last path has been handled, which did not make much sense.
+   (merge d651a54b8a ng/mergetool-lose-final-prompt later to maint).
+
+ * Among the three codepaths we use O_APPEND to open a file for
+   appending, one used for writing GIT_TRACE output requires O_APPEND
+   implementation that behaves sensibly when multiple processes are
+   writing to the same file.  POSIX emulation used in the Windows port
+   has been updated to improve in this area.
+   (merge d641097589 js/mingw-o-append later to maint).
+
+ * "git pull --rebase -v" in a repository with a submodule barfed as
+   an intermediate process did not understand what "-v(erbose)" flag
+   meant, which has been fixed.
+   (merge e84c3cf3dc sb/pull-rebase-submodule later to maint).
+
+ * Recent update to "git config" broke updating variable in a
+   subsection, which has been corrected.
+   (merge bff7df7a87 sb/config-write-fix later to maint).
+
+ * When "git rebase -i" is told to squash two or more commits into
+   one, it labeled the log message for each commit with its number.
+   It correctly called the first one "1st commit", but the next one
+   was "commit #1", which was off-by-one.  This has been corrected.
+   (merge dd2e36ebac pw/rebase-i-squash-number-fix later to maint).
+
+ * "git rebase -i", when a 'merge <branch>' insn in its todo list
+   fails, segfaulted, which has been (minimally) corrected.
+   (merge bc9238bb09 pw/rebase-i-merge-segv-fix later to maint).
+
+ * "git cherry-pick --quit" failed to remove CHERRY_PICK_HEAD even
+   though we won't be in a cherry-pick session after it returns, which
+   has been corrected.
+   (merge 3e7dd99208 nd/cherry-pick-quit-fix later to maint).
+
  * Code cleanup, docfix, build fix, etc.
    (merge aee9be2ebe sg/update-ref-stdin-cleanup later to maint).
    (merge 037714252f jc/clean-after-sanity-tests later to maint).
@@ -421,3 +555,13 @@ Fixes since v2.18
    (merge ffbd51cc60 nd/pack-objects-threading-doc later to maint).
    (merge e9dac7be60 es/mw-to-git-chain-fix later to maint).
    (merge fe583c6c7a rs/remote-mv-leakfix later to maint).
+   (merge 69885ab015 en/t3031-title-fix later to maint).
+   (merge 8578037bed nd/config-blame-sort later to maint).
+   (merge 8ad169c4ba hn/config-in-code-comment later to maint).
+   (merge b7446fcfdf ar/t4150-am-scissors-test-fix later to maint).
+   (merge a8132410ee js/typofixes later to maint).
+   (merge 388d0ff6e5 en/update-index-doc later to maint).
+   (merge e05aa688dd jc/update-index-doc later to maint).
+   (merge 10c600172c sg/t5310-empty-input-fix later to maint).
+   (merge 5641eb9465 jh/partial-clone-doc later to maint).
+   (merge 2711b1ad5e ab/submodule-relative-url-tests later to maint).
index fd8d27e..9f2deae 100644 (file)
@@ -462,10 +462,20 @@ core.untrackedCache::
        See linkgit:git-update-index[1]. `keep` by default.
 
 core.checkStat::
-       Determines which stat fields to match between the index
-       and work tree. The user can set this to 'default' or
-       'minimal'. Default (or explicitly 'default'), is to check
-       all fields, including the sub-second part of mtime and ctime.
+       When missing or is set to `default`, many fields in the stat
+       structure are checked to detect if a file has been modified
+       since Git looked at it.  When this configuration variable is
+       set to `minimal`, sub-second part of mtime and ctime, the
+       uid and gid of the owner of the file, the inode number (and
+       the device number, if Git was compiled to use it), are
+       excluded from the check among these fields, leaving only the
+       whole-second part of mtime (and ctime, if `core.trustCtime`
+       is set) and the filesize to be checked.
++
+There are implementations of Git that do not leave usable values in
+some fields (e.g. JGit); by excluding these fields from the
+comparison, the `minimal` mode may help interoperability when the
+same repository is used by these other systems at the same time.
 
 core.quotePath::
        Commands that output paths (e.g. 'ls-files', 'diff'), will
@@ -995,23 +1005,28 @@ apply.whitespace::
        Tells 'git apply' how to handle whitespaces, in the same way
        as the `--whitespace` option. See linkgit:git-apply[1].
 
-blame.showRoot::
-       Do not treat root commits as boundaries in linkgit:git-blame[1].
-       This option defaults to false.
-
 blame.blankBoundary::
        Show blank commit object name for boundary commits in
        linkgit:git-blame[1]. This option defaults to false.
 
-blame.showEmail::
-       Show the author email instead of author name in linkgit:git-blame[1].
-       This option defaults to false.
+blame.coloring::
+       This determines the coloring scheme to be applied to blame
+       output. It can be 'repeatedLines', 'highlightRecent',
+       or 'none' which is the default.
 
 blame.date::
        Specifies the format used to output dates in linkgit:git-blame[1].
        If unset the iso format is used. For supported values,
        see the discussion of the `--date` option at linkgit:git-log[1].
 
+blame.showEmail::
+       Show the author email instead of author name in linkgit:git-blame[1].
+       This option defaults to false.
+
+blame.showRoot::
+       Do not treat root commits as boundaries in linkgit:git-blame[1].
+       This option defaults to false.
+
 branch.autoSetupMerge::
        Tells 'git branch' and 'git checkout' to set up new branches
        so that linkgit:git-pull[1] will appropriately merge from the
@@ -1039,6 +1054,12 @@ branch.autoSetupRebase::
        branch to track another branch.
        This option defaults to never.
 
+branch.sort::
+       This variable controls the sort ordering of branches when displayed by
+       linkgit:git-branch[1]. Without the "--sort=<value>" option provided, the
+       value of this variable will be used as the default.
+       See linkgit:git-for-each-ref[1] field names for valid values.
+
 branch.<name>.remote::
        When on branch <name>, it tells 'git fetch' and 'git push'
        which remote to fetch from/push to.  The remote to push to
@@ -1149,6 +1170,28 @@ color.advice::
 color.advice.hint::
        Use customized color for hints.
 
+color.blame.highlightRecent::
+       This can be used to color the metadata of a blame line depending
+       on age of the line.
++
+This setting should be set to a comma-separated list of color and date settings,
+starting and ending with a color, the dates should be set from oldest to newest.
+The metadata will be colored given the colors if the the line was introduced
+before the given timestamp, overwriting older timestamped colors.
++
+Instead of an absolute timestamp relative timestamps work as well, e.g.
+2.weeks.ago is valid to address anything older than 2 weeks.
++
+It defaults to 'blue,12 month ago,white,1 month ago,red', which colors
+everything older than one year blue, recent changes between one month and
+one year old are kept white, and lines introduced within the last month are
+colored red.
+
+color.blame.repeatedLines::
+       Use the customized color for the part of git-blame output that
+       is repeated meta information per line (such as commit id,
+       author name, date and timezone). Defaults to cyan.
+
 color.branch::
        A boolean to enable/disable color in the output of
        linkgit:git-branch[1]. May be set to `always`,
@@ -1198,8 +1241,10 @@ color.diff.<slot>::
        (highlighting whitespace errors), `oldMoved` (deleted lines),
        `newMoved` (added lines), `oldMovedDimmed`, `oldMovedAlternative`,
        `oldMovedAlternativeDimmed`, `newMovedDimmed`, `newMovedAlternative`
-       and `newMovedAlternativeDimmed` (See the '<mode>'
-       setting of '--color-moved' in linkgit:git-diff[1] for details).
+       `newMovedAlternativeDimmed` (See the '<mode>'
+       setting of '--color-moved' in linkgit:git-diff[1] for details),
+       `contextDimmed`, `oldDimmed`, `newDimmed`, `contextBold`,
+       `oldBold`, and `newBold` (see linkgit:git-range-diff[1] for details).
 
 color.decorate.<slot>::
        Use customized color for 'git log --decorate' output.  `<slot>` is one
@@ -1268,6 +1313,18 @@ color.push::
 color.push.error::
        Use customized color for push errors.
 
+color.remote::
+       If set, keywords at the start of the line are highlighted. The
+       keywords are "error", "warning", "hint" and "success", and are
+       matched case-insensitively. May be set to `always`, `false` (or
+       `never`) or `auto` (or `true`). If unset, then the value of
+       `color.ui` is used (`auto` by default).
+
+color.remote.<slot>::
+       Use customized color for each remote keyword. `<slot>` may be
+       `hint`, `warning`, `success` or `error` which match the
+       corresponding keyword.
+
 color.showBranch::
        A boolean to enable/disable color in the output of
        linkgit:git-show-branch[1]. May be set to `always`,
@@ -1296,33 +1353,6 @@ color.status.<slot>::
        status short-format), or
        `unmerged` (files which have unmerged changes).
 
-color.blame.repeatedLines::
-       Use the customized color for the part of git-blame output that
-       is repeated meta information per line (such as commit id,
-       author name, date and timezone). Defaults to cyan.
-
-color.blame.highlightRecent::
-       This can be used to color the metadata of a blame line depending
-       on age of the line.
-+
-This setting should be set to a comma-separated list of color and date settings,
-starting and ending with a color, the dates should be set from oldest to newest.
-The metadata will be colored given the colors if the the line was introduced
-before the given timestamp, overwriting older timestamped colors.
-+
-Instead of an absolute timestamp relative timestamps work as well, e.g.
-2.weeks.ago is valid to address anything older than 2 weeks.
-+
-It defaults to 'blue,12 month ago,white,1 month ago,red', which colors
-everything older than one year blue, recent changes between one month and
-one year old are kept white, and lines introduced within the last month are
-colored red.
-
-blame.coloring::
-       This determines the coloring scheme to be applied to blame
-       output. It can be 'repeatedLines', 'highlightRecent',
-       or 'none' which is the default.
-
 color.transport::
        A boolean to enable/disable color when pushes are rejected. May be
        set to `always`, `false` (or `never`) or `auto` (or `true`), in which
@@ -1502,10 +1532,19 @@ fetch.recurseSubmodules::
 
 fetch.fsckObjects::
        If it is set to true, git-fetch-pack will check all fetched
-       objects. It will abort in the case of a malformed object or a
-       broken link. The result of an abort are only dangling objects.
-       Defaults to false. If not set, the value of `transfer.fsckObjects`
-       is used instead.
+       objects. See `transfer.fsckObjects` for what's
+       checked. Defaults to false. If not set, the value of
+       `transfer.fsckObjects` is used instead.
+
+fetch.fsck.<msg-id>::
+       Acts like `fsck.<msg-id>`, but is used by
+       linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See
+       the `fsck.<msg-id>` documentation for details.
+
+fetch.fsck.skipList::
+       Acts like `fsck.skipList`, but is used by
+       linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See
+       the `fsck.skipList` documentation for details.
 
 fetch.unpackLimit::
        If the number of objects fetched over the Git native
@@ -1541,9 +1580,12 @@ fetch.negotiationAlgorithm::
        sent when negotiating the contents of the packfile to be sent by the
        server. Set to "skipping" to use an algorithm that skips commits in an
        effort to converge faster, but may result in a larger-than-necessary
-       packfile; any other value instructs Git to use the default algorithm
+       packfile; The default is "default" which instructs Git to use the default algorithm
        that never skips commits (unless the server has acknowledged it or one
        of its descendants).
+       Unknown values will cause 'git fetch' to error out.
++
+See also the `--negotiation-tip` option for linkgit:git-fetch[1].
 
 format.attach::
        Enable multipart/mixed attachments as the default for
@@ -1644,15 +1686,42 @@ filter.<driver>.smudge::
        linkgit:gitattributes[5] for details.
 
 fsck.<msg-id>::
-       Allows overriding the message type (error, warn or ignore) of a
-       specific message ID such as `missingEmail`.
-+
-For convenience, fsck prefixes the error/warning with the message ID,
-e.g.  "missingEmail: invalid author/committer line - missing email" means
-that setting `fsck.missingEmail = ignore` will hide that issue.
-+
-This feature is intended to support working with legacy repositories
-which cannot be repaired without disruptive changes.
+       During fsck git may find issues with legacy data which
+       wouldn't be generated by current versions of git, and which
+       wouldn't be sent over the wire if `transfer.fsckObjects` was
+       set. This feature is intended to support working with legacy
+       repositories containing such data.
++
+Setting `fsck.<msg-id>` will be picked up by linkgit:git-fsck[1], but
+to accept pushes of such data set `receive.fsck.<msg-id>` instead, or
+to clone or fetch it set `fetch.fsck.<msg-id>`.
++
+The rest of the documentation discusses `fsck.*` for brevity, but the
+same applies for the corresponding `receive.fsck.*` and
+`fetch.<msg-id>.*`. variables.
++
+Unlike variables like `color.ui` and `core.editor` the
+`receive.fsck.<msg-id>` and `fetch.fsck.<msg-id>` variables will not
+fall back on the `fsck.<msg-id>` configuration if they aren't set. To
+uniformly configure the same fsck settings in different circumstances
+all three of them they must all set to the same values.
++
+When `fsck.<msg-id>` is set, errors can be switched to warnings and
+vice versa by configuring the `fsck.<msg-id>` setting where the
+`<msg-id>` is the fsck message ID and the value is one of `error`,
+`warn` or `ignore`. For convenience, fsck prefixes the error/warning
+with the message ID, e.g. "missingEmail: invalid author/committer line
+- missing email" means that setting `fsck.missingEmail = ignore` will
+hide that issue.
++
+In general, it is better to enumerate existing objects with problems
+with `fsck.skipList`, instead of listing the kind of breakages these
+problematic objects share to be ignored, as doing the latter will
+allow new instances of the same breakages go unnoticed.
++
+Setting an unknown `fsck.<msg-id>` value will cause fsck to die, but
+doing the same for `receive.fsck.<msg-id>` and `fetch.fsck.<msg-id>`
+will only cause git to warn.
 
 fsck.skipList::
        The path to a sorted list of object names (i.e. one SHA-1 per
@@ -1661,6 +1730,15 @@ fsck.skipList::
        should be accepted despite early commits containing errors that
        can be safely ignored such as invalid committer email addresses.
        Note: corrupt objects cannot be skipped with this setting.
++
+Like `fsck.<msg-id>` this variable has corresponding
+`receive.fsck.skipList` and `fetch.fsck.skipList` variants.
++
+Unlike variables like `color.ui` and `core.editor` the
+`receive.fsck.skipList` and `fetch.fsck.skipList` variables will not
+fall back on the `fsck.skipList` configuration if they aren't set. To
+uniformly configure the same fsck settings in different circumstances
+all three of them they must all set to the same values.
 
 gc.aggressiveDepth::
        The depth parameter used in the delta compression
@@ -2947,32 +3025,21 @@ receive.certNonceSlop::
 
 receive.fsckObjects::
        If it is set to true, git-receive-pack will check all received
-       objects. It will abort in the case of a malformed object or a
-       broken link. The result of an abort are only dangling objects.
-       Defaults to false. If not set, the value of `transfer.fsckObjects`
-       is used instead.
+       objects. See `transfer.fsckObjects` for what's checked.
+       Defaults to false. If not set, the value of
+       `transfer.fsckObjects` is used instead.
 
 receive.fsck.<msg-id>::
-       When `receive.fsckObjects` is set to true, errors can be switched
-       to warnings and vice versa by configuring the `receive.fsck.<msg-id>`
-       setting where the `<msg-id>` is the fsck message ID and the value
-       is one of `error`, `warn` or `ignore`. For convenience, fsck prefixes
-       the error/warning with the message ID, e.g. "missingEmail: invalid
-       author/committer line - missing email" means that setting
-       `receive.fsck.missingEmail = ignore` will hide that issue.
-+
-This feature is intended to support working with legacy repositories
-which would not pass pushing when `receive.fsckObjects = true`, allowing
-the host to accept repositories with certain known issues but still catch
-other issues.
+       Acts like `fsck.<msg-id>`, but is used by
+       linkgit:git-receive-pack[1] instead of
+       linkgit:git-fsck[1]. See the `fsck.<msg-id>` documentation for
+       details.
 
 receive.fsck.skipList::
-       The path to a sorted list of object names (i.e. one SHA-1 per
-       line) that are known to be broken in a non-fatal way and should
-       be ignored. This feature is useful when an established project
-       should be accepted despite early commits containing errors that
-       can be safely ignored such as invalid committer email addresses.
-       Note: corrupt objects cannot be skipped with this setting.
+       Acts like `fsck.skipList`, but is used by
+       linkgit:git-receive-pack[1] instead of
+       linkgit:git-fsck[1]. See the `fsck.skipList` documentation for
+       details.
 
 receive.keepAlive::
        After receiving the pack from the client, `receive-pack` may
@@ -3447,6 +3514,40 @@ transfer.fsckObjects::
        When `fetch.fsckObjects` or `receive.fsckObjects` are
        not set, the value of this variable is used instead.
        Defaults to false.
++
+When set, the fetch or receive will abort in the case of a malformed
+object or a link to a nonexistent object. In addition, various other
+issues are checked for, including legacy issues (see `fsck.<msg-id>`),
+and potential security issues like the existence of a `.GIT` directory
+or a malicious `.gitmodules` file (see the release notes for v2.2.1
+and v2.17.1 for details). Other sanity and security checks may be
+added in future releases.
++
+On the receiving side, failing fsckObjects will make those objects
+unreachable, see "QUARANTINE ENVIRONMENT" in
+linkgit:git-receive-pack[1]. On the fetch side, malformed objects will
+instead be left unreferenced in the repository.
++
+Due to the non-quarantine nature of the `fetch.fsckObjects`
+implementation it can not be relied upon to leave the object store
+clean like `receive.fsckObjects` can.
++
+As objects are unpacked they're written to the object store, so there
+can be cases where malicious objects get introduced even though the
+"fetch" failed, only to have a subsequent "fetch" succeed because only
+new incoming objects are checked, not those that have already been
+written to the object store. That difference in behavior should not be
+relied upon. In the future, such objects may be quarantined for
+"fetch" as well.
++
+For now, the paranoid need to find some way to emulate the quarantine
+environment if they'd like the same protection as "push". E.g. in the
+case of an internal mirror do the mirroring in two steps, one to fetch
+the untrusted objects, and then do a second "push" (which will use the
+quarantine) to another internal repo, and have internal clients
+consume this pushed-to repository, or embargo internal fetches and
+only allow them once a full "fsck" has run (and no new fetches have
+happened in the meantime).
 
 transfer.hideRefs::
        String(s) `receive-pack` and `upload-pack` use to decide which
diff --git a/Documentation/doc-diff b/Documentation/doc-diff
new file mode 100755 (executable)
index 0000000..f483fe4
--- /dev/null
@@ -0,0 +1,109 @@
+#!/bin/sh
+
+OPTIONS_SPEC="\
+doc-diff [options] <from> <to> [-- <diff-options>]
+--
+j=n    parallel argument to pass to make
+f      force rebuild; do not rely on cached results
+"
+SUBDIRECTORY_OK=1
+. "$(git --exec-path)/git-sh-setup"
+
+parallel=
+force=
+while test $# -gt 0
+do
+       case "$1" in
+       -j)
+               parallel=$2; shift ;;
+       -f)
+               force=t ;;
+       --)
+               shift; break ;;
+       *)
+               usage ;;
+       esac
+       shift
+done
+
+if test -z "$parallel"
+then
+       parallel=$(getconf _NPROCESSORS_ONLN 2>/dev/null)
+       if test $? != 0 || test -z "$parallel"
+       then
+               parallel=1
+       fi
+fi
+
+test $# -gt 1 || usage
+from=$1; shift
+to=$1; shift
+
+from_oid=$(git rev-parse --verify "$from") || exit 1
+to_oid=$(git rev-parse --verify "$to") || exit 1
+
+cd_to_toplevel
+tmp=Documentation/tmp-doc-diff
+
+if test -n "$force"
+then
+       rm -rf "$tmp"
+fi
+
+# We'll do both builds in a single worktree, which lets "make" reuse
+# results that don't differ between the two trees.
+if ! test -d "$tmp/worktree"
+then
+       git worktree add --detach "$tmp/worktree" "$from" &&
+       dots=$(echo "$tmp/worktree" | sed 's#[^/]*#..#g') &&
+       ln -s "$dots/config.mak" "$tmp/worktree/config.mak"
+fi
+
+# generate_render_makefile <srcdir> <dstdir>
+generate_render_makefile () {
+       find "$1" -type f |
+       while read src
+       do
+               dst=$2/${src#$1/}
+               printf 'all:: %s\n' "$dst"
+               printf '%s: %s\n' "$dst" "$src"
+               printf '\t@echo >&2 "  RENDER $(notdir $@)" && \\\n'
+               printf '\tmkdir -p $(dir $@) && \\\n'
+               printf '\tMANWIDTH=80 man -l $< >$@+ && \\\n'
+               printf '\tmv $@+ $@\n'
+       done
+}
+
+# render_tree <dirname> <committish>
+render_tree () {
+       # Skip install-man entirely if we already have an installed directory.
+       # We can't rely on make here, since "install-man" unconditionally
+       # copies the files (spending effort, but also updating timestamps that
+       # we then can't rely on during the render step). We use "mv" to make
+       # sure we don't get confused by a previous run that failed partway
+       # through.
+       if ! test -d "$tmp/installed/$1"
+       then
+               git -C "$tmp/worktree" checkout "$2" &&
+               make -j$parallel -C "$tmp/worktree" \
+                       GIT_VERSION=omitted \
+                       SOURCE_DATE_EPOCH=0 \
+                       DESTDIR="$PWD/$tmp/installed/$1+" \
+                       install-man &&
+               mv "$tmp/installed/$1+" "$tmp/installed/$1"
+       fi &&
+
+       # As with "installed" above, we skip the render if it's already been
+       # done.  So using make here is primarily just about running in
+       # parallel.
+       if ! test -d "$tmp/rendered/$1"
+       then
+               generate_render_makefile "$tmp/installed/$1" "$tmp/rendered/$1+" |
+               make -j$parallel -f - &&
+               mv "$tmp/rendered/$1+" "$tmp/rendered/$1"
+       fi
+}
+
+render_tree $from_oid "$from" &&
+render_tree $to_oid "$to" &&
+git -C $tmp/rendered diff --no-index "$@" $from_oid $to_oid
index 2d09f87..8bc36af 100644 (file)
@@ -57,6 +57,9 @@ commits reachable from any of the given commits.
 The argument to this option may be a glob on ref names, a ref, or the (possibly
 abbreviated) SHA-1 of a commit. Specifying a glob is equivalent to specifying
 this option multiple times, one for each matching ref name.
++
+See also the `fetch.negotiationAlgorithm` configuration variable
+documented in linkgit:git-config[1].
 
 ifndef::git-pull[]
 --dry-run::
index 1072ca0..9767b2b 100644 (file)
@@ -268,10 +268,11 @@ start-point is either a local or remote-tracking branch.
        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
+       for-each-ref`. Sort order defaults to the value configured for the
+       `branch.sort` variable if exists, or 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.
+       finally remote-tracking branches. See linkgit:git-config[1].
 
 
 --points-at <object>::
index f90f09b..7401333 100644 (file)
@@ -104,6 +104,16 @@ OPTIONS
        buffering; this is much more efficient when invoking
        `--batch-check` on a large number of objects.
 
+--unordered::
+       When `--batch-all-objects` is in use, visit objects in an
+       order which may be more efficient for accessing the object
+       contents than hash order. The exact details of the order are
+       unspecified, but if you do not require a specific order, this
+       should generally result in faster output, especially with
+       `--batch`.  Note that `cat-file` will still show each object
+       only once, even if it is stored multiple times in the
+       repository.
+
 --allow-unknown-type::
        Allow -s or -t to query broken/corrupt objects of unknown type.
 
index 18ddc78..8e24043 100644 (file)
@@ -453,6 +453,27 @@ http.sslverify false
 
 include::config.txt[]
 
+BUGS
+----
+When using the deprecated `[section.subsection]` syntax, changing a value
+will result in adding a multi-line key instead of a change, if the subsection
+is given with at least one uppercase character. For example when the config
+looks like
+
+--------
+  [section.subsection]
+    key = value1
+--------
+
+and running `git config section.Subsection.key value2` will result in
+
+--------
+  [section.subsection]
+    key = value1
+    key = value2
+--------
+
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-range-diff.txt b/Documentation/git-range-diff.txt
new file mode 100644 (file)
index 0000000..f693930
--- /dev/null
@@ -0,0 +1,252 @@
+git-range-diff(1)
+=================
+
+NAME
+----
+git-range-diff - Compare two commit ranges (e.g. two versions of a branch)
+
+SYNOPSIS
+--------
+[verse]
+'git range-diff' [--color=[<when>]] [--no-color] [<diff-options>]
+       [--no-dual-color] [--creation-factor=<factor>]
+       ( <range1> <range2> | <rev1>...<rev2> | <base> <rev1> <rev2> )
+
+DESCRIPTION
+-----------
+
+This command shows the differences between two versions of a patch
+series, or more generally, two commit ranges (ignoring merge commits).
+
+To that end, it first finds pairs of commits from both commit ranges
+that correspond with each other. Two commits are said to correspond when
+the diff between their patches (i.e. the author information, the commit
+message and the commit diff) is reasonably small compared to the
+patches' size. See ``Algorithm`` below for details.
+
+Finally, the list of matching commits is shown in the order of the
+second commit range, with unmatched commits being inserted just after
+all of their ancestors have been shown.
+
+
+OPTIONS
+-------
+--no-dual-color::
+       When the commit diffs differ, `git range-diff` recreates the
+       original diffs' coloring, and adds outer -/+ diff markers with
+       the *background* being red/green to make it easier to see e.g.
+       when there was a change in what exact lines were added.
++
+Additionally, the commit diff lines that are only present in the first commit
+range are shown "dimmed" (this can be overridden using the `color.diff.<slot>`
+config setting where `<slot>` is one of `contextDimmed`, `oldDimmed` and
+`newDimmed`), and the commit diff lines that are only present in the second
+commit range are shown in bold (which can be overridden using the config
+settings `color.diff.<slot>` with `<slot>` being one of `contextBold`,
+`oldBold` or `newBold`).
++
+This is known to `range-diff` as "dual coloring". Use `--no-dual-color`
+to revert to color all lines according to the outer diff markers
+(and completely ignore the inner diff when it comes to color).
+
+--creation-factor=<percent>::
+       Set the creation/deletion cost fudge factor to `<percent>`.
+       Defaults to 60. Try a larger value if `git range-diff` erroneously
+       considers a large change a total rewrite (deletion of one commit
+       and addition of another), and a smaller one in the reverse case.
+       See the ``Algorithm`` section below for an explanation why this is
+       needed.
+
+<range1> <range2>::
+       Compare the commits specified by the two ranges, where
+       `<range1>` is considered an older version of `<range2>`.
+
+<rev1>...<rev2>::
+       Equivalent to passing `<rev2>..<rev1>` and `<rev1>..<rev2>`.
+
+<base> <rev1> <rev2>::
+       Equivalent to passing `<base>..<rev1>` and `<base>..<rev2>`.
+       Note that `<base>` does not need to be the exact branch point
+       of the branches. Example: after rebasing a branch `my-topic`,
+       `git range-diff my-topic@{u} my-topic@{1} my-topic` would
+       show the differences introduced by the rebase.
+
+`git range-diff` also accepts the regular diff options (see
+linkgit:git-diff[1]), most notably the `--color=[<when>]` and
+`--no-color` options. These options are used when generating the "diff
+between patches", i.e. to compare the author, commit message and diff of
+corresponding old/new commits. There is currently no means to tweak the
+diff options passed to `git log` when generating those patches.
+
+
+CONFIGURATION
+-------------
+This command uses the `diff.color.*` and `pager.range-diff` settings
+(the latter is on by default).
+See linkgit:git-config[1].
+
+
+EXAMPLES
+--------
+
+When a rebase required merge conflicts to be resolved, compare the changes
+introduced by the rebase directly afterwards using:
+
+------------
+$ git range-diff @{u} @{1} @
+------------
+
+
+A typical output of `git range-diff` would look like this:
+
+------------
+-:  ------- > 1:  0ddba11 Prepare for the inevitable!
+1:  c0debee = 2:  cab005e Add a helpful message at the start
+2:  f00dbal ! 3:  decafe1 Describe a bug
+    @@ -1,3 +1,3 @@
+     Author: A U Thor <author@example.com>
+
+    -TODO: Describe a bug
+    +Describe a bug
+    @@ -324,5 +324,6
+      This is expected.
+
+    -+What is unexpected is that it will also crash.
+    ++Unexpectedly, it also crashes. This is a bug, and the jury is
+    ++still out there how to fix it best. See ticket #314 for details.
+
+      Contact
+3:  bedead < -:  ------- TO-UNDO
+------------
+
+In this example, there are 3 old and 3 new commits, where the developer
+removed the 3rd, added a new one before the first two, and modified the
+commit message of the 2nd commit as well its diff.
+
+When the output goes to a terminal, it is color-coded by default, just
+like regular `git diff`'s output. In addition, the first line (adding a
+commit) is green, the last line (deleting a commit) is red, the second
+line (with a perfect match) is yellow like the commit header of `git
+show`'s output, and the third line colors the old commit red, the new
+one green and the rest like `git show`'s commit header.
+
+A naive color-coded diff of diffs is actually a bit hard to read,
+though, as it colors the entire lines red or green. The line that added
+"What is unexpected" in the old commit, for example, is completely red,
+even if the intent of the old commit was to add something.
+
+To help with that, `range` uses the `--dual-color` mode by default. In
+this mode, the diff of diffs will retain the original diff colors, and
+prefix the lines with -/+ markers that have their *background* red or
+green, to make it more obvious that they describe how the diff itself
+changed.
+
+
+Algorithm
+---------
+
+The general idea is this: we generate a cost matrix between the commits
+in both commit ranges, then solve the least-cost assignment.
+
+The cost matrix is populated thusly: for each pair of commits, both
+diffs are generated and the "diff of diffs" is generated, with 3 context
+lines, then the number of lines in that diff is used as cost.
+
+To avoid false positives (e.g. when a patch has been removed, and an
+unrelated patch has been added between two iterations of the same patch
+series), the cost matrix is extended to allow for that, by adding
+fixed-cost entries for wholesale deletes/adds.
+
+Example: Let commits `1--2` be the first iteration of a patch series and
+`A--C` the second iteration. Let's assume that `A` is a cherry-pick of
+`2,` and `C` is a cherry-pick of `1` but with a small modification (say,
+a fixed typo). Visualize the commits as a bipartite graph:
+
+------------
+    1            A
+
+    2            B
+
+                C
+------------
+
+We are looking for a "best" explanation of the new series in terms of
+the old one. We can represent an "explanation" as an edge in the graph:
+
+
+------------
+    1            A
+              /
+    2 --------'  B
+
+                C
+------------
+
+This explanation comes for "free" because there was no change. Similarly
+`C` could be explained using `1`, but that comes at some cost c>0
+because of the modification:
+
+------------
+    1 ----.      A
+         |    /
+    2 ----+---'  B
+         |
+         `----- C
+         c>0
+------------
+
+In mathematical terms, what we are looking for is some sort of a minimum
+cost bipartite matching; `1` is matched to `C` at some cost, etc. The
+underlying graph is in fact a complete bipartite graph; the cost we
+associate with every edge is the size of the diff between the two
+commits' patches. To explain also new commits, we introduce dummy nodes
+on both sides:
+
+------------
+    1 ----.      A
+         |    /
+    2 ----+---'  B
+         |
+    o     `----- C
+         c>0
+    o            o
+
+    o            o
+------------
+
+The cost of an edge `o--C` is the size of `C`'s diff, modified by a
+fudge factor that should be smaller than 100%. The cost of an edge
+`o--o` is free. The fudge factor is necessary because even if `1` and
+`C` have nothing in common, they may still share a few empty lines and
+such, possibly making the assignment `1--C`, `o--o` slightly cheaper
+than `1--o`, `o--C` even if `1` and `C` have nothing in common. With the
+fudge factor we require a much larger common part to consider patches as
+corresponding.
+
+The overall time needed to compute this algorithm is the time needed to
+compute n+m commit diffs and then n*m diffs of patches, plus the time
+needed to compute the least-cost assigment between n and m diffs. Git
+uses an implementation of the Jonker-Volgenant algorithm to solve the
+assignment problem, which has cubic runtime complexity. The matching
+found in this case will look like this:
+
+------------
+    1 ----.      A
+         |    /
+    2 ----+---'  B
+       .--+-----'
+    o -'  `----- C
+         c>0
+    o ---------- o
+
+    o ---------- o
+------------
+
+
+SEE ALSO
+--------
+linkgit:git-log[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite
index d90e790..d056250 100644 (file)
@@ -40,6 +40,11 @@ OPTIONS
 Note that users fetching over dumb protocols will have to fetch the
 whole new pack in order to get any contained object, no matter how many
 other objects in that pack they already have locally.
++
+Promisor packfiles are repacked separately: if there are packfiles that
+have an associated ".promisor" file, these packfiles will be repacked
+into another separate pack, and an empty ".promisor" file corresponding
+to the new separate pack will be written.
 
 -A::
        Same as `-a`, unless `-d` is used.  Then any unreachable
index 4e8e762..1c4d146 100644 (file)
@@ -245,10 +245,10 @@ USING --CACHEINFO OR --INFO-ONLY
 current working directory.  This is useful for minimum-checkout
 merging.
 
-To pretend you have a file with mode and sha1 at path, say:
+To pretend you have a file at path with mode and sha1, say:
 
 ----------------
-$ git update-index --cacheinfo <mode>,<sha1>,<path>
+$ git update-index --add --cacheinfo <mode>,<sha1>,<path>
 ----------------
 
 `--info-only` is used to register files without placing them in the object
@@ -268,23 +268,20 @@ USING --INDEX-INFO
 multiple entry definitions from the standard input, and designed
 specifically for scripts.  It can take inputs of three formats:
 
-    . mode         SP sha1          TAB path
-+
-The first format is what "git-apply --index-info"
-reports, and used to reconstruct a partial tree
-that is used for phony merge base tree when falling
-back on 3-way merge.
-
     . mode SP type SP sha1          TAB path
 +
-The second format is to stuff 'git ls-tree' output
-into the index file.
+This format is to stuff `git ls-tree` output into the index.
 
     . mode         SP sha1 SP stage TAB path
 +
 This format is to put higher order stages into the
 index file and matches 'git ls-files --stage' output.
 
+    . mode         SP sha1          TAB path
++
+This format is no longer produced by any Git command, but is
+and will continue to be supported by `update-index --index-info`.
+
 To place a higher stage entry to the index, the path should
 first be removed by feeding a mode=0 entry for the path, and
 then feeding necessary input lines in the third format.
index c579793..f1fb08d 100644 (file)
@@ -33,7 +33,7 @@ name.
 it requests fetching everything up to the given tag.
 +
 The remote ref that matches <src>
-is fetched, and if <dst> is not empty string, the local
+is fetched, and if <dst> is not an empty string, the local
 ref that matches it is fast-forwarded using <src>.
 If the optional plus `+` is used, the local ref
 is updated even if it does not result in a fast-forward
index 4ab6cd1..bc2ace2 100644 (file)
@@ -59,14 +59,11 @@ that are believed to be cryptographically secure.
 
 Goals
 -----
-Where NewHash is a strong 256-bit hash function to replace SHA-1 (see
-"Selection of a New Hash", below):
-
-1. The transition to NewHash can be done one local repository at a time.
+1. The transition to SHA-256 can be done one local repository at a time.
    a. Requiring no action by any other party.
-   b. A NewHash repository can communicate with SHA-1 Git servers
+   b. A SHA-256 repository can communicate with SHA-1 Git servers
       (push/fetch).
-   c. Users can use SHA-1 and NewHash identifiers for objects
+   c. Users can use SHA-1 and SHA-256 identifiers for objects
       interchangeably (see "Object names on the command line", below).
    d. New signed objects make use of a stronger hash function than
       SHA-1 for their security guarantees.
@@ -79,7 +76,7 @@ Where NewHash is a strong 256-bit hash function to replace SHA-1 (see
 
 Non-Goals
 ---------
-1. Add NewHash support to Git protocol. This is valuable and the
+1. Add SHA-256 support to Git protocol. This is valuable and the
    logical next step but it is out of scope for this initial design.
 2. Transparently improving the security of existing SHA-1 signed
    objects.
@@ -87,26 +84,26 @@ Non-Goals
    repository.
 4. Taking the opportunity to fix other bugs in Git's formats and
    protocols.
-5. Shallow clones and fetches into a NewHash repository. (This will
-   change when we add NewHash support to Git protocol.)
-6. Skip fetching some submodules of a project into a NewHash
-   repository. (This also depends on NewHash support in Git
+5. Shallow clones and fetches into a SHA-256 repository. (This will
+   change when we add SHA-256 support to Git protocol.)
+6. Skip fetching some submodules of a project into a SHA-256
+   repository. (This also depends on SHA-256 support in Git
    protocol.)
 
 Overview
 --------
 We introduce a new repository format extension. Repositories with this
-extension enabled use NewHash instead of SHA-1 to name their objects.
+extension enabled use SHA-256 instead of SHA-1 to name their objects.
 This affects both object names and object content --- both the names
 of objects and all references to other objects within an object are
 switched to the new hash function.
 
-NewHash repositories cannot be read by older versions of Git.
+SHA-256 repositories cannot be read by older versions of Git.
 
-Alongside the packfile, a NewHash repository stores a bidirectional
-mapping between NewHash and SHA-1 object names. The mapping is generated
+Alongside the packfile, a SHA-256 repository stores a bidirectional
+mapping between SHA-256 and SHA-1 object names. The mapping is generated
 locally and can be verified using "git fsck". Object lookups use this
-mapping to allow naming objects using either their SHA-1 and NewHash names
+mapping to allow naming objects using either their SHA-1 and SHA-256 names
 interchangeably.
 
 "git cat-file" and "git hash-object" gain options to display an object
@@ -116,7 +113,7 @@ object database so that they can be named using the appropriate name
 (using the bidirectional hash mapping).
 
 Fetches from a SHA-1 based server convert the fetched objects into
-NewHash form and record the mapping in the bidirectional mapping table
+SHA-256 form and record the mapping in the bidirectional mapping table
 (see below for details). Pushes to a SHA-1 based server convert the
 objects being pushed into sha1 form so the server does not have to be
 aware of the hash function the client is using.
@@ -125,19 +122,19 @@ Detailed Design
 ---------------
 Repository format extension
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-A NewHash repository uses repository format version `1` (see
+A SHA-256 repository uses repository format version `1` (see
 Documentation/technical/repository-version.txt) with extensions
 `objectFormat` and `compatObjectFormat`:
 
        [core]
                repositoryFormatVersion = 1
        [extensions]
-               objectFormat = newhash
+               objectFormat = sha256
                compatObjectFormat = sha1
 
 The combination of setting `core.repositoryFormatVersion=1` and
 populating `extensions.*` ensures that all versions of Git later than
-`v0.99.9l` will die instead of trying to operate on the NewHash
+`v0.99.9l` will die instead of trying to operate on the SHA-256
 repository, instead producing an error message.
 
        # Between v0.99.9l and v2.7.0
@@ -155,36 +152,36 @@ repository extensions.
 Object names
 ~~~~~~~~~~~~
 Objects can be named by their 40 hexadecimal digit sha1-name or 64
-hexadecimal digit newhash-name, plus names derived from those (see
+hexadecimal digit sha256-name, plus names derived from those (see
 gitrevisions(7)).
 
 The sha1-name of an object is the SHA-1 of the concatenation of its
 type, length, a nul byte, and the object's sha1-content. This is the
 traditional <sha1> used in Git to name objects.
 
-The newhash-name of an object is the NewHash of the concatenation of its
-type, length, a nul byte, and the object's newhash-content.
+The sha256-name of an object is the SHA-256 of the concatenation of its
+type, length, a nul byte, and the object's sha256-content.
 
 Object format
 ~~~~~~~~~~~~~
 The content as a byte sequence of a tag, commit, or tree object named
-by sha1 and newhash differ because an object named by newhash-name refers to
-other objects by their newhash-names and an object named by sha1-name
+by sha1 and sha256 differ because an object named by sha256-name refers to
+other objects by their sha256-names and an object named by sha1-name
 refers to other objects by their sha1-names.
 
-The newhash-content of an object is the same as its sha1-content, except
-that objects referenced by the object are named using their newhash-names
+The sha256-content of an object is the same as its sha1-content, except
+that objects referenced by the object are named using their sha256-names
 instead of sha1-names. Because a blob object does not refer to any
-other object, its sha1-content and newhash-content are the same.
+other object, its sha1-content and sha256-content are the same.
 
-The format allows round-trip conversion between newhash-content and
+The format allows round-trip conversion between sha256-content and
 sha1-content.
 
 Object storage
 ~~~~~~~~~~~~~~
 Loose objects use zlib compression and packed objects use the packed
 format described in Documentation/technical/pack-format.txt, just like
-today. The content that is compressed and stored uses newhash-content
+today. The content that is compressed and stored uses sha256-content
 instead of sha1-content.
 
 Pack index
@@ -255,10 +252,10 @@ network byte order):
   up to and not including the table of CRC32 values.
 - Zero or more NUL bytes.
 - The trailer consists of the following:
-  - A copy of the 20-byte NewHash checksum at the end of the
+  - A copy of the 20-byte SHA-256 checksum at the end of the
     corresponding packfile.
 
-  - 20-byte NewHash checksum of all of the above.
+  - 20-byte SHA-256 checksum of all of the above.
 
 Loose object index
 ~~~~~~~~~~~~~~~~~~
@@ -266,7 +263,7 @@ A new file $GIT_OBJECT_DIR/loose-object-idx contains information about
 all loose objects. Its format is
 
   # loose-object-idx
-  (newhash-name SP sha1-name LF)*
+  (sha256-name SP sha1-name LF)*
 
 where the object names are in hexadecimal format. The file is not
 sorted.
@@ -292,8 +289,8 @@ To remove entries (e.g. in "git pack-refs" or "git-prune"):
 Translation table
 ~~~~~~~~~~~~~~~~~
 The index files support a bidirectional mapping between sha1-names
-and newhash-names. The lookup proceeds similarly to ordinary object
-lookups. For example, to convert a sha1-name to a newhash-name:
+and sha256-names. The lookup proceeds similarly to ordinary object
+lookups. For example, to convert a sha1-name to a sha256-name:
 
  1. Look for the object in idx files. If a match is present in the
     idx's sorted list of truncated sha1-names, then:
@@ -301,8 +298,8 @@ lookups. For example, to convert a sha1-name to a newhash-name:
        name order mapping.
     b. Read the corresponding entry in the full sha1-name table to
        verify we found the right object. If it is, then
-    c. Read the corresponding entry in the full newhash-name table.
-       That is the object's newhash-name.
+    c. Read the corresponding entry in the full sha256-name table.
+       That is the object's sha256-name.
  2. Check for a loose object. Read lines from loose-object-idx until
     we find a match.
 
@@ -318,25 +315,25 @@ for all objects in the object store.
 
 Reading an object's sha1-content
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The sha1-content of an object can be read by converting all newhash-names
-its newhash-content references to sha1-names using the translation table.
+The sha1-content of an object can be read by converting all sha256-names
+its sha256-content references to sha1-names using the translation table.
 
 Fetch
 ~~~~~
 Fetching from a SHA-1 based server requires translating between SHA-1
-and NewHash based representations on the fly.
+and SHA-256 based representations on the fly.
 
 SHA-1s named in the ref advertisement that are present on the client
-can be translated to NewHash and looked up as local objects using the
+can be translated to SHA-256 and looked up as local objects using the
 translation table.
 
 Negotiation proceeds as today. Any "have"s generated locally are
 converted to SHA-1 before being sent to the server, and SHA-1s
-mentioned by the server are converted to NewHash when looking them up
+mentioned by the server are converted to SHA-256 when looking them up
 locally.
 
 After negotiation, the server sends a packfile containing the
-requested objects. We convert the packfile to NewHash format using
+requested objects. We convert the packfile to SHA-256 format using
 the following steps:
 
 1. index-pack: inflate each object in the packfile and compute its
@@ -351,12 +348,12 @@ the following steps:
    (This list only contains objects reachable from the "wants". If the
    pack from the server contained additional extraneous objects, then
    they will be discarded.)
-3. convert to newhash: open a new (newhash) packfile. Read the topologically
+3. convert to sha256: open a new (sha256) packfile. Read the topologically
    sorted list just generated. For each object, inflate its
-   sha1-content, convert to newhash-content, and write it to the newhash
-   pack. Record the new sha1<->newhash mapping entry for use in the idx.
+   sha1-content, convert to sha256-content, and write it to the sha256
+   pack. Record the new sha1<->sha256 mapping entry for use in the idx.
 4. sort: reorder entries in the new pack to match the order of objects
-   in the pack the server generated and include blobs. Write a newhash idx
+   in the pack the server generated and include blobs. Write a sha256 idx
    file
 5. clean up: remove the SHA-1 based pack file, index, and
    topologically sorted list obtained from the server in steps 1
@@ -388,16 +385,16 @@ send-pack.
 
 Signed Commits
 ~~~~~~~~~~~~~~
-We add a new field "gpgsig-newhash" to the commit object format to allow
+We add a new field "gpgsig-sha256" to the commit object format to allow
 signing commits without relying on SHA-1. It is similar to the
-existing "gpgsig" field. Its signed payload is the newhash-content of the
-commit object with any "gpgsig" and "gpgsig-newhash" fields removed.
+existing "gpgsig" field. Its signed payload is the sha256-content of the
+commit object with any "gpgsig" and "gpgsig-sha256" fields removed.
 
 This means commits can be signed
 1. using SHA-1 only, as in existing signed commit objects
-2. using both SHA-1 and NewHash, by using both gpgsig-newhash and gpgsig
+2. using both SHA-1 and SHA-256, by using both gpgsig-sha256 and gpgsig
    fields.
-3. using only NewHash, by only using the gpgsig-newhash field.
+3. using only SHA-256, by only using the gpgsig-sha256 field.
 
 Old versions of "git verify-commit" can verify the gpgsig signature in
 cases (1) and (2) without modifications and view case (3) as an
@@ -405,24 +402,24 @@ ordinary unsigned commit.
 
 Signed Tags
 ~~~~~~~~~~~
-We add a new field "gpgsig-newhash" to the tag object format to allow
+We add a new field "gpgsig-sha256" to the tag object format to allow
 signing tags without relying on SHA-1. Its signed payload is the
-newhash-content of the tag with its gpgsig-newhash field and "-----BEGIN PGP
+sha256-content of the tag with its gpgsig-sha256 field and "-----BEGIN PGP
 SIGNATURE-----" delimited in-body signature removed.
 
 This means tags can be signed
 1. using SHA-1 only, as in existing signed tag objects
-2. using both SHA-1 and NewHash, by using gpgsig-newhash and an in-body
+2. using both SHA-1 and SHA-256, by using gpgsig-sha256 and an in-body
    signature.
-3. using only NewHash, by only using the gpgsig-newhash field.
+3. using only SHA-256, by only using the gpgsig-sha256 field.
 
 Mergetag embedding
 ~~~~~~~~~~~~~~~~~~
 The mergetag field in the sha1-content of a commit contains the
 sha1-content of a tag that was merged by that commit.
 
-The mergetag field in the newhash-content of the same commit contains the
-newhash-content of the same tag.
+The mergetag field in the sha256-content of the same commit contains the
+sha256-content of the same tag.
 
 Submodules
 ~~~~~~~~~~
@@ -497,7 +494,7 @@ Caveats
 -------
 Invalid objects
 ~~~~~~~~~~~~~~~
-The conversion from sha1-content to newhash-content retains any
+The conversion from sha1-content to sha256-content retains any
 brokenness in the original object (e.g., tree entry modes encoded with
 leading 0, tree objects whose paths are not sorted correctly, and
 commit objects without an author or committer). This is a deliberate
@@ -516,7 +513,7 @@ allow lifting this restriction.
 
 Alternates
 ~~~~~~~~~~
-For the same reason, a newhash repository cannot borrow objects from a
+For the same reason, a sha256 repository cannot borrow objects from a
 sha1 repository using objects/info/alternates or
 $GIT_ALTERNATE_OBJECT_REPOSITORIES.
 
@@ -524,20 +521,20 @@ git notes
 ~~~~~~~~~
 The "git notes" tool annotates objects using their sha1-name as key.
 This design does not describe a way to migrate notes trees to use
-newhash-names. That migration is expected to happen separately (for
+sha256-names. That migration is expected to happen separately (for
 example using a file at the root of the notes tree to describe which
 hash it uses).
 
 Server-side cost
 ~~~~~~~~~~~~~~~~
-Until Git protocol gains NewHash support, using NewHash based storage
+Until Git protocol gains SHA-256 support, using SHA-256 based storage
 on public-facing Git servers is strongly discouraged. Once Git
-protocol gains NewHash support, NewHash based servers are likely not
+protocol gains SHA-256 support, SHA-256 based servers are likely not
 to support SHA-1 compatibility, to avoid what may be a very expensive
 hash reencode during clone and to encourage peers to modernize.
 
 The design described here allows fetches by SHA-1 clients of a
-personal NewHash repository because it's not much more difficult than
+personal SHA-256 repository because it's not much more difficult than
 allowing pushes from that repository. This support needs to be guarded
 by a configuration option --- servers like git.kernel.org that serve a
 large number of clients would not be expected to bear that cost.
@@ -547,7 +544,7 @@ Meaning of signatures
 The signed payload for signed commits and tags does not explicitly
 name the hash used to identify objects. If some day Git adopts a new
 hash function with the same length as the current SHA-1 (40
-hexadecimal digit) or NewHash (64 hexadecimal digit) objects then the
+hexadecimal digit) or SHA-256 (64 hexadecimal digit) objects then the
 intent behind the PGP signed payload in an object signature is
 unclear:
 
@@ -562,7 +559,7 @@ Does this mean Git v2.12.0 is the commit with sha1-name
 e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7 or the commit with
 new-40-digit-hash-name e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7?
 
-Fortunately NewHash and SHA-1 have different lengths. If Git starts
+Fortunately SHA-256 and SHA-1 have different lengths. If Git starts
 using another hash with the same length to name objects, then it will
 need to change the format of signed payloads using that hash to
 address this issue.
@@ -574,24 +571,24 @@ supports four different modes of operation:
 
  1. ("dark launch") Treat object names input by the user as SHA-1 and
     convert any object names written to output to SHA-1, but store
-    objects using NewHash.  This allows users to test the code with no
+    objects using SHA-256.  This allows users to test the code with no
     visible behavior change except for performance.  This allows
     allows running even tests that assume the SHA-1 hash function, to
     sanity-check the behavior of the new mode.
 
- 2. ("early transition") Allow both SHA-1 and NewHash object names in
+ 2. ("early transition") Allow both SHA-1 and SHA-256 object names in
     input. Any object names written to output use SHA-1. This allows
     users to continue to make use of SHA-1 to communicate with peers
     (e.g. by email) that have not migrated yet and prepares for mode 3.
 
- 3. ("late transition") Allow both SHA-1 and NewHash object names in
-    input. Any object names written to output use NewHash. In this
+ 3. ("late transition") Allow both SHA-1 and SHA-256 object names in
+    input. Any object names written to output use SHA-256. In this
     mode, users are using a more secure object naming method by
     default.  The disruption is minimal as long as most of their peers
     are in mode 2 or mode 3.
 
  4. ("post-transition") Treat object names input by the user as
-    NewHash and write output using NewHash. This is safer than mode 3
+    SHA-256 and write output using SHA-256. This is safer than mode 3
     because there is less risk that input is incorrectly interpreted
     using the wrong hash function.
 
@@ -601,27 +598,31 @@ The user can also explicitly specify which format to use for a
 particular revision specifier and for output, overriding the mode. For
 example:
 
-git --output-format=sha1 log abac87a^{sha1}..f787cac^{newhash}
+git --output-format=sha1 log abac87a^{sha1}..f787cac^{sha256}
 
-Selection of a New Hash
------------------------
+Choice of Hash
+--------------
 In early 2005, around the time that Git was written,  Xiaoyun Wang,
 Yiqun Lisa Yin, and Hongbo Yu announced an attack finding SHA-1
 collisions in 2^69 operations. In August they published details.
 Luckily, no practical demonstrations of a collision in full SHA-1 were
 published until 10 years later, in 2017.
 
-The hash function NewHash to replace SHA-1 should be stronger than
-SHA-1 was: we would like it to be trustworthy and useful in practice
-for at least 10 years.
+Git v2.13.0 and later subsequently moved to a hardened SHA-1
+implementation by default that mitigates the SHAttered attack, but
+SHA-1 is still believed to be weak.
+
+The hash to replace this hardened SHA-1 should be stronger than SHA-1
+was: we would like it to be trustworthy and useful in practice for at
+least 10 years.
 
 Some other relevant properties:
 
 1. A 256-bit hash (long enough to match common security practice; not
    excessively long to hurt performance and disk usage).
 
-2. High quality implementations should be widely available (e.g. in
-   OpenSSL).
+2. High quality implementations should be widely available (e.g., in
+   OpenSSL and Apple CommonCrypto).
 
 3. The hash function's properties should match Git's needs (e.g. Git
    requires collision and 2nd preimage resistance and does not require
@@ -630,14 +631,13 @@ Some other relevant properties:
 4. As a tiebreaker, the hash should be fast to compute (fortunately
    many contenders are faster than SHA-1).
 
-Some hashes under consideration are SHA-256, SHA-512/256, SHA-256x16,
-K12, and BLAKE2bp-256.
+We choose SHA-256.
 
 Transition plan
 ---------------
 Some initial steps can be implemented independently of one another:
 - adding a hash function API (vtable)
-- teaching fsck to tolerate the gpgsig-newhash field
+- teaching fsck to tolerate the gpgsig-sha256 field
 - excluding gpgsig-* from the fields copied by "git commit --amend"
 - annotating tests that depend on SHA-1 values with a SHA1 test
   prerequisite
@@ -664,7 +664,7 @@ Next comes introduction of compatObjectFormat:
 - adding appropriate index entries when adding a new object to the
   object store
 - --output-format option
-- ^{sha1} and ^{newhash} revision notation
+- ^{sha1} and ^{sha256} revision notation
 - configuration to specify default input and output format (see
   "Object names on the command line" above)
 
@@ -672,7 +672,7 @@ The next step is supporting fetches and pushes to SHA-1 repositories:
 - allow pushes to a repository using the compat format
 - generate a topologically sorted list of the SHA-1 names of fetched
   objects
-- convert the fetched packfile to newhash format and generate an idx
+- convert the fetched packfile to sha256 format and generate an idx
   file
 - re-sort to match the order of objects in the fetched packfile
 
@@ -680,30 +680,30 @@ The infrastructure supporting fetch also allows converting an existing
 repository. In converted repositories and new clones, end users can
 gain support for the new hash function without any visible change in
 behavior (see "dark launch" in the "Object names on the command line"
-section). In particular this allows users to verify NewHash signatures
+section). In particular this allows users to verify SHA-256 signatures
 on objects in the repository, and it should ensure the transition code
 is stable in production in preparation for using it more widely.
 
 Over time projects would encourage their users to adopt the "early
 transition" and then "late transition" modes to take advantage of the
-new, more futureproof NewHash object names.
+new, more futureproof SHA-256 object names.
 
 When objectFormat and compatObjectFormat are both set, commands
-generating signatures would generate both SHA-1 and NewHash signatures
+generating signatures would generate both SHA-1 and SHA-256 signatures
 by default to support both new and old users.
 
-In projects using NewHash heavily, users could be encouraged to adopt
+In projects using SHA-256 heavily, users could be encouraged to adopt
 the "post-transition" mode to avoid accidentally making implicit use
 of SHA-1 object names.
 
 Once a critical mass of users have upgraded to a version of Git that
-can verify NewHash signatures and have converted their existing
+can verify SHA-256 signatures and have converted their existing
 repositories to support verifying them, we can add support for a
-setting to generate only NewHash signatures. This is expected to be at
+setting to generate only SHA-256 signatures. This is expected to be at
 least a year later.
 
 That is also a good moment to advertise the ability to convert
-repositories to use NewHash only, stripping out all SHA-1 related
+repositories to use SHA-256 only, stripping out all SHA-1 related
 metadata. This improves performance by eliminating translation
 overhead and security by avoiding the possibility of accidentally
 relying on the safety of SHA-1.
@@ -742,16 +742,16 @@ using the old hash function.
 
 Signed objects with multiple hashes
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Instead of introducing the gpgsig-newhash field in commit and tag objects
-for newhash-content based signatures, an earlier version of this design
-added "hash newhash <newhash-name>" fields to strengthen the existing
+Instead of introducing the gpgsig-sha256 field in commit and tag objects
+for sha256-content based signatures, an earlier version of this design
+added "hash sha256 <sha256-name>" fields to strengthen the existing
 sha1-content based signatures.
 
 In other words, a single signature was used to attest to the object
 content using both hash functions. This had some advantages:
 * Using one signature instead of two speeds up the signing process.
 * Having one signed payload with both hashes allows the signer to
-  attest to the sha1-name and newhash-name referring to the same object.
+  attest to the sha1-name and sha256-name referring to the same object.
 * All users consume the same signature. Broken signatures are likely
   to be detected quickly using current versions of git.
 
@@ -760,11 +760,11 @@ However, it also came with disadvantages:
   objects it references, even after the transition is complete and
   translation table is no longer needed for anything else. To support
   this, the design added fields such as "hash sha1 tree <sha1-name>"
-  and "hash sha1 parent <sha1-name>" to the newhash-content of a signed
+  and "hash sha1 parent <sha1-name>" to the sha256-content of a signed
   commit, complicating the conversion process.
 * Allowing signed objects without a sha1 (for after the transition is
   complete) complicated the design further, requiring a "nohash sha1"
-  field to suppress including "hash sha1" fields in the newhash-content
+  field to suppress including "hash sha1" fields in the sha256-content
   and signed payload.
 
 Lazily populated translation table
@@ -772,7 +772,7 @@ Lazily populated translation table
 Some of the work of building the translation table could be deferred to
 push time, but that would significantly complicate and slow down pushes.
 Calculating the sha1-name at object creation time at the same time it is
-being streamed to disk and having its newhash-name calculated should be
+being streamed to disk and having its sha256-name calculated should be
 an acceptable cost.
 
 Document History
@@ -814,6 +814,12 @@ Incorporated suggestions from jonathantanmy and sbeller:
 * avoid loose object overhead by packing more aggressively in
   "git gc --auto"
 
+Later history:
+
+ See the history of this file in git.git for the history of subsequent
+ edits. This document history is no longer being maintained as it
+ would now be superfluous to the commit log
+
 [1] http://public-inbox.org/git/CA+55aFzJtejiCjV0e43+9oR3QuJK2PiFiLQemytoLpyJWe6P9w@mail.gmail.com/
 [2] http://public-inbox.org/git/CA+55aFz+gkAsDZ24zmePQuEs1XPS9BP_s8O7Q4wQ7LV7X5-oDA@mail.gmail.com/
 [3] http://public-inbox.org/git/20170306084353.nrns455dvkdsfgo5@sigill.intra.peff.net/
index 0bed247..1ef66bd 100644 (file)
@@ -69,24 +69,24 @@ Design Details
 
 - A new pack-protocol capability "filter" is added to the fetch-pack and
   upload-pack negotiation.
-
-  This uses the existing capability discovery mechanism.
-  See "filter" in Documentation/technical/pack-protocol.txt.
++
+This uses the existing capability discovery mechanism.
+See "filter" in Documentation/technical/pack-protocol.txt.
 
 - Clients pass a "filter-spec" to clone and fetch which is passed to the
   server to request filtering during packfile construction.
-
-  There are various filters available to accommodate different situations.
-  See "--filter=<filter-spec>" in Documentation/rev-list-options.txt.
++
+There are various filters available to accommodate different situations.
+See "--filter=<filter-spec>" in Documentation/rev-list-options.txt.
 
 - On the server pack-objects applies the requested filter-spec as it
   creates "filtered" packfiles for the client.
-
-  These filtered packfiles are *incomplete* in the traditional sense because
-  they may contain objects that reference objects not contained in the
-  packfile and that the client doesn't already have.  For example, the
-  filtered packfile may contain trees or tags that reference missing blobs
-  or commits that reference missing trees.
++
+These filtered packfiles are *incomplete* in the traditional sense because
+they may contain objects that reference objects not contained in the
+packfile and that the client doesn't already have.  For example, the
+filtered packfile may contain trees or tags that reference missing blobs
+or commits that reference missing trees.
 
 - On the client these incomplete packfiles are marked as "promisor packfiles"
   and treated differently by various commands.
@@ -104,47 +104,47 @@ Handling Missing Objects
   to repository corruption.  To differentiate these cases, the local
   repository specially indicates such filtered packfiles obtained from the
   promisor remote as "promisor packfiles".
-
-  These promisor packfiles consist of a "<name>.promisor" file with
-  arbitrary contents (like the "<name>.keep" files), in addition to
-  their "<name>.pack" and "<name>.idx" files.
++
+These promisor packfiles consist of a "<name>.promisor" file with
+arbitrary contents (like the "<name>.keep" files), in addition to
+their "<name>.pack" and "<name>.idx" files.
 
 - The local repository considers a "promisor object" to be an object that
   it knows (to the best of its ability) that the promisor remote has promised
   that it has, either because the local repository has that object in one of
   its promisor packfiles, or because another promisor object refers to it.
-
-  When Git encounters a missing object, Git can see if it a promisor object
-  and handle it appropriately.  If not, Git can report a corruption.
-
-  This means that there is no need for the client to explicitly maintain an
-  expensive-to-modify list of missing objects.[a]
++
+When Git encounters a missing object, Git can see if it a promisor object
+and handle it appropriately.  If not, Git can report a corruption.
++
+This means that there is no need for the client to explicitly maintain an
+expensive-to-modify list of missing objects.[a]
 
 - Since almost all Git code currently expects any referenced object to be
   present locally and because we do not want to force every command to do
   a dry-run first, a fallback mechanism is added to allow Git to attempt
   to dynamically fetch missing objects from the promisor remote.
-
-  When the normal object lookup fails to find an object, Git invokes
-  fetch-object to try to get the object from the server and then retry
-  the object lookup.  This allows objects to be "faulted in" without
-  complicated prediction algorithms.
-
-  For efficiency reasons, no check as to whether the missing object is
-  actually a promisor object is performed.
-
-  Dynamic object fetching tends to be slow as objects are fetched one at
-  a time.
++
+When the normal object lookup fails to find an object, Git invokes
+fetch-object to try to get the object from the server and then retry
+the object lookup.  This allows objects to be "faulted in" without
+complicated prediction algorithms.
++
+For efficiency reasons, no check as to whether the missing object is
+actually a promisor object is performed.
++
+Dynamic object fetching tends to be slow as objects are fetched one at
+a time.
 
 - `checkout` (and any other command using `unpack-trees`) has been taught
   to bulk pre-fetch all required missing blobs in a single batch.
 
 - `rev-list` has been taught to print missing objects.
-
-  This can be used by other commands to bulk prefetch objects.
-  For example, a "git log -p A..B" may internally want to first do
-  something like "git rev-list --objects --quiet --missing=print A..B"
-  and prefetch those objects in bulk.
++
+This can be used by other commands to bulk prefetch objects.
+For example, a "git log -p A..B" may internally want to first do
+something like "git rev-list --objects --quiet --missing=print A..B"
+and prefetch those objects in bulk.
 
 - `fsck` has been updated to be fully aware of promisor objects.
 
@@ -154,11 +154,11 @@ Handling Missing Objects
 - The global variable "fetch_if_missing" is used to control whether an
   object lookup will attempt to dynamically fetch a missing object or
   report an error.
-
-  We are not happy with this global variable and would like to remove it,
-  but that requires significant refactoring of the object code to pass an
-  additional flag.  We hope that concurrent efforts to add an ODB API can
-  encompass this.
++
+We are not happy with this global variable and would like to remove it,
+but that requires significant refactoring of the object code to pass an
+additional flag.  We hope that concurrent efforts to add an ODB API can
+encompass this.
 
 
 Fetching Missing Objects
@@ -168,10 +168,10 @@ Fetching Missing Objects
   transport_fetch_refs(), setting a new transport option
   TRANS_OPT_NO_DEPENDENTS to indicate that only the objects themselves are
   desired, not any object that they refer to.
-
-  Because some transports invoke fetch_pack() in the same process, fetch_pack()
-  has been updated to not use any object flags when the corresponding argument
-  (no_dependents) is set.
++
+Because some transports invoke fetch_pack() in the same process, fetch_pack()
+has been updated to not use any object flags when the corresponding argument
+(no_dependents) is set.
 
 - The local repository sends a request with the hashes of all requested
   objects as "want" lines, and does not perform any packfile negotiation.
@@ -187,13 +187,13 @@ Current Limitations
 
 - The remote used for a partial clone (or the first partial fetch
   following a regular clone) is marked as the "promisor remote".
-
-  We are currently limited to a single promisor remote and only that
-  remote may be used for subsequent partial fetches.
-
-  We accept this limitation because we believe initial users of this
-  feature will be using it on repositories with a strong single central
-  server.
++
+We are currently limited to a single promisor remote and only that
+remote may be used for subsequent partial fetches.
++
+We accept this limitation because we believe initial users of this
+feature will be using it on repositories with a strong single central
+server.
 
 - Dynamic object fetching will only ask the promisor remote for missing
   objects.  We assume that the promisor remote has a complete view of the
@@ -221,13 +221,13 @@ Future Work
 - Allow more than one promisor remote and define a strategy for fetching
   missing objects from specific promisor remotes or of iterating over the
   set of promisor remotes until a missing object is found.
-
-  A user might want to have multiple geographically-close cache servers
-  for fetching missing blobs while continuing to do filtered `git-fetch`
-  commands from the central server, for example.
-
-  Or the user might want to work in a triangular work flow with multiple
-  promisor remotes that each have an incomplete view of the repository.
++
+A user might want to have multiple geographically-close cache servers
+for fetching missing blobs while continuing to do filtered `git-fetch`
+commands from the central server, for example.
++
+Or the user might want to work in a triangular work flow with multiple
+promisor remotes that each have an incomplete view of the repository.
 
 - Allow repack to work on promisor packfiles (while keeping them distinct
   from non-promisor packfiles).
@@ -238,25 +238,25 @@ Future Work
 - Investigate use of a long-running process to dynamically fetch a series
   of objects, such as proposed in [5,6] to reduce process startup and
   overhead costs.
-
-  It would be nice if pack protocol V2 could allow that long-running
-  process to make a series of requests over a single long-running
-  connection.
++
+It would be nice if pack protocol V2 could allow that long-running
+process to make a series of requests over a single long-running
+connection.
 
 - Investigate pack protocol V2 to avoid the info/refs broadcast on
   each connection with the server to dynamically fetch missing objects.
 
 - Investigate the need to handle loose promisor objects.
-
-  Objects in promisor packfiles are allowed to reference missing objects
-  that can be dynamically fetched from the server.  An assumption was
-  made that loose objects are only created locally and therefore should
-  not reference a missing object.  We may need to revisit that assumption
-  if, for example, we dynamically fetch a missing tree and store it as a
-  loose object rather than a single object packfile.
-
-  This does not necessarily mean we need to mark loose objects as promisor;
-  it may be sufficient to relax the object lookup or is-promisor functions.
++
+Objects in promisor packfiles are allowed to reference missing objects
+that can be dynamically fetched from the server.  An assumption was
+made that loose objects are only created locally and therefore should
+not reference a missing object.  We may need to revisit that assumption
+if, for example, we dynamically fetch a missing tree and store it as a
+loose object rather than a single object packfile.
++
+This does not necessarily mean we need to mark loose objects as promisor;
+it may be sufficient to relax the object lookup or is-promisor functions.
 
 
 Non-Tasks
@@ -265,13 +265,13 @@ Non-Tasks
 - Every time the subject of "demand loading blobs" comes up it seems
   that someone suggests that the server be allowed to "guess" and send
   additional objects that may be related to the requested objects.
-
-  No work has gone into actually doing that; we're just documenting that
-  it is a common suggestion.  We're not sure how it would work and have
-  no plans to work on it.
-
-  It is valid for the server to send more objects than requested (even
-  for a dynamic object fetch), but we are not building on that.
++
+No work has gone into actually doing that; we're just documenting that
+it is a common suggestion.  We're not sure how it would work and have
+no plans to work on it.
++
+It is valid for the server to send more objects than requested (even
+for a dynamic object fetch), but we are not building on that.
 
 
 Footnotes
@@ -282,43 +282,43 @@ Footnotes
     This would essentially be a sorted linear list of OIDs that the were
     omitted by the server during a clone or subsequent fetches.
 
-    This file would need to be loaded into memory on every object lookup.
-    It would need to be read, updated, and re-written (like the .git/index)
-    on every explicit "git fetch" command *and* on any dynamic object fetch.
+This file would need to be loaded into memory on every object lookup.
+It would need to be read, updated, and re-written (like the .git/index)
+on every explicit "git fetch" command *and* on any dynamic object fetch.
 
-    The cost to read, update, and write this file could add significant
-    overhead to every command if there are many missing objects.  For example,
-    if there are 100M missing blobs, this file would be at least 2GiB on disk.
+The cost to read, update, and write this file could add significant
+overhead to every command if there are many missing objects.  For example,
+if there are 100M missing blobs, this file would be at least 2GiB on disk.
 
-    With the "promisor" concept, we *infer* a missing object based upon the
-    type of packfile that references it.
+With the "promisor" concept, we *infer* a missing object based upon the
+type of packfile that references it.
 
 
 Related Links
 -------------
-[0] https://bugs.chromium.org/p/git/issues/detail?id=2
-    Chromium work item for: Partial Clone
+[0] https://crbug.com/git/2
+    Bug#2: Partial Clone
 
-[1] https://public-inbox.org/git/20170113155253.1644-1-benpeart@microsoft.com/
-    Subject: [RFC] Add support for downloading blobs on demand
+[1] https://public-inbox.org/git/20170113155253.1644-1-benpeart@microsoft.com/ +
+    Subject: [RFC] Add support for downloading blobs on demand +
     Date: Fri, 13 Jan 2017 10:52:53 -0500
 
-[2] https://public-inbox.org/git/cover.1506714999.git.jonathantanmy@google.com/
-    Subject: [PATCH 00/18] Partial clone (from clone to lazy fetch in 18 patches)
+[2] https://public-inbox.org/git/cover.1506714999.git.jonathantanmy@google.com/ +
+    Subject: [PATCH 00/18] Partial clone (from clone to lazy fetch in 18 patches) +
     Date: Fri, 29 Sep 2017 13:11:36 -0700
 
-[3] https://public-inbox.org/git/20170426221346.25337-1-jonathantanmy@google.com/
-    Subject: Proposal for missing blob support in Git repos
+[3] https://public-inbox.org/git/20170426221346.25337-1-jonathantanmy@google.com/ +
+    Subject: Proposal for missing blob support in Git repos +
     Date: Wed, 26 Apr 2017 15:13:46 -0700
 
-[4] https://public-inbox.org/git/1488999039-37631-1-git-send-email-git@jeffhostetler.com/
-    Subject: [PATCH 00/10] RFC Partial Clone and Fetch
+[4] https://public-inbox.org/git/1488999039-37631-1-git-send-email-git@jeffhostetler.com/ +
+    Subject: [PATCH 00/10] RFC Partial Clone and Fetch +
     Date: Wed,  8 Mar 2017 18:50:29 +0000
 
-[5] https://public-inbox.org/git/20170505152802.6724-1-benpeart@microsoft.com/
-    Subject: [PATCH v7 00/10] refactor the filter process code into a reusable module
+[5] https://public-inbox.org/git/20170505152802.6724-1-benpeart@microsoft.com/ +
+    Subject: [PATCH v7 00/10] refactor the filter process code into a reusable module +
     Date: Fri,  5 May 2017 11:27:52 -0400
 
-[6] https://public-inbox.org/git/20170714132651.170708-1-benpeart@microsoft.com/
-    Subject: [RFC/PATCH v2 0/1] Add support for downloading blobs on demand
+[6] https://public-inbox.org/git/20170714132651.170708-1-benpeart@microsoft.com/ +
+    Subject: [RFC/PATCH v2 0/1] Add support for downloading blobs on demand +
     Date: Fri, 14 Jul 2017 09:26:50 -0400
index 920678a..81f4397 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.18.GIT
+DEF_VER=v2.19.0-rc0
 
 LF='
 '
index e3364a4..d03df31 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -876,6 +876,7 @@ LIB_OBJS += gpg-interface.o
 LIB_OBJS += graph.o
 LIB_OBJS += grep.o
 LIB_OBJS += hashmap.o
+LIB_OBJS += linear-assignment.o
 LIB_OBJS += help.o
 LIB_OBJS += hex.o
 LIB_OBJS += ident.o
@@ -931,6 +932,7 @@ LIB_OBJS += progress.o
 LIB_OBJS += prompt.o
 LIB_OBJS += protocol.o
 LIB_OBJS += quote.o
+LIB_OBJS += range-diff.o
 LIB_OBJS += reachable.o
 LIB_OBJS += read-cache.o
 LIB_OBJS += reflog-walk.o
@@ -1069,6 +1071,7 @@ BUILTIN_OBJS += builtin/prune-packed.o
 BUILTIN_OBJS += builtin/prune.o
 BUILTIN_OBJS += builtin/pull.o
 BUILTIN_OBJS += builtin/push.o
+BUILTIN_OBJS += builtin/range-diff.o
 BUILTIN_OBJS += builtin/read-tree.o
 BUILTIN_OBJS += builtin/rebase--helper.o
 BUILTIN_OBJS += builtin/receive-pack.o
@@ -2044,7 +2047,7 @@ $(BUILT_INS): git$X
 
 command-list.h: generate-cmdlist.sh command-list.txt
 
-command-list.h: $(wildcard Documentation/git*.txt)
+command-list.h: $(wildcard Documentation/git*.txt) Documentation/config.txt
        $(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@
 
 SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
diff --git a/alloc.c b/alloc.c
index c2fc5d6..e7aa81b 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -36,7 +36,7 @@ struct alloc_state {
        int slab_nr, slab_alloc;
 };
 
-void *allocate_alloc_state(void)
+struct alloc_state *allocate_alloc_state(void)
 {
        return xcalloc(1, sizeof(struct alloc_state));
 }
diff --git a/alloc.h b/alloc.h
index 3e4e828..ba356ed 100644 (file)
--- a/alloc.h
+++ b/alloc.h
@@ -1,9 +1,11 @@
 #ifndef ALLOC_H
 #define ALLOC_H
 
+struct alloc_state;
 struct tree;
 struct commit;
 struct tag;
+struct repository;
 
 void *alloc_blob_node(struct repository *r);
 void *alloc_tree_node(struct repository *r);
@@ -13,7 +15,7 @@ void *alloc_object_node(struct repository *r);
 void alloc_report(struct repository *r);
 unsigned int alloc_commit_index(struct repository *r);
 
-void *allocate_alloc_state(void);
+struct alloc_state *allocate_alloc_state(void);
 void clear_alloc_state(struct alloc_state *s);
 
 #endif
diff --git a/apply.c b/apply.c
index 2594927..e485fbc 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -76,10 +76,12 @@ static int parse_ignorewhitespace_option(struct apply_state *state,
 }
 
 int init_apply_state(struct apply_state *state,
+                    struct repository *repo,
                     const char *prefix)
 {
        memset(state, 0, sizeof(*state));
        state->prefix = prefix;
+       state->repo = repo;
        state->apply = 1;
        state->line_termination = '\n';
        state->p_value = 1;
@@ -3374,14 +3376,17 @@ static struct patch *previous_patch(struct apply_state *state,
        return previous;
 }
 
-static int verify_index_match(const struct cache_entry *ce, struct stat *st)
+static int verify_index_match(struct apply_state *state,
+                             const struct cache_entry *ce,
+                             struct stat *st)
 {
        if (S_ISGITLINK(ce->ce_mode)) {
                if (!S_ISDIR(st->st_mode))
                        return -1;
                return 0;
        }
-       return ce_match_stat(ce, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
+       return ie_match_stat(state->repo->index, ce, st,
+                            CE_MATCH_IGNORE_VALID | CE_MATCH_IGNORE_SKIP_WORKTREE);
 }
 
 #define SUBMODULE_PATCH_WITHOUT_INDEX 1
@@ -3514,17 +3519,17 @@ static int load_current(struct apply_state *state,
        if (!patch->is_new)
                BUG("patch to %s is not a creation", patch->old_name);
 
-       pos = cache_name_pos(name, strlen(name));
+       pos = index_name_pos(state->repo->index, name, strlen(name));
        if (pos < 0)
                return error(_("%s: does not exist in index"), name);
-       ce = active_cache[pos];
+       ce = state->repo->index->cache[pos];
        if (lstat(name, &st)) {
                if (errno != ENOENT)
                        return error_errno("%s", name);
-               if (checkout_target(&the_index, ce, &st))
+               if (checkout_target(state->repo->index, ce, &st))
                        return -1;
        }
-       if (verify_index_match(ce, &st))
+       if (verify_index_match(state, ce, &st))
                return error(_("%s: does not match index"), name);
 
        status = load_patch_target(state, &buf, ce, &st, patch, name, mode);
@@ -3683,18 +3688,19 @@ static int check_preimage(struct apply_state *state,
        }
 
        if (state->check_index && !previous) {
-               int pos = cache_name_pos(old_name, strlen(old_name));
+               int pos = index_name_pos(state->repo->index, old_name,
+                                        strlen(old_name));
                if (pos < 0) {
                        if (patch->is_new < 0)
                                goto is_new;
                        return error(_("%s: does not exist in index"), old_name);
                }
-               *ce = active_cache[pos];
+               *ce = state->repo->index->cache[pos];
                if (stat_ret < 0) {
-                       if (checkout_target(&the_index, *ce, st))
+                       if (checkout_target(state->repo->index, *ce, st))
                                return -1;
                }
-               if (!state->cached && verify_index_match(*ce, st))
+               if (!state->cached && verify_index_match(state, *ce, st))
                        return error(_("%s: does not match index"), old_name);
                if (state->cached)
                        st_mode = (*ce)->ce_mode;
@@ -3738,7 +3744,7 @@ static int check_to_create(struct apply_state *state,
        struct stat nst;
 
        if (state->check_index &&
-           cache_name_pos(new_name, strlen(new_name)) >= 0 &&
+           index_name_pos(state->repo->index, new_name, strlen(new_name)) >= 0 &&
            !ok_if_exists)
                return EXISTS_IN_INDEX;
        if (state->cached)
@@ -3827,7 +3833,8 @@ static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *na
                if (state->check_index) {
                        struct cache_entry *ce;
 
-                       ce = cache_file_exists(name->buf, name->len, ignore_case);
+                       ce = index_file_exists(state->repo->index, name->buf,
+                                              name->len, ignore_case);
                        if (ce && S_ISLNK(ce->ce_mode))
                                return 1;
                } else {
@@ -4002,9 +4009,10 @@ static int check_patch_list(struct apply_state *state, struct patch *patch)
 static int read_apply_cache(struct apply_state *state)
 {
        if (state->index_file)
-               return read_cache_from(state->index_file);
+               return read_index_from(state->repo->index, state->index_file,
+                                      get_git_dir());
        else
-               return read_cache();
+               return read_index(state->repo->index);
 }
 
 /* This function tries to read the object name from the current index */
@@ -4015,10 +4023,10 @@ static int get_current_oid(struct apply_state *state, const char *path,
 
        if (read_apply_cache(state) < 0)
                return -1;
-       pos = cache_name_pos(path, strlen(path));
+       pos = index_name_pos(state->repo->index, path, strlen(path));
        if (pos < 0)
                return -1;
-       oidcpy(oid, &active_cache[pos]->oid);
+       oidcpy(oid, &state->repo->index->cache[pos]->oid);
        return 0;
 }
 
@@ -4246,7 +4254,7 @@ static void patch_stats(struct apply_state *state, struct patch *patch)
 static int remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty)
 {
        if (state->update_index && !state->ita_only) {
-               if (remove_file_from_cache(patch->old_name) < 0)
+               if (remove_file_from_index(state->repo->index, patch->old_name) < 0)
                        return error(_("unable to remove %s from index"), patch->old_name);
        }
        if (!state->cached) {
@@ -4267,7 +4275,7 @@ static int add_index_file(struct apply_state *state,
        struct cache_entry *ce;
        int namelen = strlen(path);
 
-       ce = make_empty_cache_entry(&the_index, namelen);
+       ce = make_empty_cache_entry(state->repo->index, namelen);
        memcpy(ce->name, path, namelen);
        ce->ce_mode = create_ce_mode(mode);
        ce->ce_flags = create_ce_flags(0);
@@ -4299,7 +4307,7 @@ static int add_index_file(struct apply_state *state,
                                       "for newly created file %s"), path);
                }
        }
-       if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) {
+       if (add_index_entry(state->repo->index, ce, ADD_CACHE_OK_TO_ADD) < 0) {
                discard_cache_entry(ce);
                return error(_("unable to add cache entry for %s"), path);
        }
@@ -4313,7 +4321,9 @@ static int add_index_file(struct apply_state *state,
  *   0 if everything went well
  *   1 if a recoverable error happened
  */
-static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
+static int try_create_file(struct apply_state *state, const char *path,
+                          unsigned int mode, const char *buf,
+                          unsigned long size)
 {
        int fd, res;
        struct strbuf nbuf = STRBUF_INIT;
@@ -4335,7 +4345,7 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
        if (fd < 0)
                return 1;
 
-       if (convert_to_working_tree(path, buf, size, &nbuf)) {
+       if (convert_to_working_tree(state->repo->index, path, buf, size, &nbuf)) {
                size = nbuf.len;
                buf  = nbuf.buf;
        }
@@ -4371,7 +4381,7 @@ static int create_one_file(struct apply_state *state,
        if (state->cached)
                return 0;
 
-       res = try_create_file(path, mode, buf, size);
+       res = try_create_file(state, path, mode, buf, size);
        if (res < 0)
                return -1;
        if (!res)
@@ -4380,7 +4390,7 @@ static int create_one_file(struct apply_state *state,
        if (errno == ENOENT) {
                if (safe_create_leading_directories(path))
                        return 0;
-               res = try_create_file(path, mode, buf, size);
+               res = try_create_file(state, path, mode, buf, size);
                if (res < 0)
                        return -1;
                if (!res)
@@ -4402,7 +4412,7 @@ static int create_one_file(struct apply_state *state,
                for (;;) {
                        char newpath[PATH_MAX];
                        mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
-                       res = try_create_file(newpath, mode, buf, size);
+                       res = try_create_file(state, newpath, mode, buf, size);
                        if (res < 0)
                                return -1;
                        if (!res) {
@@ -4432,17 +4442,17 @@ static int add_conflicted_stages_file(struct apply_state *state,
        namelen = strlen(patch->new_name);
        mode = patch->new_mode ? patch->new_mode : (S_IFREG | 0644);
 
-       remove_file_from_cache(patch->new_name);
+       remove_file_from_index(state->repo->index, patch->new_name);
        for (stage = 1; stage < 4; stage++) {
                if (is_null_oid(&patch->threeway_stage[stage - 1]))
                        continue;
-               ce = make_empty_cache_entry(&the_index, namelen);
+               ce = make_empty_cache_entry(state->repo->index, namelen);
                memcpy(ce->name, patch->new_name, namelen);
                ce->ce_mode = create_ce_mode(mode);
                ce->ce_flags = create_ce_flags(stage);
                ce->ce_namelen = namelen;
                oidcpy(&ce->oid, &patch->threeway_stage[stage - 1]);
-               if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) {
+               if (add_index_entry(state->repo->index, ce, ADD_CACHE_OK_TO_ADD) < 0) {
                        discard_cache_entry(ce);
                        return error(_("unable to add cache entry for %s"),
                                     patch->new_name);
@@ -4891,7 +4901,7 @@ int apply_all_patches(struct apply_state *state,
        }
 
        if (state->update_index) {
-               res = write_locked_index(&the_index, &state->lock_file, COMMIT_LOCK);
+               res = write_locked_index(state->repo->index, &state->lock_file, COMMIT_LOCK);
                if (res) {
                        error(_("Unable to write new index file"));
                        res = -128;
diff --git a/apply.h b/apply.h
index b80d8ba..5948348 100644 (file)
--- a/apply.h
+++ b/apply.h
@@ -1,6 +1,11 @@
 #ifndef APPLY_H
 #define APPLY_H
 
+#include "lockfile.h"
+#include "string-list.h"
+
+struct repository;
+
 enum apply_ws_error_action {
        nowarn_ws_error,
        warn_on_ws_error,
@@ -62,6 +67,7 @@ struct apply_state {
        int unsafe_paths;
 
        /* Other non boolean parameters */
+       struct repository *repo;
        const char *index_file;
        enum apply_verbosity apply_verbosity;
        const char *fake_ancestor;
@@ -111,14 +117,15 @@ struct apply_state {
        int applied_after_fixing_ws;
 };
 
-extern int apply_parse_options(int argc, const char **argv,
-                              struct apply_state *state,
-                              int *force_apply, int *options,
-                              const char * const *apply_usage);
-extern int init_apply_state(struct apply_state *state,
-                           const char *prefix);
-extern void clear_apply_state(struct apply_state *state);
-extern int check_apply_state(struct apply_state *state, int force_apply);
+int apply_parse_options(int argc, const char **argv,
+                       struct apply_state *state,
+                       int *force_apply, int *options,
+                       const char * const *apply_usage);
+int init_apply_state(struct apply_state *state,
+                    struct repository *repo,
+                    const char *prefix);
+void clear_apply_state(struct apply_state *state);
+int check_apply_state(struct apply_state *state, int force_apply);
 
 /*
  * Some aspects of the apply behavior are controlled by the following
@@ -127,9 +134,8 @@ extern int check_apply_state(struct apply_state *state, int force_apply);
 #define APPLY_OPT_INACCURATE_EOF       (1<<0) /* accept inaccurate eof */
 #define APPLY_OPT_RECOUNT              (1<<1) /* accept inaccurate line count */
 
-extern int apply_all_patches(struct apply_state *state,
-                            int argc,
-                            const char **argv,
-                            int options);
+int apply_all_patches(struct apply_state *state,
+                     int argc, const char **argv,
+                     int options);
 
 #endif
index 0bc50f6..7a535cb 100644 (file)
@@ -277,7 +277,7 @@ static int write_tar_entry(struct archiver_args *args,
                memcpy(header.name, path, pathlen);
 
        if (S_ISREG(mode) && !args->convert &&
-           oid_object_info(the_repository, oid, &size) == OBJ_BLOB &&
+           oid_object_info(args->repo, oid, &size) == OBJ_BLOB &&
            size > big_file_threshold)
                buffer = NULL;
        else if (S_ISLNK(mode) || S_ISREG(mode)) {
index 024267f..5a62351 100644 (file)
@@ -326,7 +326,7 @@ static int write_zip_entry(struct archiver_args *args,
                compressed_size = 0;
                buffer = NULL;
        } else if (S_ISREG(mode) || S_ISLNK(mode)) {
-               enum object_type type = oid_object_info(the_repository, oid,
+               enum object_type type = oid_object_info(args->repo, oid,
                                                        &size);
 
                method = 0;
index 78b0a39..0a07b14 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -79,7 +79,7 @@ void *object_file_to_archive(const struct archiver_args *args,
                size_t size = 0;
 
                strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
-               convert_to_working_tree(path, buf.buf, buf.len, &buf);
+               convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf);
                if (commit)
                        format_subst(commit, buf.buf, buf.len, &buf);
                buffer = strbuf_detach(&buf, &size);
@@ -104,12 +104,13 @@ struct archiver_context {
        struct directory *bottom;
 };
 
-static const struct attr_check *get_archive_attrs(const char *path)
+static const struct attr_check *get_archive_attrs(struct index_state *istate,
+                                                 const char *path)
 {
        static struct attr_check *check;
        if (!check)
                check = attr_check_initl("export-ignore", "export-subst", NULL);
-       return git_check_attr(path, check) ? NULL : check;
+       return git_check_attr(istate, path, check) ? NULL : check;
 }
 
 static int check_attr_export_ignore(const struct attr_check *check)
@@ -145,7 +146,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
 
        if (!S_ISDIR(mode)) {
                const struct attr_check *check;
-               check = get_archive_attrs(path_without_prefix);
+               check = get_archive_attrs(args->repo->index, path_without_prefix);
                if (check_attr_export_ignore(check))
                        return 0;
                args->convert = check_attr_export_subst(check);
@@ -220,7 +221,7 @@ static int queue_or_write_archive_entry(const struct object_id *oid,
                /* Borrow base, but restore its original value when done. */
                strbuf_addstr(base, filename);
                strbuf_addch(base, '/');
-               check = get_archive_attrs(base->buf);
+               check = get_archive_attrs(c->args->repo->index, base->buf);
                strbuf_setlen(base, baselen);
 
                if (check_attr_export_ignore(check))
@@ -268,13 +269,13 @@ int write_archive_entries(struct archiver_args *args,
                memset(&opts, 0, sizeof(opts));
                opts.index_only = 1;
                opts.head_idx = -1;
-               opts.src_index = &the_index;
-               opts.dst_index = &the_index;
+               opts.src_index = args->repo->index;
+               opts.dst_index = args->repo->index;
                opts.fn = oneway_merge;
                init_tree_desc(&t, args->tree->buffer, args->tree->size);
                if (unpack_trees(1, &t, &opts))
                        return -1;
-               git_attr_set_direction(GIT_ATTR_INDEX, &the_index);
+               git_attr_set_direction(GIT_ATTR_INDEX);
        }
 
        err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec,
@@ -304,33 +305,43 @@ static const struct archiver *lookup_archiver(const char *name)
        return NULL;
 }
 
+struct path_exists_context {
+       struct pathspec pathspec;
+       struct archiver_args *args;
+};
+
 static int reject_entry(const struct object_id *oid, struct strbuf *base,
                        const char *filename, unsigned mode,
                        int stage, void *context)
 {
        int ret = -1;
+       struct path_exists_context *ctx = context;
+
        if (S_ISDIR(mode)) {
                struct strbuf sb = STRBUF_INIT;
                strbuf_addbuf(&sb, base);
                strbuf_addstr(&sb, filename);
-               if (!match_pathspec(context, sb.buf, sb.len, 0, NULL, 1))
+               if (!match_pathspec(ctx->args->repo->index,
+                                   &ctx->pathspec,
+                                   sb.buf, sb.len, 0, NULL, 1))
                        ret = READ_TREE_RECURSIVE;
                strbuf_release(&sb);
        }
        return ret;
 }
 
-static int path_exists(struct tree *tree, const char *path)
+static int path_exists(struct archiver_args *args, const char *path)
 {
        const char *paths[] = { path, NULL };
-       struct pathspec pathspec;
+       struct path_exists_context ctx;
        int ret;
 
-       parse_pathspec(&pathspec, 0, 0, "", paths);
-       pathspec.recursive = 1;
-       ret = read_tree_recursive(tree, "", 0, 0, &pathspec,
-                                 reject_entry, &pathspec);
-       clear_pathspec(&pathspec);
+       ctx.args = args;
+       parse_pathspec(&ctx.pathspec, 0, 0, "", paths);
+       ctx.pathspec.recursive = 1;
+       ret = read_tree_recursive(args->tree, "", 0, 0, &ctx.pathspec,
+                                 reject_entry, &ctx);
+       clear_pathspec(&ctx.pathspec);
        return ret != 0;
 }
 
@@ -348,7 +359,7 @@ static void parse_pathspec_arg(const char **pathspec,
        ar_args->pathspec.recursive = 1;
        if (pathspec) {
                while (*pathspec) {
-                       if (**pathspec && !path_exists(ar_args->tree, *pathspec))
+                       if (**pathspec && !path_exists(ar_args, *pathspec))
                                die(_("pathspec '%s' did not match any files"), *pathspec);
                        pathspec++;
                }
@@ -510,6 +521,7 @@ static int parse_archive_args(int argc, const char **argv,
 }
 
 int write_archive(int argc, const char **argv, const char *prefix,
+                 struct repository *repo,
                  const char *name_hint, int remote)
 {
        const struct archiver *ar = NULL;
@@ -521,6 +533,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
        init_tar_archiver();
        init_zip_archiver();
 
+       args.repo = repo;
        argc = parse_archive_args(argc, argv, &ar, &args, name_hint, remote);
        if (!startup_info->have_repository) {
                /*
index 1f9954f..d4f97a0 100644 (file)
--- a/archive.h
+++ b/archive.h
@@ -1,9 +1,13 @@
 #ifndef ARCHIVE_H
 #define ARCHIVE_H
 
+#include "cache.h"
 #include "pathspec.h"
 
+struct repository;
+
 struct archiver_args {
+       struct repository *repo;
        const char *base;
        size_t baselen;
        struct tree *tree;
@@ -17,6 +21,16 @@ struct archiver_args {
        int compression_level;
 };
 
+/* main api */
+
+extern int write_archive(int argc, const char **argv, const char *prefix,
+                        struct repository *repo,
+                        const char *name_hint, int remote);
+
+const char *archive_format_from_filename(const char *filename);
+
+/* archive backend stuff */
+
 #define ARCHIVER_WANT_COMPRESSION_LEVELS 1
 #define ARCHIVER_REMOTE 2
 struct archiver {
@@ -36,9 +50,6 @@ typedef int (*write_archive_entry_fn_t)(struct archiver_args *args,
                                        unsigned int mode);
 
 extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
-extern int write_archive(int argc, const char **argv, const char *prefix, const char *name_hint, int remote);
-
-const char *archive_format_from_filename(const char *filename);
 extern void *object_file_to_archive(const struct archiver_args *args,
                                    const char *path, const struct object_id *oid,
                                    unsigned int mode, enum object_type *type,
diff --git a/attr.c b/attr.c
index 067fb9e..98e4953 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -708,10 +708,8 @@ static struct attr_stack *read_attr_from_array(const char **list)
  * another thread could potentially be calling into the attribute system.
  */
 static enum git_attr_direction direction;
-static struct index_state *use_index;
 
-void git_attr_set_direction(enum git_attr_direction new_direction,
-                           struct index_state *istate)
+void git_attr_set_direction(enum git_attr_direction new_direction)
 {
        if (is_bare_repository() && new_direction != GIT_ATTR_INDEX)
                BUG("non-INDEX attr direction in a bare repo");
@@ -720,7 +718,6 @@ void git_attr_set_direction(enum git_attr_direction new_direction,
                drop_all_attr_stacks();
 
        direction = new_direction;
-       use_index = istate;
 }
 
 static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
@@ -743,13 +740,18 @@ static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
        return res;
 }
 
-static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
+static struct attr_stack *read_attr_from_index(const struct index_state *istate,
+                                              const char *path,
+                                              int macro_ok)
 {
        struct attr_stack *res;
        char *buf, *sp;
        int lineno = 0;
 
-       buf = read_blob_data_from_index(use_index ? use_index : &the_index, path, NULL);
+       if (!istate)
+               return NULL;
+
+       buf = read_blob_data_from_index(istate, path, NULL);
        if (!buf)
                return NULL;
 
@@ -768,15 +770,16 @@ static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
        return res;
 }
 
-static struct attr_stack *read_attr(const char *path, int macro_ok)
+static struct attr_stack *read_attr(const struct index_state *istate,
+                                   const char *path, int macro_ok)
 {
        struct attr_stack *res = NULL;
 
        if (direction == GIT_ATTR_INDEX) {
-               res = read_attr_from_index(path, macro_ok);
+               res = read_attr_from_index(istate, path, macro_ok);
        } else if (!is_bare_repository()) {
                if (direction == GIT_ATTR_CHECKOUT) {
-                       res = read_attr_from_index(path, macro_ok);
+                       res = read_attr_from_index(istate, path, macro_ok);
                        if (!res)
                                res = read_attr_from_file(path, macro_ok);
                } else if (direction == GIT_ATTR_CHECKIN) {
@@ -788,7 +791,7 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
                                 * We allow operation in a sparsely checked out
                                 * work tree, so read from it.
                                 */
-                               res = read_attr_from_index(path, macro_ok);
+                               res = read_attr_from_index(istate, path, macro_ok);
                }
        }
 
@@ -859,7 +862,8 @@ static void push_stack(struct attr_stack **attr_stack_p,
        }
 }
 
-static void bootstrap_attr_stack(struct attr_stack **stack)
+static void bootstrap_attr_stack(const struct index_state *istate,
+                                struct attr_stack **stack)
 {
        struct attr_stack *e;
 
@@ -883,7 +887,7 @@ static void bootstrap_attr_stack(struct attr_stack **stack)
        }
 
        /* root directory */
-       e = read_attr(GITATTRIBUTES_FILE, 1);
+       e = read_attr(istate, GITATTRIBUTES_FILE, 1);
        push_stack(stack, e, xstrdup(""), 0);
 
        /* info frame */
@@ -896,7 +900,8 @@ static void bootstrap_attr_stack(struct attr_stack **stack)
        push_stack(stack, e, NULL, 0);
 }
 
-static void prepare_attr_stack(const char *path, int dirlen,
+static void prepare_attr_stack(const struct index_state *istate,
+                              const char *path, int dirlen,
                               struct attr_stack **stack)
 {
        struct attr_stack *info;
@@ -917,7 +922,7 @@ static void prepare_attr_stack(const char *path, int dirlen,
         * .gitattributes in deeper directories to shallower ones,
         * and finally use the built-in set as the default.
         */
-       bootstrap_attr_stack(stack);
+       bootstrap_attr_stack(istate, stack);
 
        /*
         * Pop the "info" one that is always at the top of the stack.
@@ -973,7 +978,7 @@ static void prepare_attr_stack(const char *path, int dirlen,
                strbuf_add(&pathbuf, path + pathbuf.len, (len - pathbuf.len));
                strbuf_addf(&pathbuf, "/%s", GITATTRIBUTES_FILE);
 
-               next = read_attr(pathbuf.buf, 0);
+               next = read_attr(istate, pathbuf.buf, 0);
 
                /* reset the pathbuf to not include "/.gitattributes" */
                strbuf_setlen(&pathbuf, len);
@@ -1095,7 +1100,9 @@ static void determine_macros(struct all_attrs_item *all_attrs,
  * If check->check_nr is non-zero, only attributes in check[] are collected.
  * Otherwise all attributes are collected.
  */
-static void collect_some_attrs(const char *path, struct attr_check *check)
+static void collect_some_attrs(const struct index_state *istate,
+                              const char *path,
+                              struct attr_check *check)
 {
        int i, pathlen, rem, dirlen;
        const char *cp, *last_slash = NULL;
@@ -1114,7 +1121,7 @@ static void collect_some_attrs(const char *path, struct attr_check *check)
                dirlen = 0;
        }
 
-       prepare_attr_stack(path, dirlen, &check->stack);
+       prepare_attr_stack(istate, path, dirlen, &check->stack);
        all_attrs_init(&g_attr_hashmap, check);
        determine_macros(check->all_attrs, check->stack);
 
@@ -1136,11 +1143,13 @@ static void collect_some_attrs(const char *path, struct attr_check *check)
        fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem);
 }
 
-int git_check_attr(const char *path, struct attr_check *check)
+int git_check_attr(const struct index_state *istate,
+                  const char *path,
+                  struct attr_check *check)
 {
        int i;
 
-       collect_some_attrs(path, check);
+       collect_some_attrs(istate, path, check);
 
        for (i = 0; i < check->nr; i++) {
                size_t n = check->items[i].attr->attr_nr;
@@ -1153,12 +1162,13 @@ int git_check_attr(const char *path, struct attr_check *check)
        return 0;
 }
 
-void git_all_attrs(const char *path, struct attr_check *check)
+void git_all_attrs(const struct index_state *istate,
+                  const char *path, struct attr_check *check)
 {
        int i;
 
        attr_check_reset(check);
-       collect_some_attrs(path, check);
+       collect_some_attrs(istate, path, check);
 
        for (i = 0; i < check->all_attrs_nr; i++) {
                const char *name = check->all_attrs[i].attr->name;
diff --git a/attr.h b/attr.h
index 442d464..2be86db 100644 (file)
--- a/attr.h
+++ b/attr.h
@@ -1,12 +1,15 @@
 #ifndef ATTR_H
 #define ATTR_H
 
+struct index_state;
+
 /* An attribute is a pointer to this opaque structure */
 struct git_attr;
 
 /* opaque structures used internally for attribute collection */
 struct all_attrs_item;
 struct attr_stack;
+struct index_state;
 
 /*
  * Given a string, return the gitattribute object that
@@ -42,40 +45,41 @@ struct attr_check {
        struct attr_stack *stack;
 };
 
-extern struct attr_check *attr_check_alloc(void);
-extern struct attr_check *attr_check_initl(const char *, ...);
-extern struct attr_check *attr_check_dup(const struct attr_check *check);
+struct attr_check *attr_check_alloc(void);
+struct attr_check *attr_check_initl(const char *, ...);
+struct attr_check *attr_check_dup(const struct attr_check *check);
 
-extern struct attr_check_item *attr_check_append(struct attr_check *check,
-                                                const struct git_attr *attr);
+struct attr_check_item *attr_check_append(struct attr_check *check,
+                                         const struct git_attr *attr);
 
-extern void attr_check_reset(struct attr_check *check);
-extern void attr_check_clear(struct attr_check *check);
-extern void attr_check_free(struct attr_check *check);
+void attr_check_reset(struct attr_check *check);
+void attr_check_clear(struct attr_check *check);
+void attr_check_free(struct attr_check *check);
 
 /*
  * Return the name of the attribute represented by the argument.  The
  * return value is a pointer to a null-delimited string that is part
  * of the internal data structure; it should not be modified or freed.
  */
-extern const char *git_attr_name(const struct git_attr *);
+const char *git_attr_name(const struct git_attr *);
 
-extern int git_check_attr(const char *path, struct attr_check *check);
+int git_check_attr(const struct index_state *istate,
+                  const char *path, struct attr_check *check);
 
 /*
  * Retrieve all attributes that apply to the specified path.
  * check holds the attributes and their values.
  */
-extern void git_all_attrs(const char *path, struct attr_check *check);
+void git_all_attrs(const struct index_state *istate,
+                  const char *path, struct attr_check *check);
 
 enum git_attr_direction {
        GIT_ATTR_CHECKIN,
        GIT_ATTR_CHECKOUT,
        GIT_ATTR_INDEX
 };
-void git_attr_set_direction(enum git_attr_direction new_direction,
-                           struct index_state *istate);
+void git_attr_set_direction(enum git_attr_direction new_direction);
 
-extern void attr_start(void);
+void attr_start(void);
 
 #endif /* ATTR_H */
index a5d9248..34df209 100644 (file)
--- a/bisect.h
+++ b/bisect.h
@@ -1,6 +1,8 @@
 #ifndef BISECT_H
 #define BISECT_H
 
+struct commit_list;
+
 /*
  * Find bisection. If something is found, `reaches` will be the number of
  * commits that the best commit reaches. `all` will be the count of
diff --git a/blame.c b/blame.c
index 58a7036..08c0c6c 100644 (file)
--- a/blame.c
+++ b/blame.c
@@ -90,7 +90,8 @@ static struct blame_origin *get_origin(struct commit *commit, const char *path)
 
 
 
-static void verify_working_tree_path(struct commit *work_tree, const char *path)
+static void verify_working_tree_path(struct repository *repo,
+                                    struct commit *work_tree, const char *path)
 {
        struct commit_list *parents;
        int pos;
@@ -101,15 +102,15 @@ static void verify_working_tree_path(struct commit *work_tree, const char *path)
                unsigned mode;
 
                if (!get_tree_entry(commit_oid, path, &blob_oid, &mode) &&
-                   oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB)
+                   oid_object_info(repo, &blob_oid, NULL) == OBJ_BLOB)
                        return;
        }
 
-       pos = cache_name_pos(path, strlen(path));
+       pos = index_name_pos(repo->index, path, strlen(path));
        if (pos >= 0)
                ; /* path is in the index */
-       else if (-1 - pos < active_nr &&
-                !strcmp(active_cache[-1 - pos]->name, path))
+       else if (-1 - pos < repo->index->cache_nr &&
+                !strcmp(repo->index->cache[-1 - pos]->name, path))
                ; /* path is in the index, unmerged */
        else
                die("no such path '%s' in HEAD", path);
@@ -165,7 +166,8 @@ static void set_commit_buffer_from_strbuf(struct commit *c, struct strbuf *sb)
  * Prepare a dummy commit that represents the work tree (or staged) item.
  * Note that annotating work tree item never works in the reverse.
  */
-static struct commit *fake_working_tree_commit(struct diff_options *opt,
+static struct commit *fake_working_tree_commit(struct repository *repo,
+                                              struct diff_options *opt,
                                               const char *path,
                                               const char *contents_from)
 {
@@ -181,7 +183,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
        unsigned mode;
        struct strbuf msg = STRBUF_INIT;
 
-       read_cache();
+       read_index(repo->index);
        time(&now);
        commit = alloc_commit_node(the_repository);
        commit->object.parsed = 1;
@@ -193,7 +195,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
 
        parent_tail = append_parent(parent_tail, &head_oid);
        append_merge_parents(parent_tail);
-       verify_working_tree_path(commit, path);
+       verify_working_tree_path(repo, commit, path);
 
        origin = make_origin(commit, path);
 
@@ -251,7 +253,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
                if (strbuf_read(&buf, 0, 0) < 0)
                        die_errno("failed to read from stdin");
        }
-       convert_to_git(&the_index, path, buf.buf, buf.len, &buf, 0);
+       convert_to_git(repo->index, path, buf.buf, buf.len, &buf, 0);
        origin->file.ptr = buf.buf;
        origin->file.size = buf.len;
        pretend_object_file(buf.buf, buf.len, OBJ_BLOB, &origin->blob_oid);
@@ -262,27 +264,28 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
         * bits; we are not going to write this index out -- we just
         * want to run "diff-index --cached".
         */
-       discard_cache();
-       read_cache();
+       discard_index(repo->index);
+       read_index(repo->index);
 
        len = strlen(path);
        if (!mode) {
-               int pos = cache_name_pos(path, len);
+               int pos = index_name_pos(repo->index, path, len);
                if (0 <= pos)
-                       mode = active_cache[pos]->ce_mode;
+                       mode = repo->index->cache[pos]->ce_mode;
                else
                        /* Let's not bother reading from HEAD tree */
                        mode = S_IFREG | 0644;
        }
-       ce = make_empty_cache_entry(&the_index, len);
+       ce = make_empty_cache_entry(repo->index, len);
        oidcpy(&ce->oid, &origin->blob_oid);
        memcpy(ce->name, path, len);
        ce->ce_flags = create_ce_flags(0);
        ce->ce_namelen = len;
        ce->ce_mode = create_ce_mode(mode);
-       add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
+       add_index_entry(repo->index, ce,
+                       ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
 
-       cache_tree_invalidate_path(&the_index, path);
+       cache_tree_invalidate_path(repo->index, path);
 
        return commit;
 }
@@ -519,13 +522,14 @@ static void queue_blames(struct blame_scoreboard *sb, struct blame_origin *porig
  *
  * This also fills origin->mode for corresponding tree path.
  */
-static int fill_blob_sha1_and_mode(struct blame_origin *origin)
+static int fill_blob_sha1_and_mode(struct repository *repo,
+                                  struct blame_origin *origin)
 {
        if (!is_null_oid(&origin->blob_oid))
                return 0;
        if (get_tree_entry(&origin->commit->object.oid, origin->path, &origin->blob_oid, &origin->mode))
                goto error_out;
-       if (oid_object_info(the_repository, &origin->blob_oid, NULL) != OBJ_BLOB)
+       if (oid_object_info(repo, &origin->blob_oid, NULL) != OBJ_BLOB)
                goto error_out;
        return 0;
  error_out:
@@ -1767,7 +1771,9 @@ void init_scoreboard(struct blame_scoreboard *sb)
        sb->copy_score = BLAME_DEFAULT_COPY_SCORE;
 }
 
-void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blame_origin **orig)
+void setup_scoreboard(struct blame_scoreboard *sb,
+                     const char *path,
+                     struct blame_origin **orig)
 {
        const char *final_commit_name = NULL;
        struct blame_origin *o;
@@ -1779,6 +1785,9 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam
        if (sb->reverse && sb->contents_from)
                die(_("--contents and --reverse do not blend well."));
 
+       if (!sb->repo)
+               BUG("repo is NULL");
+
        if (!sb->reverse) {
                sb->final = find_single_final(sb->revs, &final_commit_name);
                sb->commits.compare = compare_commits_by_commit_date;
@@ -1800,7 +1809,8 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam
                 * or "--contents".
                 */
                setup_work_tree();
-               sb->final = fake_working_tree_commit(&sb->revs->diffopt,
+               sb->final = fake_working_tree_commit(sb->repo,
+                                                    &sb->revs->diffopt,
                                                     path, sb->contents_from);
                add_pending_object(sb->revs, &(sb->final->object), ":");
        }
@@ -1845,7 +1855,7 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam
        }
        else {
                o = get_origin(sb->final, path);
-               if (fill_blob_sha1_and_mode(o))
+               if (fill_blob_sha1_and_mode(sb->repo, o))
                        die(_("no such path %s in %s"), path, final_commit_name);
 
                if (sb->revs->diffopt.flags.allow_textconv &&
diff --git a/blame.h b/blame.h
index 2092f95..be3a895 100644 (file)
--- a/blame.h
+++ b/blame.h
@@ -102,6 +102,7 @@ struct blame_scoreboard {
        struct commit *final;
        /* Priority queue for commits with unassigned blame records */
        struct prio_queue commits;
+       struct repository *repo;
        struct rev_info *revs;
        const char *path;
 
@@ -159,18 +160,22 @@ static inline struct blame_origin *blame_origin_incref(struct blame_origin *o)
                o->refcnt++;
        return o;
 }
-extern void blame_origin_decref(struct blame_origin *o);
-
-extern void blame_coalesce(struct blame_scoreboard *sb);
-extern void blame_sort_final(struct blame_scoreboard *sb);
-extern unsigned blame_entry_score(struct blame_scoreboard *sb, struct blame_entry *e);
-extern void assign_blame(struct blame_scoreboard *sb, int opt);
-extern const char *blame_nth_line(struct blame_scoreboard *sb, long lno);
-
-extern void init_scoreboard(struct blame_scoreboard *sb);
-extern void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blame_origin **orig);
-
-extern struct blame_entry *blame_entry_prepend(struct blame_entry *head, long start, long end, struct blame_origin *o);
+void blame_origin_decref(struct blame_origin *o);
+
+void blame_coalesce(struct blame_scoreboard *sb);
+void blame_sort_final(struct blame_scoreboard *sb);
+unsigned blame_entry_score(struct blame_scoreboard *sb, struct blame_entry *e);
+void assign_blame(struct blame_scoreboard *sb, int opt);
+const char *blame_nth_line(struct blame_scoreboard *sb, long lno);
+
+void init_scoreboard(struct blame_scoreboard *sb);
+void setup_scoreboard(struct blame_scoreboard *sb,
+                     const char *path,
+                     struct blame_origin **orig);
+
+struct blame_entry *blame_entry_prepend(struct blame_entry *head,
+                                       long start, long end,
+                                       struct blame_origin *o);
 
 extern struct blame_origin *get_blame_suspects(struct commit *commit);
 
index 473d0a9..5cace45 100644 (file)
--- a/branch.h
+++ b/branch.h
@@ -1,6 +1,19 @@
 #ifndef BRANCH_H
 #define BRANCH_H
 
+struct strbuf;
+
+enum branch_track {
+       BRANCH_TRACK_UNSPECIFIED = -1,
+       BRANCH_TRACK_NEVER = 0,
+       BRANCH_TRACK_REMOTE,
+       BRANCH_TRACK_ALWAYS,
+       BRANCH_TRACK_EXPLICIT,
+       BRANCH_TRACK_OVERRIDE
+};
+
+extern enum branch_track git_branch_track;
+
 /* Functions for acting on the information about branches. */
 
 /*
index 0362f1c..99206df 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -201,6 +201,7 @@ extern int cmd_prune(int argc, const char **argv, const char *prefix);
 extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);
 extern int cmd_pull(int argc, const char **argv, const char *prefix);
 extern int cmd_push(int argc, const char **argv, const char *prefix);
+extern int cmd_range_diff(int argc, const char **argv, const char *prefix);
 extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_rebase__helper(int argc, const char **argv, const char *prefix);
 extern int cmd_receive_pack(int argc, const char **argv, const char *prefix);
index 8a155dd..9916498 100644 (file)
@@ -40,7 +40,7 @@ static void chmod_pathspec(struct pathspec *pathspec, char flip)
        for (i = 0; i < active_nr; i++) {
                struct cache_entry *ce = active_cache[i];
 
-               if (pathspec && !ce_path_match(ce, pathspec, NULL))
+               if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
                        continue;
 
                if (chmod_cache_entry(ce, flip) < 0)
@@ -135,7 +135,7 @@ static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
                        continue; /* do not touch unmerged paths */
                if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
                        continue; /* do not touch non blobs */
-               if (pathspec && !ce_path_match(ce, pathspec, NULL))
+               if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
                        continue;
                retval |= add_file_to_cache(ce->name, flags | HASH_RENORMALIZE);
        }
@@ -155,7 +155,7 @@ static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec,
        i = dir->nr;
        while (--i >= 0) {
                struct dir_entry *entry = *src++;
-               if (dir_path_match(entry, pathspec, prefix, seen))
+               if (dir_path_match(&the_index, entry, pathspec, prefix, seen))
                        *dst++ = entry;
        }
        dir->nr = dst - dir->entries;
@@ -304,7 +304,8 @@ static struct option builtin_add_options[] = {
        OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
        OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
        OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
-       OPT_STRING( 0 , "chmod", &chmod_arg, N_("(+/-)x"), N_("override the executable bit of the listed files")),
+       OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
+                  N_("override the executable bit of the listed files")),
        OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
                        N_("warn when adding an embedded repository")),
        OPT_END(),
index 2c19e69..9f7ecf6 100644 (file)
@@ -1464,7 +1464,7 @@ static int run_apply(const struct am_state *state, const char *index_file)
        int force_apply = 0;
        int options = 0;
 
-       if (init_apply_state(&apply_state, NULL))
+       if (init_apply_state(&apply_state, the_repository, NULL))
                BUG("init_apply_state() failed");
 
        argv_array_push(&apply_opts, "apply");
index 48d3989..3f099b9 100644 (file)
@@ -16,7 +16,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix)
        int ret;
        struct apply_state state;
 
-       if (init_apply_state(&state, prefix))
+       if (init_apply_state(&state, the_repository, prefix))
                exit(128);
 
        argc = apply_parse_options(argc, argv,
index 73971d0..e74f675 100644 (file)
@@ -105,5 +105,5 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
 
        setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
 
-       return write_archive(argc, argv, prefix, output, 0);
+       return write_archive(argc, argv, prefix, the_repository, output, 0);
 }
index 97f6eca..c2da673 100644 (file)
@@ -988,6 +988,7 @@ parse_done:
        sb.revs = &revs;
        sb.contents_from = contents_from;
        sb.reverse = reverse;
+       sb.repo = the_repository;
        setup_scoreboard(&sb, path, &o);
        lno = sb.num_lines;
 
index 4fc55c3..bbd006a 100644 (file)
@@ -74,6 +74,14 @@ define_list_config_array(color_branch_slots);
 static int git_branch_config(const char *var, const char *value, void *cb)
 {
        const char *slot_name;
+       struct ref_sorting **sorting_tail = (struct ref_sorting **)cb;
+
+       if (!strcmp(var, "branch.sort")) {
+               if (!value)
+                       return config_error_nonbool(var);
+               parse_ref_sorting(sorting_tail, value);
+               return 0;
+       }
 
        if (starts_with(var, "column."))
                return git_column_config(var, value, "branch", &colopts);
@@ -653,7 +661,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage_with_options(builtin_branch_usage, options);
 
-       git_config(git_branch_config, NULL);
+       git_config(git_branch_config, sorting_tail);
 
        track = git_branch_track;
 
index 4a44b24..64ec174 100644 (file)
@@ -21,6 +21,7 @@ struct batch_options {
        int print_contents;
        int buffer_output;
        int all_objects;
+       int unordered;
        int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */
        const char *format;
 };
@@ -39,7 +40,7 @@ static int filter_object(const char *path, unsigned mode,
                             oid_to_hex(oid), path);
        if ((type == OBJ_BLOB) && S_ISREG(mode)) {
                struct strbuf strbuf = STRBUF_INIT;
-               if (convert_to_working_tree(path, *buf, *size, &strbuf)) {
+               if (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf)) {
                        free(*buf);
                        *size = strbuf.len;
                        *buf = strbuf_detach(&strbuf, NULL);
@@ -337,11 +338,11 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d
        }
 }
 
-static void batch_object_write(const char *obj_name, struct batch_options *opt,
+static void batch_object_write(const char *obj_name,
+                              struct strbuf *scratch,
+                              struct batch_options *opt,
                               struct expand_data *data)
 {
-       struct strbuf buf = STRBUF_INIT;
-
        if (!data->skip_object_info &&
            oid_object_info_extended(the_repository, &data->oid, &data->info,
                                     OBJECT_INFO_LOOKUP_REPLACE) < 0) {
@@ -351,10 +352,10 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,
                return;
        }
 
-       strbuf_expand(&buf, opt->format, expand_format, data);
-       strbuf_addch(&buf, '\n');
-       batch_write(opt, buf.buf, buf.len);
-       strbuf_release(&buf);
+       strbuf_reset(scratch);
+       strbuf_expand(scratch, opt->format, expand_format, data);
+       strbuf_addch(scratch, '\n');
+       batch_write(opt, scratch->buf, scratch->len);
 
        if (opt->print_contents) {
                print_object_or_die(opt, data);
@@ -362,7 +363,9 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,
        }
 }
 
-static void batch_one_object(const char *obj_name, struct batch_options *opt,
+static void batch_one_object(const char *obj_name,
+                            struct strbuf *scratch,
+                            struct batch_options *opt,
                             struct expand_data *data)
 {
        struct object_context ctx;
@@ -404,42 +407,70 @@ static void batch_one_object(const char *obj_name, struct batch_options *opt,
                return;
        }
 
-       batch_object_write(obj_name, opt, data);
+       batch_object_write(obj_name, scratch, opt, data);
 }
 
 struct object_cb_data {
        struct batch_options *opt;
        struct expand_data *expand;
+       struct oidset *seen;
+       struct strbuf *scratch;
 };
 
 static int batch_object_cb(const struct object_id *oid, void *vdata)
 {
        struct object_cb_data *data = vdata;
        oidcpy(&data->expand->oid, oid);
-       batch_object_write(NULL, data->opt, data->expand);
+       batch_object_write(NULL, data->scratch, data->opt, data->expand);
        return 0;
 }
 
-static int batch_loose_object(const struct object_id *oid,
-                             const char *path,
-                             void *data)
+static int collect_loose_object(const struct object_id *oid,
+                               const char *path,
+                               void *data)
 {
        oid_array_append(data, oid);
        return 0;
 }
 
-static int batch_packed_object(const struct object_id *oid,
-                              struct packed_git *pack,
-                              uint32_t pos,
-                              void *data)
+static int collect_packed_object(const struct object_id *oid,
+                                struct packed_git *pack,
+                                uint32_t pos,
+                                void *data)
 {
        oid_array_append(data, oid);
        return 0;
 }
 
+static int batch_unordered_object(const struct object_id *oid, void *vdata)
+{
+       struct object_cb_data *data = vdata;
+
+       if (oidset_insert(data->seen, oid))
+               return 0;
+
+       return batch_object_cb(oid, data);
+}
+
+static int batch_unordered_loose(const struct object_id *oid,
+                                const char *path,
+                                void *data)
+{
+       return batch_unordered_object(oid, data);
+}
+
+static int batch_unordered_packed(const struct object_id *oid,
+                                 struct packed_git *pack,
+                                 uint32_t pos,
+                                 void *data)
+{
+       return batch_unordered_object(oid, data);
+}
+
 static int batch_objects(struct batch_options *opt)
 {
-       struct strbuf buf = STRBUF_INIT;
+       struct strbuf input = STRBUF_INIT;
+       struct strbuf output = STRBUF_INIT;
        struct expand_data data;
        int save_warning;
        int retval = 0;
@@ -454,8 +485,9 @@ static int batch_objects(struct batch_options *opt)
         */
        memset(&data, 0, sizeof(data));
        data.mark_query = 1;
-       strbuf_expand(&buf, opt->format, expand_format, &data);
+       strbuf_expand(&output, opt->format, expand_format, &data);
        data.mark_query = 0;
+       strbuf_release(&output);
        if (opt->cmdmode)
                data.split_on_whitespace = 1;
 
@@ -473,19 +505,37 @@ static int batch_objects(struct batch_options *opt)
                data.info.typep = &data.type;
 
        if (opt->all_objects) {
-               struct oid_array sa = OID_ARRAY_INIT;
                struct object_cb_data cb;
 
-               for_each_loose_object(batch_loose_object, &sa, 0);
-               for_each_packed_object(batch_packed_object, &sa, 0);
                if (repository_format_partial_clone)
                        warning("This repository has extensions.partialClone set. Some objects may not be loaded.");
 
                cb.opt = opt;
                cb.expand = &data;
-               oid_array_for_each_unique(&sa, batch_object_cb, &cb);
+               cb.scratch = &output;
+
+               if (opt->unordered) {
+                       struct oidset seen = OIDSET_INIT;
+
+                       cb.seen = &seen;
+
+                       for_each_loose_object(batch_unordered_loose, &cb, 0);
+                       for_each_packed_object(batch_unordered_packed, &cb,
+                                              FOR_EACH_OBJECT_PACK_ORDER);
+
+                       oidset_clear(&seen);
+               } else {
+                       struct oid_array sa = OID_ARRAY_INIT;
+
+                       for_each_loose_object(collect_loose_object, &sa, 0);
+                       for_each_packed_object(collect_packed_object, &sa, 0);
+
+                       oid_array_for_each_unique(&sa, batch_object_cb, &cb);
+
+                       oid_array_clear(&sa);
+               }
 
-               oid_array_clear(&sa);
+               strbuf_release(&output);
                return 0;
        }
 
@@ -499,14 +549,14 @@ static int batch_objects(struct batch_options *opt)
        save_warning = warn_on_object_refname_ambiguity;
        warn_on_object_refname_ambiguity = 0;
 
-       while (strbuf_getline(&buf, stdin) != EOF) {
+       while (strbuf_getline(&input, stdin) != EOF) {
                if (data.split_on_whitespace) {
                        /*
                         * Split at first whitespace, tying off the beginning
                         * of the string and saving the remainder (or NULL) in
                         * data.rest.
                         */
-                       char *p = strpbrk(buf.buf, " \t");
+                       char *p = strpbrk(input.buf, " \t");
                        if (p) {
                                while (*p && strchr(" \t", *p))
                                        *p++ = '\0';
@@ -514,10 +564,11 @@ static int batch_objects(struct batch_options *opt)
                        data.rest = p;
                }
 
-               batch_one_object(buf.buf, opt, &data);
+               batch_one_object(input.buf, &output, opt, &data);
        }
 
-       strbuf_release(&buf);
+       strbuf_release(&input);
+       strbuf_release(&output);
        warn_on_object_refname_ambiguity = save_warning;
        return retval;
 }
@@ -586,6 +637,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
                         N_("follow in-tree symlinks (used with --batch or --batch-check)")),
                OPT_BOOL(0, "batch-all-objects", &batch.all_objects,
                         N_("show all objects with --batch or --batch-check")),
+               OPT_BOOL(0, "unordered", &batch.unordered,
+                        N_("do not order --batch-all-objects output")),
                OPT_END()
        };
 
index 91444dc..c05573f 100644 (file)
@@ -63,9 +63,9 @@ static void check_attr(const char *prefix,
                prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
 
        if (collect_all) {
-               git_all_attrs(full_path, check);
+               git_all_attrs(&the_index, full_path, check);
        } else {
-               if (git_check_attr(full_path, check))
+               if (git_check_attr(&the_index, full_path, check))
                        die("git_check_attr died");
        }
        output_attr(check, file);
@@ -120,7 +120,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
        }
 
        if (cached_attrs)
-               git_attr_set_direction(GIT_ATTR_INDEX, NULL);
+               git_attr_set_direction(GIT_ATTR_INDEX);
 
        doubledash = -1;
        for (i = 0; doubledash < 0 && i < argc; i++) {
index a730f6a..d92db62 100644 (file)
@@ -190,6 +190,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
 
        argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
                        builtin_checkout_index_usage, 0);
+       state.istate = &the_index;
        state.force = force;
        state.quiet = quiet;
        state.not_new = not_new;
index cb6bb76..29ef500 100644 (file)
@@ -318,7 +318,7 @@ static int checkout_paths(const struct checkout_opts *opts,
                 * match_pathspec() for _all_ entries when
                 * opts->source_tree != NULL.
                 */
-               if (ce_path_match(ce, &opts->pathspec, ps_matched))
+               if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched))
                        ce->ce_flags |= CE_MATCHED;
        }
 
index ab402c2..8d9a7dc 100644 (file)
@@ -976,7 +976,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
                        continue;
 
                if (pathspec.nr)
-                       matches = dir_path_match(ent, &pathspec, 0, NULL);
+                       matches = dir_path_match(&the_index, ent, &pathspec, 0, NULL);
 
                if (pathspec.nr && !matches)
                        continue;
index 213fca2..0d9828e 100644 (file)
@@ -251,7 +251,7 @@ static int list_paths(struct string_list *list, const char *with_tree,
 
                if (ce->ce_flags & CE_UPDATE)
                        continue;
-               if (!ce_path_match(ce, pattern, m))
+               if (!ce_path_match(&the_index, ce, pattern, m))
                        continue;
                item = string_list_insert(list, ce->name);
                if (ce_skip_worktree(ce))
index 91ba670..d07bf2e 100644 (file)
@@ -163,9 +163,11 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
                int saved_nrl = 0;
                int saved_dcctc = 0;
 
-               if (opt->diffopt.detect_rename)
-                       opt->diffopt.setup |= (DIFF_SETUP_USE_SIZE_CACHE |
-                                              DIFF_SETUP_USE_CACHE);
+               if (opt->diffopt.detect_rename) {
+                       if (!the_index.cache)
+                               read_index(&the_index);
+                       opt->diffopt.setup |= DIFF_SETUP_USE_SIZE_CACHE;
+               }
                while (fgets(line, sizeof(line), stdin)) {
                        struct object_id oid;
 
index 3018e61..cdd585c 100644 (file)
@@ -703,7 +703,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
                        1, PARSE_OPT_NONEG | PARSE_OPT_HIDDEN),
                OPT_BOOL(0, "symlinks", &symlinks,
                         N_("use symlinks in dir-diff mode")),
-               OPT_STRING('t', "tool", &difftool_cmd, N_("<tool>"),
+               OPT_STRING('t', "tool", &difftool_cmd, N_("tool"),
                           N_("use the specified diff tool")),
                OPT_BOOL(0, "tool-help", &tool_help,
                         N_("print a list of diff tools that may be used with "
@@ -711,7 +711,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
                OPT_BOOL(0, "trust-exit-code", &trust_exit_code,
                         N_("make 'git-difftool' exit when an invoked diff "
                            "tool returns a non - zero exit code")),
-               OPT_STRING('x', "extcmd", &extcmd, N_("<command>"),
+               OPT_STRING('x', "extcmd", &extcmd, N_("command"),
                           N_("specify a custom command for viewing diffs")),
                OPT_END()
        };
index ee5a1bd..601f801 100644 (file)
@@ -497,7 +497,7 @@ static int grep_cache(struct grep_opt *opt, struct repository *repo,
                strbuf_addstr(&name, ce->name);
 
                if (S_ISREG(ce->ce_mode) &&
-                   match_pathspec(pathspec, name.buf, name.len, 0, NULL,
+                   match_pathspec(repo->index, pathspec, name.buf, name.len, 0, NULL,
                                   S_ISDIR(ce->ce_mode) ||
                                   S_ISGITLINK(ce->ce_mode))) {
                        /*
@@ -515,7 +515,7 @@ static int grep_cache(struct grep_opt *opt, struct repository *repo,
                                hit |= grep_file(opt, name.buf);
                        }
                } else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
-                          submodule_path_match(pathspec, name.buf, NULL)) {
+                          submodule_path_match(repo->index, pathspec, name.buf, NULL)) {
                        hit |= grep_submodule(opt, repo, pathspec, NULL, ce->name, ce->name);
                } else {
                        continue;
@@ -679,7 +679,7 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,
 
        fill_directory(&dir, &the_index, pathspec);
        for (i = 0; i < dir.nr; i++) {
-               if (!dir_path_match(dir.entries[i], pathspec, 0, NULL))
+               if (!dir_path_match(&the_index, dir.entries[i], pathspec, 0, NULL))
                        continue;
                hit |= grep_file(opt, dir.entries[i]->name);
                if (hit && opt->status_only)
index 88bb201..7f9919a 100644 (file)
@@ -63,7 +63,7 @@ static void write_eolinfo(const struct index_state *istate,
                struct stat st;
                const char *i_txt = "";
                const char *w_txt = "";
-               const char *a_txt = get_convert_attr_ascii(path);
+               const char *a_txt = get_convert_attr_ascii(istate, path);
                if (ce && S_ISREG(ce->ce_mode))
                        i_txt = get_cached_convert_stats_ascii(istate,
                                                               ce->name);
@@ -121,18 +121,19 @@ static void print_debug(const struct cache_entry *ce)
        }
 }
 
-static void show_dir_entry(const char *tag, struct dir_entry *ent)
+static void show_dir_entry(const struct index_state *istate,
+                          const char *tag, struct dir_entry *ent)
 {
        int len = max_prefix_len;
 
        if (len > ent->len)
                die("git ls-files: internal error - directory entry not superset of prefix");
 
-       if (!dir_path_match(ent, &pathspec, len, ps_matched))
+       if (!dir_path_match(istate, ent, &pathspec, len, ps_matched))
                return;
 
        fputs(tag, stdout);
-       write_eolinfo(NULL, NULL, ent->name);
+       write_eolinfo(istate, NULL, ent->name);
        write_name(ent->name);
 }
 
@@ -145,7 +146,7 @@ static void show_other_files(const struct index_state *istate,
                struct dir_entry *ent = dir->entries[i];
                if (!index_name_is_other(istate, ent->name, ent->len))
                        continue;
-               show_dir_entry(tag_other, ent);
+               show_dir_entry(istate, tag_other, ent);
        }
 }
 
@@ -196,7 +197,7 @@ static void show_killed_files(const struct index_state *istate,
                        }
                }
                if (killed)
-                       show_dir_entry(tag_killed, dir->entries[i]);
+                       show_dir_entry(istate, tag_killed, dir->entries[i]);
        }
 }
 
@@ -228,7 +229,7 @@ static void show_ce(struct repository *repo, struct dir_struct *dir,
        if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
            is_submodule_active(repo, ce->name)) {
                show_submodule(repo, dir, ce->name);
-       } else if (match_pathspec(&pathspec, fullname, strlen(fullname),
+       } else if (match_pathspec(repo->index, &pathspec, fullname, strlen(fullname),
                                  max_prefix_len, ps_matched,
                                  S_ISDIR(ce->ce_mode) ||
                                  S_ISGITLINK(ce->ce_mode))) {
@@ -264,7 +265,7 @@ static void show_ru_info(const struct index_state *istate)
                len = strlen(path);
                if (len < max_prefix_len)
                        continue; /* outside of the prefix */
-               if (!match_pathspec(&pathspec, path, len,
+               if (!match_pathspec(istate, &pathspec, path, len,
                                    max_prefix_len, ps_matched, 0))
                        continue; /* uninterested */
                for (i = 0; i < 3; i++) {
index 80c880e..d1144a8 100644 (file)
@@ -951,7 +951,7 @@ static int no_try_delta(const char *path)
 
        if (!check)
                check = attr_check_initl("delta", NULL);
-       if (git_check_attr(path, check))
+       if (git_check_attr(&the_index, path, check))
                return 0;
        if (ATTR_FALSE(check->items[0].value))
                return 1;
@@ -2041,10 +2041,6 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
        delta_buf = create_delta(src->index, trg->data, trg_size, &delta_size, max_size);
        if (!delta_buf)
                return 0;
-       if (delta_size >= (1U << OE_DELTA_SIZE_BITS)) {
-               free(delta_buf);
-               return 0;
-       }
 
        if (DELTA(trg_entry)) {
                /* Prefer only shallower same-sized deltas. */
@@ -2303,6 +2299,7 @@ static void init_threaded_search(void)
        pthread_mutex_init(&cache_mutex, NULL);
        pthread_mutex_init(&progress_mutex, NULL);
        pthread_cond_init(&progress_cond, NULL);
+       pthread_mutex_init(&to_pack.lock, NULL);
        old_try_to_free_routine = set_try_to_free_routine(try_to_free_from_threads);
 }
 
@@ -3135,7 +3132,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                OPT_BOOL(0, "all-progress-implied",
                         &all_progress_implied,
                         N_("similar to --all-progress when progress meter is shown")),
-               { OPTION_CALLBACK, 0, "index-version", NULL, N_("version[,offset]"),
+               { OPTION_CALLBACK, 0, "index-version", NULL, N_("<version>[,<offset>]"),
                  N_("write the pack index file in the specified idx format version"),
                  0, option_parse_index_version },
                OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit,
index 4ff525e..a9e7b55 100644 (file)
@@ -3,6 +3,7 @@
 #include "progress.h"
 #include "parse-options.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static const char * const prune_packed_usage[] = {
        N_("git prune-packed [-n | --dry-run] [-q | --quiet]"),
index 4e78935..53bc5fa 100644 (file)
@@ -48,11 +48,11 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value,
                return REBASE_FALSE;
        else if (v > 0)
                return REBASE_TRUE;
-       else if (!strcmp(value, "preserve"))
+       else if (!strcmp(value, "preserve") || !strcmp(value, "p"))
                return REBASE_PRESERVE;
-       else if (!strcmp(value, "merges"))
+       else if (!strcmp(value, "merges") || !strcmp(value, "m"))
                return REBASE_MERGES;
-       else if (!strcmp(value, "interactive"))
+       else if (!strcmp(value, "interactive") || !strcmp(value, "i"))
                return REBASE_INTERACTIVE;
 
        if (fatal)
index 9cd8e8c..ef4c188 100644 (file)
@@ -558,9 +558,9 @@ int cmd_push(int argc, const char **argv, const char *prefix)
                OPT_BIT( 0,  "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
                OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
                { OPTION_CALLBACK,
-                 0, CAS_OPT_NAME, &cas, N_("refname>:<expect"),
+                 0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"),
                  N_("require old value of ref to be at this value"),
-                 PARSE_OPT_OPTARG, parseopt_push_cas_option },
+                 PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option },
                { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, "check|on-demand|no",
                        N_("control recursive pushing of submodules"),
                        PARSE_OPT_OPTARG, option_parse_recurse_submodules },
diff --git a/builtin/range-diff.c b/builtin/range-diff.c
new file mode 100644 (file)
index 0000000..f52d45d
--- /dev/null
@@ -0,0 +1,116 @@
+#include "cache.h"
+#include "builtin.h"
+#include "parse-options.h"
+#include "range-diff.h"
+#include "config.h"
+
+static const char * const builtin_range_diff_usage[] = {
+N_("git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"),
+N_("git range-diff [<options>] <old-tip>...<new-tip>"),
+N_("git range-diff [<options>] <base> <old-tip> <new-tip>"),
+NULL
+};
+
+static struct strbuf *output_prefix_cb(struct diff_options *opt, void *data)
+{
+       return data;
+}
+
+int cmd_range_diff(int argc, const char **argv, const char *prefix)
+{
+       int creation_factor = 60;
+       struct diff_options diffopt = { NULL };
+       int simple_color = -1;
+       struct option options[] = {
+               OPT_INTEGER(0, "creation-factor", &creation_factor,
+                           N_("Percentage by which creation is weighted")),
+               OPT_BOOL(0, "no-dual-color", &simple_color,
+                           N_("color both diff and diff-between-diffs")),
+               OPT_END()
+       };
+       int i, j, res = 0;
+       struct strbuf four_spaces = STRBUF_INIT;
+       struct strbuf range1 = STRBUF_INIT, range2 = STRBUF_INIT;
+
+       git_config(git_diff_ui_config, NULL);
+
+       diff_setup(&diffopt);
+       diffopt.output_format = DIFF_FORMAT_PATCH;
+       diffopt.flags.suppress_diff_headers = 1;
+       diffopt.output_prefix = output_prefix_cb;
+       strbuf_addstr(&four_spaces, "    ");
+       diffopt.output_prefix_data = &four_spaces;
+
+       argc = parse_options(argc, argv, NULL, options,
+                            builtin_range_diff_usage, PARSE_OPT_KEEP_UNKNOWN |
+                            PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0);
+
+       for (i = j = 1; i < argc && strcmp("--", argv[i]); ) {
+               int c = diff_opt_parse(&diffopt, argv + i, argc - i, prefix);
+
+               if (!c)
+                       argv[j++] = argv[i++];
+               else
+                       i += c;
+       }
+       while (i < argc)
+               argv[j++] = argv[i++];
+       argc = j;
+       diff_setup_done(&diffopt);
+
+       /* Make sure that there are no unparsed options */
+       argc = parse_options(argc, argv, NULL,
+                            options + ARRAY_SIZE(options) - 1, /* OPT_END */
+                            builtin_range_diff_usage, 0);
+
+       if (simple_color < 1) {
+               if (!simple_color)
+                       /* force color when --dual-color was used */
+                       diffopt.use_color = 1;
+               diffopt.flags.dual_color_diffed_diffs = 1;
+       }
+
+       if (argc == 2) {
+               if (!strstr(argv[0], ".."))
+                       die(_("no .. in range: '%s'"), argv[0]);
+               strbuf_addstr(&range1, argv[0]);
+
+               if (!strstr(argv[1], ".."))
+                       die(_("no .. in range: '%s'"), argv[1]);
+               strbuf_addstr(&range2, argv[1]);
+       } else if (argc == 3) {
+               strbuf_addf(&range1, "%s..%s", argv[0], argv[1]);
+               strbuf_addf(&range2, "%s..%s", argv[0], argv[2]);
+       } else if (argc == 1) {
+               const char *b = strstr(argv[0], "..."), *a = argv[0];
+               int a_len;
+
+               if (!b) {
+                       error(_("single arg format must be symmetric range"));
+                       usage_with_options(builtin_range_diff_usage, options);
+               }
+
+               a_len = (int)(b - a);
+               if (!a_len) {
+                       a = "HEAD";
+                       a_len = strlen(a);
+               }
+               b += 3;
+               if (!*b)
+                       b = "HEAD";
+               strbuf_addf(&range1, "%s..%.*s", b, a_len, a);
+               strbuf_addf(&range2, "%.*s..%s", a_len, a, b);
+       } else {
+               error(_("need two commit ranges"));
+               usage_with_options(builtin_range_diff_usage, options);
+       }
+
+       res = show_range_diff(range1.buf, range2.buf, creation_factor,
+                             &diffopt);
+
+       strbuf_release(&range1);
+       strbuf_release(&range2);
+       strbuf_release(&four_spaces);
+
+       return res;
+}
index ebc43eb..fbbc98e 100644 (file)
@@ -133,7 +133,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
                         N_("same as -m, but discard unmerged entries")),
                { OPTION_STRING, 0, "prefix", &opts.prefix, N_("<subdirectory>/"),
                  N_("read the tree into the index under <subdirectory>/"),
-                 PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP },
+                 PARSE_OPT_NONEG },
                OPT_BOOL('u', NULL, &opts.update,
                         N_("update working tree with merge result")),
                { OPTION_CALLBACK, 0, "exclude-per-directory", &opts,
index 6c636e1..d588603 100644 (file)
@@ -8,6 +8,8 @@
 #include "strbuf.h"
 #include "string-list.h"
 #include "argv-array.h"
+#include "packfile.h"
+#include "object-store.h"
 
 static int delta_base_offset = 1;
 static int pack_kept_objects = -1;
@@ -83,7 +85,7 @@ static void remove_pack_on_signal(int signo)
 
 /*
  * Adds all packs hex strings to the fname list, which do not
- * have a corresponding .keep or .promisor file. These packs are not to
+ * have a corresponding .keep file. These packs are not to
  * be kept if we are going to pack everything into one file.
  */
 static void get_non_kept_pack_filenames(struct string_list *fname_list,
@@ -111,8 +113,7 @@ static void get_non_kept_pack_filenames(struct string_list *fname_list,
 
                fname = xmemdupz(e->d_name, len);
 
-               if (!file_exists(mkpath("%s/%s.keep", packdir, fname)) &&
-                   !file_exists(mkpath("%s/%s.promisor", packdir, fname)))
+               if (!file_exists(mkpath("%s/%s.keep", packdir, fname)))
                        string_list_append_nodup(fname_list, fname);
                else
                        free(fname);
@@ -122,7 +123,7 @@ static void get_non_kept_pack_filenames(struct string_list *fname_list,
 
 static void remove_redundant_pack(const char *dir_name, const char *base_name)
 {
-       const char *exts[] = {".pack", ".idx", ".keep", ".bitmap"};
+       const char *exts[] = {".pack", ".idx", ".keep", ".bitmap", ".promisor"};
        int i;
        struct strbuf buf = STRBUF_INIT;
        size_t plen;
@@ -138,6 +139,117 @@ static void remove_redundant_pack(const char *dir_name, const char *base_name)
        strbuf_release(&buf);
 }
 
+struct pack_objects_args {
+       const char *window;
+       const char *window_memory;
+       const char *depth;
+       const char *threads;
+       const char *max_pack_size;
+       int no_reuse_delta;
+       int no_reuse_object;
+       int quiet;
+       int local;
+};
+
+static void prepare_pack_objects(struct child_process *cmd,
+                                const struct pack_objects_args *args)
+{
+       argv_array_push(&cmd->args, "pack-objects");
+       if (args->window)
+               argv_array_pushf(&cmd->args, "--window=%s", args->window);
+       if (args->window_memory)
+               argv_array_pushf(&cmd->args, "--window-memory=%s", args->window_memory);
+       if (args->depth)
+               argv_array_pushf(&cmd->args, "--depth=%s", args->depth);
+       if (args->threads)
+               argv_array_pushf(&cmd->args, "--threads=%s", args->threads);
+       if (args->max_pack_size)
+               argv_array_pushf(&cmd->args, "--max-pack-size=%s", args->max_pack_size);
+       if (args->no_reuse_delta)
+               argv_array_pushf(&cmd->args, "--no-reuse-delta");
+       if (args->no_reuse_object)
+               argv_array_pushf(&cmd->args, "--no-reuse-object");
+       if (args->local)
+               argv_array_push(&cmd->args,  "--local");
+       if (args->quiet)
+               argv_array_push(&cmd->args,  "--quiet");
+       if (delta_base_offset)
+               argv_array_push(&cmd->args,  "--delta-base-offset");
+       argv_array_push(&cmd->args, packtmp);
+       cmd->git_cmd = 1;
+       cmd->out = -1;
+}
+
+/*
+ * Write oid to the given struct child_process's stdin, starting it first if
+ * necessary.
+ */
+static int write_oid(const struct object_id *oid, struct packed_git *pack,
+                    uint32_t pos, void *data)
+{
+       struct child_process *cmd = data;
+
+       if (cmd->in == -1) {
+               if (start_command(cmd))
+                       die("Could not start pack-objects to repack promisor objects");
+       }
+
+       xwrite(cmd->in, oid_to_hex(oid), GIT_SHA1_HEXSZ);
+       xwrite(cmd->in, "\n", 1);
+       return 0;
+}
+
+static void repack_promisor_objects(const struct pack_objects_args *args,
+                                   struct string_list *names)
+{
+       struct child_process cmd = CHILD_PROCESS_INIT;
+       FILE *out;
+       struct strbuf line = STRBUF_INIT;
+
+       prepare_pack_objects(&cmd, args);
+       cmd.in = -1;
+
+       /*
+        * NEEDSWORK: Giving pack-objects only the OIDs without any ordering
+        * hints may result in suboptimal deltas in the resulting pack. See if
+        * the OIDs can be sent with fake paths such that pack-objects can use a
+        * {type -> existing pack order} ordering when computing deltas instead
+        * of a {type -> size} ordering, which may produce better deltas.
+        */
+       for_each_packed_object(write_oid, &cmd,
+                              FOR_EACH_OBJECT_PROMISOR_ONLY);
+
+       if (cmd.in == -1)
+               /* No packed objects; cmd was never started */
+               return;
+
+       close(cmd.in);
+
+       out = xfdopen(cmd.out, "r");
+       while (strbuf_getline_lf(&line, out) != EOF) {
+               char *promisor_name;
+               int fd;
+               if (line.len != 40)
+                       die("repack: Expecting 40 character sha1 lines only from pack-objects.");
+               string_list_append(names, line.buf);
+
+               /*
+                * pack-objects creates the .pack and .idx files, but not the
+                * .promisor file. Create the .promisor file, which is empty.
+                */
+               promisor_name = mkpathdup("%s-%s.promisor", packtmp,
+                                         line.buf);
+               fd = open(promisor_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
+               if (fd < 0)
+                       die_errno("unable to create '%s'", promisor_name);
+               close(fd);
+               free(promisor_name);
+       }
+       fclose(out);
+       if (finish_command(&cmd))
+               die("Could not finish pack-objects to repack promisor objects");
+}
+
 #define ALL_INTO_ONE 1
 #define LOOSEN_UNREACHABLE 2
 
@@ -150,6 +262,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                {".pack"},
                {".idx"},
                {".bitmap", 1},
+               {".promisor", 1},
        };
        struct child_process cmd = CHILD_PROCESS_INIT;
        struct string_list_item *item;
@@ -165,15 +278,9 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
        int delete_redundant = 0;
        const char *unpack_unreachable = NULL;
        int keep_unreachable = 0;
-       const char *window = NULL, *window_memory = NULL;
-       const char *depth = NULL;
-       const char *threads = NULL;
-       const char *max_pack_size = NULL;
        struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
-       int no_reuse_delta = 0, no_reuse_object = 0;
        int no_update_server_info = 0;
-       int quiet = 0;
-       int local = 0;
+       struct pack_objects_args po_args = {NULL};
 
        struct option builtin_repack_options[] = {
                OPT_BIT('a', NULL, &pack_everything,
@@ -183,14 +290,14 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                                   LOOSEN_UNREACHABLE | ALL_INTO_ONE),
                OPT_BOOL('d', NULL, &delete_redundant,
                                N_("remove redundant packs, and run git-prune-packed")),
-               OPT_BOOL('f', NULL, &no_reuse_delta,
+               OPT_BOOL('f', NULL, &po_args.no_reuse_delta,
                                N_("pass --no-reuse-delta to git-pack-objects")),
-               OPT_BOOL('F', NULL, &no_reuse_object,
+               OPT_BOOL('F', NULL, &po_args.no_reuse_object,
                                N_("pass --no-reuse-object to git-pack-objects")),
                OPT_BOOL('n', NULL, &no_update_server_info,
                                N_("do not run git-update-server-info")),
-               OPT__QUIET(&quiet, N_("be quiet")),
-               OPT_BOOL('l', "local", &local,
+               OPT__QUIET(&po_args.quiet, N_("be quiet")),
+               OPT_BOOL('l', "local", &po_args.local,
                                N_("pass --local to git-pack-objects")),
                OPT_BOOL('b', "write-bitmap-index", &write_bitmaps,
                                N_("write bitmap index")),
@@ -198,15 +305,15 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                                N_("with -A, do not loosen objects older than this")),
                OPT_BOOL('k', "keep-unreachable", &keep_unreachable,
                                N_("with -a, repack unreachable objects")),
-               OPT_STRING(0, "window", &window, N_("n"),
+               OPT_STRING(0, "window", &po_args.window, N_("n"),
                                N_("size of the window used for delta compression")),
-               OPT_STRING(0, "window-memory", &window_memory, N_("bytes"),
+               OPT_STRING(0, "window-memory", &po_args.window_memory, N_("bytes"),
                                N_("same as the above, but limit memory size instead of entries count")),
-               OPT_STRING(0, "depth", &depth, N_("n"),
+               OPT_STRING(0, "depth", &po_args.depth, N_("n"),
                                N_("limits the maximum delta depth")),
-               OPT_STRING(0, "threads", &threads, N_("n"),
+               OPT_STRING(0, "threads", &po_args.threads, N_("n"),
                                N_("limits the maximum number of threads")),
-               OPT_STRING(0, "max-pack-size", &max_pack_size, N_("bytes"),
+               OPT_STRING(0, "max-pack-size", &po_args.max_pack_size, N_("bytes"),
                                N_("maximum size of each packfile")),
                OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects,
                                N_("repack objects in packs marked with .keep")),
@@ -238,7 +345,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
        sigchain_push_common(remove_pack_on_signal);
 
-       argv_array_push(&cmd.args, "pack-objects");
+       prepare_pack_objects(&cmd, &po_args);
+
        argv_array_push(&cmd.args, "--keep-true-parents");
        if (!pack_kept_objects)
                argv_array_push(&cmd.args, "--honor-pack-keep");
@@ -251,26 +359,14 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
        argv_array_push(&cmd.args, "--indexed-objects");
        if (repository_format_partial_clone)
                argv_array_push(&cmd.args, "--exclude-promisor-objects");
-       if (window)
-               argv_array_pushf(&cmd.args, "--window=%s", window);
-       if (window_memory)
-               argv_array_pushf(&cmd.args, "--window-memory=%s", window_memory);
-       if (depth)
-               argv_array_pushf(&cmd.args, "--depth=%s", depth);
-       if (threads)
-               argv_array_pushf(&cmd.args, "--threads=%s", threads);
-       if (max_pack_size)
-               argv_array_pushf(&cmd.args, "--max-pack-size=%s", max_pack_size);
-       if (no_reuse_delta)
-               argv_array_pushf(&cmd.args, "--no-reuse-delta");
-       if (no_reuse_object)
-               argv_array_pushf(&cmd.args, "--no-reuse-object");
        if (write_bitmaps)
                argv_array_push(&cmd.args, "--write-bitmap-index");
 
        if (pack_everything & ALL_INTO_ONE) {
                get_non_kept_pack_filenames(&existing_packs, &keep_pack_list);
 
+               repack_promisor_objects(&po_args, &names);
+
                if (existing_packs.nr && delete_redundant) {
                        if (unpack_unreachable) {
                                argv_array_pushf(&cmd.args,
@@ -292,17 +388,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                argv_array_push(&cmd.args, "--incremental");
        }
 
-       if (local)
-               argv_array_push(&cmd.args,  "--local");
-       if (quiet)
-               argv_array_push(&cmd.args,  "--quiet");
-       if (delta_base_offset)
-               argv_array_push(&cmd.args,  "--delta-base-offset");
-
-       argv_array_push(&cmd.args, packtmp);
-
-       cmd.git_cmd = 1;
-       cmd.out = -1;
        cmd.no_stdin = 1;
 
        ret = start_command(&cmd);
@@ -320,7 +405,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
        if (ret)
                return ret;
 
-       if (!names.nr && !quiet)
+       if (!names.nr && !po_args.quiet)
                printf("Nothing new to pack.\n");
 
        /*
@@ -429,6 +514,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
        /* End of pack replacement. */
 
+       reprepare_packed_git(the_repository);
+
        if (delete_redundant) {
                int opts = 0;
                string_list_sort(&names);
@@ -441,7 +528,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                        if (!string_list_has_string(&names, sha1))
                                remove_redundant_pack(packdir, item->string);
                }
-               if (!quiet && isatty(2))
+               if (!po_args.quiet && isatty(2))
                        opts |= PRUNE_PACKED_VERBOSE;
                prune_packed_objects(opts);
        }
index 76f0a35..9a66720 100644 (file)
@@ -7,6 +7,7 @@
 #include "rerere.h"
 #include "dir.h"
 #include "sequencer.h"
+#include "branch.h"
 
 /*
  * This implements the builtins revert and cherry-pick.
@@ -191,8 +192,12 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
        opts->gpg_sign = xstrdup_or_null(opts->gpg_sign);
        opts->strategy = xstrdup_or_null(opts->strategy);
 
-       if (cmd == 'q')
-               return sequencer_remove_state(opts);
+       if (cmd == 'q') {
+               int ret = sequencer_remove_state(opts);
+               if (!ret)
+                       remove_branch_state();
+               return ret;
+       }
        if (cmd == 'c')
                return sequencer_continue(opts);
        if (cmd == 'a')
index f4d3f00..2cbe89e 100644 (file)
@@ -278,7 +278,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
        for (i = 0; i < active_nr; i++) {
                const struct cache_entry *ce = active_cache[i];
-               if (!ce_path_match(ce, &pathspec, seen))
+               if (!ce_path_match(&the_index, ce, &pathspec, seen))
                        continue;
                ALLOC_GROW(list.entry, list.nr + 1, list.alloc);
                list.entry[list.nr].name = xstrdup(ce->name);
index 42fd8d1..724b484 100644 (file)
@@ -178,7 +178,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
                OPT_BOOL(0, "stdin", &from_stdin, N_("read refs from stdin")),
                OPT_BOOL(0, "helper-status", &helper_status, N_("print status from remote helper")),
                { OPTION_CALLBACK,
-                 0, CAS_OPT_NAME, &cas, N_("refname>:<expect"),
+                 0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"),
                  N_("require old value of ref to be at this value"),
                  PARSE_OPT_OPTARG, parseopt_push_cas_option },
                OPT_END()
index 608d6ba..3898a2c 100644 (file)
@@ -268,8 +268,9 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
                         N_("Suppress commit descriptions, only provides commit count")),
                OPT_BOOL('e', "email", &log.email,
                         N_("Show the email address of each author")),
-               { OPTION_CALLBACK, 'w', NULL, &log, N_("w[,i1[,i2]]"),
-                       N_("Linewrap output"), PARSE_OPT_OPTARG, &parse_wrap_args },
+               { OPTION_CALLBACK, 'w', NULL, &log, N_("<w>[,<i1>[,<i2>]]"),
+                       N_("Linewrap output"), PARSE_OPT_OPTARG,
+                       &parse_wrap_args },
                OPT_END(),
        };
 
index 4b9d3c0..363cf85 100644 (file)
@@ -674,7 +674,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                { OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("<n>[,<base>]"),
                            N_("show <n> most recent ref-log entries starting at "
                               "base"),
-                           PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP,
+                           PARSE_OPT_OPTARG,
                            parse_reflog_param },
                OPT_END()
        };
index a3c4564..2bcc70f 100644 (file)
@@ -331,7 +331,7 @@ static int module_list_compute(int argc, const char **argv,
        for (i = 0; i < active_nr; i++) {
                const struct cache_entry *ce = active_cache[i];
 
-               if (!match_pathspec(pathspec, ce->name, ce_namelen(ce),
+               if (!match_pathspec(&the_index, pathspec, ce->name, ce_namelen(ce),
                                    0, ps_matched, 1) ||
                    !S_ISGITLINK(ce->ce_mode))
                        continue;
@@ -1024,7 +1024,6 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
 {
        struct sync_cb *info = cb_data;
        sync_submodule(list_item->name, info->prefix, info->flags);
-
 }
 
 static int module_sync(int argc, const char **argv, const char *prefix)
index f5c0b6a..fe84003 100644 (file)
@@ -748,7 +748,7 @@ static int do_reupdate(int ac, const char **av,
                int save_nr;
                char *path;
 
-               if (ce_stage(ce) || !ce_path_match(ce, &pathspec, NULL))
+               if (ce_stage(ce) || !ce_path_match(&the_index, ce, &pathspec, NULL))
                        continue;
                if (has_head)
                        old = read_one_ent(NULL, &head_oid,
@@ -969,9 +969,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                        PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */
                        PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
                        (parse_opt_cb *) cacheinfo_callback},
-               {OPTION_CALLBACK, 0, "chmod", &set_executable_bit, N_("(+/-)x"),
+               {OPTION_CALLBACK, 0, "chmod", &set_executable_bit, "(+|-)x",
                        N_("override the executable bit of the listed files"),
-                       PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
+                       PARSE_OPT_NONEG,
                        chmod_callback},
                {OPTION_SET_INT, 0, "assume-unchanged", &mark_valid_only, NULL,
                        N_("mark files as \"not changing\""),
index 84532ae..25d9116 100644 (file)
@@ -43,7 +43,8 @@ int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
        }
 
        /* parse all options sent by the client */
-       return write_archive(sent_argv.argc, sent_argv.argv, prefix, NULL, 1);
+       return write_archive(sent_argv.argc, sent_argv.argv, prefix,
+                            the_repository, NULL, 1);
 }
 
 __attribute__((format (printf, 1, 2)))
index c9d3c54..cdcbf82 100644 (file)
@@ -24,9 +24,8 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
        struct option write_tree_options[] = {
                OPT_BIT(0, "missing-ok", &flags, N_("allow missing objects"),
                        WRITE_TREE_MISSING_OK),
-               { OPTION_STRING, 0, "prefix", &prefix, N_("<prefix>/"),
-                 N_("write tree object for a subdirectory <prefix>") ,
-                 PARSE_OPT_LITERAL_ARGHELP },
+               OPT_STRING(0, "prefix", &prefix, N_("<prefix>/"),
+                          N_("write tree object for a subdirectory <prefix>")),
                { OPTION_BIT, 0, "ignore-cache-tree", &flags, NULL,
                  N_("only useful for debugging"),
                  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, NULL,
index a855273..f438f93 100644 (file)
@@ -4,6 +4,8 @@
 #ifndef BULK_CHECKIN_H
 #define BULK_CHECKIN_H
 
+#include "cache.h"
+
 extern int index_bulk_checkin(struct object_id *oid,
                              int fd, size_t size, enum object_type type,
                              const char *path, unsigned flags);
index 181d591..16ea022 100644 (file)
@@ -652,11 +652,6 @@ out:
        return ret;
 }
 
-int write_cache_as_tree(struct object_id *oid, int flags, const char *prefix)
-{
-       return write_index_as_tree(oid, &the_index, get_index_file(), flags, prefix);
-}
-
 static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
 {
        struct tree_desc desc;
@@ -723,10 +718,3 @@ int cache_tree_matches_traversal(struct cache_tree *root,
                return it->entry_count;
        return 0;
 }
-
-int update_main_cache_tree(int flags)
-{
-       if (!the_index.cache_tree)
-               the_index.cache_tree = cache_tree();
-       return cache_tree_update(&the_index, flags);
-}
index cfd5328..fc0c842 100644 (file)
@@ -33,8 +33,6 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);
 int cache_tree_fully_valid(struct cache_tree *);
 int cache_tree_update(struct index_state *, int);
 
-int update_main_cache_tree(int);
-
 /* bitmasks to write_cache_as_tree flags */
 #define WRITE_TREE_MISSING_OK 1
 #define WRITE_TREE_IGNORE_CACHE_TREE 2
@@ -48,9 +46,22 @@ int update_main_cache_tree(int);
 #define WRITE_TREE_PREFIX_ERROR (-3)
 
 int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix);
-int write_cache_as_tree(struct object_id *oid, int flags, const char *prefix);
 void prime_cache_tree(struct index_state *, struct tree *);
 
-extern int cache_tree_matches_traversal(struct cache_tree *, struct name_entry *ent, struct traverse_info *info);
+int cache_tree_matches_traversal(struct cache_tree *, struct name_entry *ent, struct traverse_info *info);
+
+#ifndef NO_THE_INDEX_COMPATIBILITY_MACROS
+static inline int write_cache_as_tree(struct object_id *oid, int flags, const char *prefix)
+{
+       return write_index_as_tree(oid, &the_index, get_index_file(), flags, prefix);
+}
+
+static inline int update_main_cache_tree(int flags)
+{
+       if (!the_index.cache_tree)
+               the_index.cache_tree = cache_tree();
+       return cache_tree_update(&the_index, flags);
+}
+#endif
 
 #endif
diff --git a/cache.h b/cache.h
index 1398b2a..b1fd3d5 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -917,15 +917,6 @@ enum log_refs_config {
 };
 extern enum log_refs_config log_all_ref_updates;
 
-enum branch_track {
-       BRANCH_TRACK_UNSPECIFIED = -1,
-       BRANCH_TRACK_NEVER = 0,
-       BRANCH_TRACK_REMOTE,
-       BRANCH_TRACK_ALWAYS,
-       BRANCH_TRACK_EXPLICIT,
-       BRANCH_TRACK_OVERRIDE
-};
-
 enum rebase_setup_type {
        AUTOREBASE_NEVER = 0,
        AUTOREBASE_LOCAL,
@@ -942,7 +933,6 @@ enum push_default_type {
        PUSH_DEFAULT_UNSPECIFIED
 };
 
-extern enum branch_track git_branch_track;
 extern enum rebase_setup_type autorebase;
 extern enum push_default_type push_default;
 
@@ -1575,62 +1565,6 @@ extern int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);
  */
 extern int odb_pack_keep(const char *name);
 
-/*
- * Iterate over the files in the loose-object parts of the object
- * directory "path", triggering the following callbacks:
- *
- *  - loose_object is called for each loose object we find.
- *
- *  - loose_cruft is called for any files that do not appear to be
- *    loose objects. Note that we only look in the loose object
- *    directories "objects/[0-9a-f]{2}/", so we will not report
- *    "objects/foobar" as cruft.
- *
- *  - loose_subdir is called for each top-level hashed subdirectory
- *    of the object directory (e.g., "$OBJDIR/f0"). It is called
- *    after the objects in the directory are processed.
- *
- * Any callback that is NULL will be ignored. Callbacks returning non-zero
- * will end the iteration.
- *
- * In the "buf" variant, "path" is a strbuf which will also be used as a
- * scratch buffer, but restored to its original contents before
- * the function returns.
- */
-typedef int each_loose_object_fn(const struct object_id *oid,
-                                const char *path,
-                                void *data);
-typedef int each_loose_cruft_fn(const char *basename,
-                               const char *path,
-                               void *data);
-typedef int each_loose_subdir_fn(unsigned int nr,
-                                const char *path,
-                                void *data);
-int for_each_file_in_obj_subdir(unsigned int subdir_nr,
-                               struct strbuf *path,
-                               each_loose_object_fn obj_cb,
-                               each_loose_cruft_fn cruft_cb,
-                               each_loose_subdir_fn subdir_cb,
-                               void *data);
-int for_each_loose_file_in_objdir(const char *path,
-                                 each_loose_object_fn obj_cb,
-                                 each_loose_cruft_fn cruft_cb,
-                                 each_loose_subdir_fn subdir_cb,
-                                 void *data);
-int for_each_loose_file_in_objdir_buf(struct strbuf *path,
-                                     each_loose_object_fn obj_cb,
-                                     each_loose_cruft_fn cruft_cb,
-                                     each_loose_subdir_fn subdir_cb,
-                                     void *data);
-
-/*
- * Iterate over loose objects in both the local
- * repository and any alternates repositories (unless the
- * LOCAL_ONLY flag is set).
- */
-#define FOR_EACH_OBJECT_LOCAL_ONLY 0x1
-extern int for_each_loose_object(each_loose_object_fn, void *, unsigned flags);
-
 /*
  * Set this to 0 to prevent sha1_object_info_extended() from fetching missing
  * blobs. This has a difference only if extensions.partialClone is set.
index 4b04c75..2a5bff4 100755 (executable)
@@ -14,6 +14,7 @@ then
        export GIT_TEST_SPLIT_INDEX=yes
        export GIT_TEST_FULL_IN_PACK_ARRAY=true
        export GIT_TEST_OE_SIZE=10
+       export GIT_TEST_OE_DELTA_SIZE=5
        make --quiet test
 fi
 
diff --git a/color.c b/color.c
index b1c24c6..ebb222e 100644 (file)
--- a/color.c
+++ b/color.c
@@ -343,6 +343,9 @@ int want_color_fd(int fd, int var)
 
        static int want_auto[3] = { -1, -1, -1 };
 
+       if (fd < 1 || fd >= ARRAY_SIZE(want_auto))
+               BUG("file descriptor out of range: %d", fd);
+
        if (var < 0)
                var = git_use_color_default;
 
diff --git a/color.h b/color.h
index 5b744e1..98894d6 100644 (file)
--- a/color.h
+++ b/color.h
@@ -36,6 +36,12 @@ struct strbuf;
 #define GIT_COLOR_BOLD_BLUE    "\033[1;34m"
 #define GIT_COLOR_BOLD_MAGENTA "\033[1;35m"
 #define GIT_COLOR_BOLD_CYAN    "\033[1;36m"
+#define GIT_COLOR_FAINT_RED    "\033[2;31m"
+#define GIT_COLOR_FAINT_GREEN  "\033[2;32m"
+#define GIT_COLOR_FAINT_YELLOW "\033[2;33m"
+#define GIT_COLOR_FAINT_BLUE   "\033[2;34m"
+#define GIT_COLOR_FAINT_MAGENTA        "\033[2;35m"
+#define GIT_COLOR_FAINT_CYAN   "\033[2;36m"
 #define GIT_COLOR_BG_RED       "\033[41m"
 #define GIT_COLOR_BG_GREEN     "\033[42m"
 #define GIT_COLOR_BG_YELLOW    "\033[43m"
@@ -44,6 +50,7 @@ struct strbuf;
 #define GIT_COLOR_BG_CYAN      "\033[46m"
 #define GIT_COLOR_FAINT                "\033[2m"
 #define GIT_COLOR_FAINT_ITALIC "\033[2;3m"
+#define GIT_COLOR_REVERSE      "\033[7m"
 
 /* A special value meaning "no color selected" */
 #define GIT_COLOR_NIL "NIL"
index 0a61917..2567a5c 100644 (file)
--- a/column.h
+++ b/column.h
@@ -36,6 +36,7 @@ static inline int column_active(unsigned int colopts)
        return (colopts & COL_ENABLE_MASK) == COL_ENABLED;
 }
 
+struct string_list;
 extern void print_columns(const struct string_list *list, unsigned int colopts,
                          const struct column_options *opts);
 
index e1c26c1..a9dda3b 100644 (file)
@@ -139,6 +139,7 @@ git-prune-packed                        plumbingmanipulators
 git-pull                                mainporcelain           remote
 git-push                                mainporcelain           remote
 git-quiltimport                         foreignscminterface
+git-range-diff                          mainporcelain
 git-read-tree                           plumbingmanipulators
 git-rebase                              mainporcelain           history
 git-receive-pack                        synchelpers
index 0034740..8a1bec7 100644 (file)
@@ -730,7 +730,7 @@ void write_commit_graph(const char *obj_dir,
                                die(_("error adding pack %s"), packname.buf);
                        if (open_pack_index(p))
                                die(_("error opening index for %s"), packname.buf);
-                       for_each_object_in_pack(p, add_packed_commits, &oids);
+                       for_each_object_in_pack(p, add_packed_commits, &oids, 0);
                        close_pack(p);
                }
                strbuf_release(&packname);
index 76e0989..eea62f8 100644 (file)
@@ -4,6 +4,7 @@
 #include "git-compat-util.h"
 #include "repository.h"
 #include "string-list.h"
+#include "cache.h"
 
 struct commit;
 
index 6ded1c8..858ca14 100644 (file)
@@ -341,12 +341,44 @@ int mingw_mkdir(const char *path, int mode)
        return ret;
 }
 
+static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
+{
+       HANDLE handle;
+       int fd;
+       DWORD create = (oflags & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING;
+
+       /* only these flags are supported */
+       if ((oflags & ~O_CREAT) != (O_WRONLY | O_APPEND))
+               return errno = ENOSYS, -1;
+
+       /*
+        * FILE_SHARE_WRITE is required to permit child processes
+        * to append to the file.
+        */
+       handle = CreateFileW(wfilename, FILE_APPEND_DATA,
+                       FILE_SHARE_WRITE | FILE_SHARE_READ,
+                       NULL, create, FILE_ATTRIBUTE_NORMAL, NULL);
+       if (handle == INVALID_HANDLE_VALUE)
+               return errno = err_win_to_posix(GetLastError()), -1;
+       /*
+        * No O_APPEND here, because the CRT uses it only to reset the
+        * file pointer to EOF on write(); but that is not necessary
+        * for a file created with FILE_APPEND_DATA.
+        */
+       fd = _open_osfhandle((intptr_t)handle, O_BINARY);
+       if (fd < 0)
+               CloseHandle(handle);
+       return fd;
+}
+
 int mingw_open (const char *filename, int oflags, ...)
 {
+       typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
        va_list args;
        unsigned mode;
        int fd;
        wchar_t wfilename[MAX_PATH];
+       open_fn_t open_fn;
 
        va_start(args, oflags);
        mode = va_arg(args, int);
@@ -355,9 +387,14 @@ int mingw_open (const char *filename, int oflags, ...)
        if (filename && !strcmp(filename, "/dev/null"))
                filename = "nul";
 
+       if (oflags & O_APPEND)
+               open_fn = mingw_open_append;
+       else
+               open_fn = _wopen;
+
        if (xutftowcs_path(wfilename, filename) < 0)
                return -1;
-       fd = _wopen(wfilename, oflags, mode);
+       fd = open_fn(wfilename, oflags, mode);
 
        if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) {
                DWORD attrs = GetFileAttributesW(wfilename);
@@ -375,7 +412,7 @@ int mingw_open (const char *filename, int oflags, ...)
                 * CREATE_ALWAYS flag of CreateFile()).
                 */
                if (fd < 0 && errno == EACCES)
-                       fd = _wopen(wfilename, oflags & ~O_CREAT, mode);
+                       fd = open_fn(wfilename, oflags & ~O_CREAT, mode);
                if (fd >= 0 && set_hidden_flag(wfilename, 1))
                        warning("could not mark '%s' as hidden.", filename);
        }
index a94e7c4..6f843d3 100644 (file)
@@ -1,4 +1,6 @@
 #ifndef PRECOMPOSE_UNICODE_H
+#define PRECOMPOSE_UNICODE_H
+
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <dirent.h>
@@ -41,5 +43,4 @@ int precompose_utf8_closedir(PREC_DIR *dirp);
 #define DIR PREC_DIR
 #endif /* PRECOMPOSE_UNICODE_C */
 
-#define  PRECOMPOSE_UNICODE_H
 #endif /* PRECOMPOSE_UNICODE_H */
index 10522f3..9a0b10d 100644 (file)
--- a/config.c
+++ b/config.c
@@ -6,6 +6,7 @@
  *
  */
 #include "cache.h"
+#include "branch.h"
 #include "config.h"
 #include "repository.h"
 #include "lockfile.h"
@@ -37,6 +38,7 @@ struct config_source {
        int eof;
        struct strbuf value;
        struct strbuf var;
+       unsigned subsection_case_sensitive : 1;
 
        int (*do_fgetc)(struct config_source *c);
        int (*do_ungetc)(int c, struct config_source *conf);
@@ -605,6 +607,7 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name)
 
 static int get_extended_base_var(struct strbuf *name, int c)
 {
+       cf->subsection_case_sensitive = 0;
        do {
                if (c == '\n')
                        goto error_incomplete_line;
@@ -641,6 +644,7 @@ error_incomplete_line:
 
 static int get_base_var(struct strbuf *name)
 {
+       cf->subsection_case_sensitive = 1;
        for (;;) {
                int c = get_next_char();
                if (cf->eof)
@@ -933,7 +937,7 @@ int git_parse_ulong(const char *value, unsigned long *ret)
        return 1;
 }
 
-static int git_parse_ssize_t(const char *value, ssize_t *ret)
+int git_parse_ssize_t(const char *value, ssize_t *ret)
 {
        intmax_t tmp;
        if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(ssize_t)))
@@ -2369,14 +2373,21 @@ static int store_aux_event(enum config_event_t type,
        store->parsed[store->parsed_nr].type = type;
 
        if (type == CONFIG_EVENT_SECTION) {
+               int (*cmpfn)(const char *, const char *, size_t);
+
                if (cf->var.len < 2 || cf->var.buf[cf->var.len - 1] != '.')
                        return error(_("invalid section name '%s'"), cf->var.buf);
 
+               if (cf->subsection_case_sensitive)
+                       cmpfn = strncasecmp;
+               else
+                       cmpfn = strncmp;
+
                /* Is this the section we were looking for? */
                store->is_keys_section =
                        store->parsed[store->parsed_nr].is_keys_section =
                        cf->var.len - 1 == store->baselen &&
-                       !strncasecmp(cf->var.buf, store->key, store->baselen);
+                       !cmpfn(cf->var.buf, store->key, store->baselen);
                if (store->is_keys_section) {
                        store->section_seen = 1;
                        ALLOC_GROW(store->seen, store->seen_nr + 1,
index bb2f506..ab46e01 100644 (file)
--- a/config.h
+++ b/config.h
@@ -1,6 +1,11 @@
 #ifndef CONFIG_H
 #define CONFIG_H
 
+#include "hashmap.h"
+#include "string-list.h"
+
+struct object_id;
+
 /* git_config_parse_key() returns these negated: */
 #define CONFIG_INVALID_KEY 1
 #define CONFIG_NO_SECTION_OR_NAME 2
@@ -82,6 +87,7 @@ extern void git_config(config_fn_t fn, void *);
 extern int config_with_options(config_fn_t fn, void *,
                               struct git_config_source *config_source,
                               const struct config_options *opts);
+extern int git_parse_ssize_t(const char *, ssize_t *);
 extern int git_parse_ulong(const char *, unsigned long *);
 extern int git_parse_maybe_bool(const char *);
 extern int git_config_int(const char *, const char *);
@@ -188,9 +194,14 @@ struct config_set {
 
 extern void git_configset_init(struct config_set *cs);
 extern int git_configset_add_file(struct config_set *cs, const char *filename);
-extern int git_configset_get_value(struct config_set *cs, const char *key, const char **value);
 extern const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);
 extern void git_configset_clear(struct config_set *cs);
+
+/*
+ * These functions return 1 if not found, and 0 if found, leaving the found
+ * value in the 'dest' pointer.
+ */
+extern int git_configset_get_value(struct config_set *cs, const char *key, const char **dest);
 extern int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest);
 extern int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
 extern int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
index 322dc76..e4c9618 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef CONNECTED_H
 #define CONNECTED_H
 
+struct object_id;
 struct transport;
 
 /*
index 94c9551..d63d2df 100644 (file)
@@ -1976,6 +1976,20 @@ _git_push ()
        __git_complete_remote_or_refspec
 }
 
+_git_range_diff ()
+{
+       case "$cur" in
+       --*)
+               __gitcomp "
+                       --creation-factor= --no-dual-color
+                       $__git_diff_common_options
+               "
+               return
+               ;;
+       esac
+       __git_complete_revlist
+}
+
 _git_rebase ()
 {
        __git_find_repo_path
index ce7ea0d..6057f1f 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -1293,7 +1293,8 @@ struct conv_attrs {
        const char *working_tree_encoding; /* Supported encoding or default encoding if NULL */
 };
 
-static void convert_attrs(struct conv_attrs *ca, const char *path)
+static void convert_attrs(const struct index_state *istate,
+                         struct conv_attrs *ca, const char *path)
 {
        static struct attr_check *check;
 
@@ -1305,7 +1306,7 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
                git_config(read_convert_config, NULL);
        }
 
-       if (!git_check_attr(path, check)) {
+       if (!git_check_attr(istate, path, check)) {
                struct attr_check_item *ccheck = check->items;
                ca->crlf_action = git_path_check_crlf(ccheck + 4);
                if (ca->crlf_action == CRLF_UNDEFINED)
@@ -1342,11 +1343,11 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
                ca->crlf_action = CRLF_AUTO_INPUT;
 }
 
-int would_convert_to_git_filter_fd(const char *path)
+int would_convert_to_git_filter_fd(const struct index_state *istate, const char *path)
 {
        struct conv_attrs ca;
 
-       convert_attrs(&ca, path);
+       convert_attrs(istate, &ca, path);
        if (!ca.drv)
                return 0;
 
@@ -1361,11 +1362,11 @@ int would_convert_to_git_filter_fd(const char *path)
        return apply_filter(path, NULL, 0, -1, NULL, ca.drv, CAP_CLEAN, NULL);
 }
 
-const char *get_convert_attr_ascii(const char *path)
+const char *get_convert_attr_ascii(const struct index_state *istate, const char *path)
 {
        struct conv_attrs ca;
 
-       convert_attrs(&ca, path);
+       convert_attrs(istate, &ca, path);
        switch (ca.attr_action) {
        case CRLF_UNDEFINED:
                return "";
@@ -1394,7 +1395,7 @@ int convert_to_git(const struct index_state *istate,
        int ret = 0;
        struct conv_attrs ca;
 
-       convert_attrs(&ca, path);
+       convert_attrs(istate, &ca, path);
 
        ret |= apply_filter(path, src, len, -1, dst, ca.drv, CAP_CLEAN, NULL);
        if (!ret && ca.drv && ca.drv->required)
@@ -1426,7 +1427,7 @@ void convert_to_git_filter_fd(const struct index_state *istate,
                              int conv_flags)
 {
        struct conv_attrs ca;
-       convert_attrs(&ca, path);
+       convert_attrs(istate, &ca, path);
 
        assert(ca.drv);
        assert(ca.drv->clean || ca.drv->process);
@@ -1439,14 +1440,15 @@ void convert_to_git_filter_fd(const struct index_state *istate,
        ident_to_git(path, dst->buf, dst->len, dst, ca.ident);
 }
 
-static int convert_to_working_tree_internal(const char *path, const char *src,
+static int convert_to_working_tree_internal(const struct index_state *istate,
+                                           const char *path, const char *src,
                                            size_t len, struct strbuf *dst,
                                            int normalizing, struct delayed_checkout *dco)
 {
        int ret = 0, ret_filter = 0;
        struct conv_attrs ca;
 
-       convert_attrs(&ca, path);
+       convert_attrs(istate, &ca, path);
 
        ret |= ident_to_worktree(path, src, len, dst, ca.ident);
        if (ret) {
@@ -1480,22 +1482,25 @@ static int convert_to_working_tree_internal(const char *path, const char *src,
        return ret | ret_filter;
 }
 
-int async_convert_to_working_tree(const char *path, const char *src,
+int async_convert_to_working_tree(const struct index_state *istate,
+                                 const char *path, const char *src,
                                  size_t len, struct strbuf *dst,
                                  void *dco)
 {
-       return convert_to_working_tree_internal(path, src, len, dst, 0, dco);
+       return convert_to_working_tree_internal(istate, path, src, len, dst, 0, dco);
 }
 
-int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)
+int convert_to_working_tree(const struct index_state *istate,
+                           const char *path, const char *src,
+                           size_t len, struct strbuf *dst)
 {
-       return convert_to_working_tree_internal(path, src, len, dst, 0, NULL);
+       return convert_to_working_tree_internal(istate, path, src, len, dst, 0, NULL);
 }
 
 int renormalize_buffer(const struct index_state *istate, const char *path,
                       const char *src, size_t len, struct strbuf *dst)
 {
-       int ret = convert_to_working_tree_internal(path, src, len, dst, 1, NULL);
+       int ret = convert_to_working_tree_internal(istate, path, src, len, dst, 1, NULL);
        if (ret) {
                src = dst->buf;
                len = dst->len;
@@ -1929,12 +1934,14 @@ static struct stream_filter *ident_filter(const struct object_id *oid)
  * Note that you would be crazy to set CRLF, smuge/clean or ident to a
  * large binary blob you would want us not to slurp into the memory!
  */
-struct stream_filter *get_stream_filter(const char *path, const struct object_id *oid)
+struct stream_filter *get_stream_filter(const struct index_state *istate,
+                                       const char *path,
+                                       const struct object_id *oid)
 {
        struct conv_attrs ca;
        struct stream_filter *filter = NULL;
 
-       convert_attrs(&ca, path);
+       convert_attrs(istate, &ca, path);
        if (ca.drv && (ca.drv->process || ca.drv->smudge || ca.drv->clean))
                return NULL;
 
index 01385d9..831559f 100644 (file)
--- a/convert.h
+++ b/convert.h
@@ -7,6 +7,8 @@
 #include "string-list.h"
 
 struct index_state;
+struct object_id;
+struct strbuf;
 
 #define CONV_EOL_RNDTRP_DIE   (1<<0) /* Die if CRLF to LF to CRLF is different */
 #define CONV_EOL_RNDTRP_WARN  (1<<1) /* Warn if CRLF to LF to CRLF is different */
@@ -57,35 +59,40 @@ struct delayed_checkout {
 
 extern enum eol core_eol;
 extern char *check_roundtrip_encoding;
-extern const char *get_cached_convert_stats_ascii(const struct index_state *istate,
-                                                 const char *path);
-extern const char *get_wt_convert_stats_ascii(const char *path);
-extern const char *get_convert_attr_ascii(const char *path);
+const char *get_cached_convert_stats_ascii(const struct index_state *istate,
+                                          const char *path);
+const char *get_wt_convert_stats_ascii(const char *path);
+const char *get_convert_attr_ascii(const struct index_state *istate,
+                                  const char *path);
 
 /* returns 1 if *dst was used */
-extern int convert_to_git(const struct index_state *istate,
-                         const char *path, const char *src, size_t len,
-                         struct strbuf *dst, int conv_flags);
-extern int convert_to_working_tree(const char *path, const char *src,
-                                  size_t len, struct strbuf *dst);
-extern int async_convert_to_working_tree(const char *path, const char *src,
-                                        size_t len, struct strbuf *dst,
-                                        void *dco);
-extern int async_query_available_blobs(const char *cmd, struct string_list *available_paths);
-extern int renormalize_buffer(const struct index_state *istate,
-                             const char *path, const char *src, size_t len,
-                             struct strbuf *dst);
+int convert_to_git(const struct index_state *istate,
+                  const char *path, const char *src, size_t len,
+                  struct strbuf *dst, int conv_flags);
+int convert_to_working_tree(const struct index_state *istate,
+                           const char *path, const char *src,
+                           size_t len, struct strbuf *dst);
+int async_convert_to_working_tree(const struct index_state *istate,
+                                 const char *path, const char *src,
+                                 size_t len, struct strbuf *dst,
+                                 void *dco);
+int async_query_available_blobs(const char *cmd,
+                               struct string_list *available_paths);
+int renormalize_buffer(const struct index_state *istate,
+                      const char *path, const char *src, size_t len,
+                      struct strbuf *dst);
 static inline int would_convert_to_git(const struct index_state *istate,
                                       const char *path)
 {
        return convert_to_git(istate, path, NULL, 0, NULL, 0);
 }
 /* Precondition: would_convert_to_git_filter_fd(path) == true */
-extern void convert_to_git_filter_fd(const struct index_state *istate,
-                                    const char *path, int fd,
-                                    struct strbuf *dst,
-                                    int conv_flags);
-extern int would_convert_to_git_filter_fd(const char *path);
+void convert_to_git_filter_fd(const struct index_state *istate,
+                             const char *path, int fd,
+                             struct strbuf *dst,
+                             int conv_flags);
+int would_convert_to_git_filter_fd(const struct index_state *istate,
+                                  const char *path);
 
 /*****************************************************************
  *
@@ -95,9 +102,11 @@ extern int would_convert_to_git_filter_fd(const char *path);
 
 struct stream_filter; /* opaque */
 
-extern struct stream_filter *get_stream_filter(const char *path, const struct object_id *);
-extern void free_stream_filter(struct stream_filter *);
-extern int is_null_stream_filter(struct stream_filter *);
+struct stream_filter *get_stream_filter(const struct index_state *istate,
+                                       const char *path,
+                                       const struct object_id *);
+void free_stream_filter(struct stream_filter *);
+int is_null_stream_filter(struct stream_filter *);
 
 /*
  * Use as much input up to *isize_p and fill output up to *osize_p;
@@ -111,8 +120,8 @@ extern int is_null_stream_filter(struct stream_filter *);
  * such filters know there is no more input coming and it is time for
  * them to produce the remaining output based on the buffered input.
  */
-extern int stream_filter(struct stream_filter *,
-                        const char *input, size_t *isize_p,
-                        char *output, size_t *osize_p);
+int stream_filter(struct stream_filter *,
+                 const char *input, size_t *isize_p,
+                 char *output, size_t *osize_p);
 
 #endif /* CONVERT_H */
index c5a2e33..3bf7184 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef CSUM_FILE_H
 #define CSUM_FILE_H
 
+#include "hash.h"
+
 struct progress;
 
 /* A SHA1-protected file */
index 732f684..88a98b1 100644 (file)
@@ -109,7 +109,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                if (diff_can_quit_early(&revs->diffopt))
                        break;
 
-               if (!ce_path_match(ce, &revs->prune_data, NULL))
+               if (!ce_path_match(&the_index, ce, &revs->prune_data, NULL))
                        continue;
 
                if (ce_stage(ce)) {
@@ -474,7 +474,7 @@ static int oneway_diff(const struct cache_entry * const *src,
        if (tree == o->df_conflict_entry)
                tree = NULL;
 
-       if (ce_path_match(idx ? idx : tree, &revs->prune_data, NULL)) {
+       if (ce_path_match(&the_index, idx ? idx : tree, &revs->prune_data, NULL)) {
                do_oneway_diff(o, idx, tree);
                if (diff_can_quit_early(&revs->diffopt)) {
                        o->exiting_early = 1;
diff --git a/diff.c b/diff.c
index f830afa..145cfba 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -70,6 +70,12 @@ static char diff_colors[][COLOR_MAXLEN] = {
        GIT_COLOR_BOLD_YELLOW,  /* NEW_MOVED ALTERNATIVE */
        GIT_COLOR_FAINT,        /* NEW_MOVED_DIM */
        GIT_COLOR_FAINT_ITALIC, /* NEW_MOVED_ALTERNATIVE_DIM */
+       GIT_COLOR_FAINT,        /* CONTEXT_DIM */
+       GIT_COLOR_FAINT_RED,    /* OLD_DIM */
+       GIT_COLOR_FAINT_GREEN,  /* NEW_DIM */
+       GIT_COLOR_BOLD,         /* CONTEXT_BOLD */
+       GIT_COLOR_BOLD_RED,     /* OLD_BOLD */
+       GIT_COLOR_BOLD_GREEN,   /* NEW_BOLD */
 };
 
 static const char *color_diff_slots[] = {
@@ -89,6 +95,12 @@ static const char *color_diff_slots[] = {
        [DIFF_FILE_NEW_MOVED_ALT]     = "newMovedAlternative",
        [DIFF_FILE_NEW_MOVED_DIM]     = "newMovedDimmed",
        [DIFF_FILE_NEW_MOVED_ALT_DIM] = "newMovedAlternativeDimmed",
+       [DIFF_CONTEXT_DIM]            = "contextDimmed",
+       [DIFF_FILE_OLD_DIM]           = "oldDimmed",
+       [DIFF_FILE_NEW_DIM]           = "newDimmed",
+       [DIFF_CONTEXT_BOLD]           = "contextBold",
+       [DIFF_FILE_OLD_BOLD]          = "oldBold",
+       [DIFF_FILE_NEW_BOLD]          = "newBold",
 };
 
 static NORETURN void die_want_option(const char *option_name)
@@ -611,14 +623,18 @@ static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,
        ecbdata->blank_at_eof_in_postimage = (at - l2) + 1;
 }
 
-static void emit_line_0(struct diff_options *o, const char *set, const char *reset,
+static void emit_line_0(struct diff_options *o,
+                       const char *set, unsigned reverse, const char *reset,
                        int first, const char *line, int len)
 {
        int has_trailing_newline, has_trailing_carriage_return;
        int nofirst;
        FILE *file = o->file;
 
-       fputs(diff_line_prefix(o), file);
+       if (first)
+               fputs(diff_line_prefix(o), file);
+       else if (!len)
+               return;
 
        if (len == 0) {
                has_trailing_newline = (first == '\n');
@@ -636,8 +652,10 @@ static void emit_line_0(struct diff_options *o, const char *set, const char *res
        }
 
        if (len || !nofirst) {
+               if (reverse && want_color(o->use_color))
+                       fputs(GIT_COLOR_REVERSE, file);
                fputs(set, file);
-               if (!nofirst)
+               if (first && !nofirst)
                        fputc(first, file);
                fwrite(line, len, 1, file);
                fputs(reset, file);
@@ -651,7 +669,7 @@ static void emit_line_0(struct diff_options *o, const char *set, const char *res
 static void emit_line(struct diff_options *o, const char *set, const char *reset,
                      const char *line, int len)
 {
-       emit_line_0(o, set, reset, line[0], line+1, len-1);
+       emit_line_0(o, set, 0, reset, line[0], line+1, len-1);
 }
 
 enum diff_symbol {
@@ -1170,7 +1188,8 @@ static void dim_moved_lines(struct diff_options *o)
 
 static void emit_line_ws_markup(struct diff_options *o,
                                const char *set, const char *reset,
-                               const char *line, int len, char sign,
+                               const char *line, int len,
+                               const char *set_sign, char sign,
                                unsigned ws_rule, int blank_at_eof)
 {
        const char *ws = NULL;
@@ -1181,14 +1200,20 @@ static void emit_line_ws_markup(struct diff_options *o,
                        ws = NULL;
        }
 
-       if (!ws)
-               emit_line_0(o, set, reset, sign, line, len);
-       else if (blank_at_eof)
+       if (!ws && !set_sign)
+               emit_line_0(o, set, 0, reset, sign, line, len);
+       else if (!ws) {
+               /* Emit just the prefix, then the rest. */
+               emit_line_0(o, set_sign ? set_sign : set, !!set_sign, reset,
+                           sign, "", 0);
+               emit_line_0(o, set, 0, reset, 0, line, len);
+       } else if (blank_at_eof)
                /* Blank line at EOF - paint '+' as well */
-               emit_line_0(o, ws, reset, sign, line, len);
+               emit_line_0(o, ws, 0, reset, sign, line, len);
        else {
                /* Emit just the prefix, then the rest. */
-               emit_line_0(o, set, reset, sign, "", 0);
+               emit_line_0(o, set_sign ? set_sign : set, !!set_sign, reset,
+                           sign, "", 0);
                ws_check_emit(line, len, ws_rule,
                              o->file, set, reset, ws);
        }
@@ -1198,7 +1223,7 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
                                         struct emitted_diff_symbol *eds)
 {
        static const char *nneof = " No newline at end of file\n";
-       const char *context, *reset, *set, *meta, *fraginfo;
+       const char *context, *reset, *set, *set_sign, *meta, *fraginfo;
        struct strbuf sb = STRBUF_INIT;
 
        enum diff_symbol s = eds->s;
@@ -1211,7 +1236,7 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
                context = diff_get_color_opt(o, DIFF_CONTEXT);
                reset = diff_get_color_opt(o, DIFF_RESET);
                putc('\n', o->file);
-               emit_line_0(o, context, reset, '\\',
+               emit_line_0(o, context, 0, reset, '\\',
                            nneof, strlen(nneof));
                break;
        case DIFF_SYMBOL_SUBMODULE_HEADER:
@@ -1238,7 +1263,18 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
        case DIFF_SYMBOL_CONTEXT:
                set = diff_get_color_opt(o, DIFF_CONTEXT);
                reset = diff_get_color_opt(o, DIFF_RESET);
-               emit_line_ws_markup(o, set, reset, line, len, ' ',
+               set_sign = NULL;
+               if (o->flags.dual_color_diffed_diffs) {
+                       char c = !len ? 0 : line[0];
+
+                       if (c == '+')
+                               set = diff_get_color_opt(o, DIFF_FILE_NEW);
+                       else if (c == '@')
+                               set = diff_get_color_opt(o, DIFF_FRAGINFO);
+                       else if (c == '-')
+                               set = diff_get_color_opt(o, DIFF_FILE_OLD);
+               }
+               emit_line_ws_markup(o, set, reset, line, len, set_sign, ' ',
                                    flags & (DIFF_SYMBOL_CONTENT_WS_MASK), 0);
                break;
        case DIFF_SYMBOL_PLUS:
@@ -1265,7 +1301,23 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
                        set = diff_get_color_opt(o, DIFF_FILE_NEW);
                }
                reset = diff_get_color_opt(o, DIFF_RESET);
-               emit_line_ws_markup(o, set, reset, line, len, '+',
+               if (!o->flags.dual_color_diffed_diffs)
+                       set_sign = NULL;
+               else {
+                       char c = !len ? 0 : line[0];
+
+                       set_sign = set;
+                       if (c == '-')
+                               set = diff_get_color_opt(o, DIFF_FILE_OLD_BOLD);
+                       else if (c == '@')
+                               set = diff_get_color_opt(o, DIFF_FRAGINFO);
+                       else if (c == '+')
+                               set = diff_get_color_opt(o, DIFF_FILE_NEW_BOLD);
+                       else
+                               set = diff_get_color_opt(o, DIFF_CONTEXT_BOLD);
+                       flags &= ~DIFF_SYMBOL_CONTENT_WS_MASK;
+               }
+               emit_line_ws_markup(o, set, reset, line, len, set_sign, '+',
                                    flags & DIFF_SYMBOL_CONTENT_WS_MASK,
                                    flags & DIFF_SYMBOL_CONTENT_BLANK_LINE_EOF);
                break;
@@ -1293,7 +1345,22 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
                        set = diff_get_color_opt(o, DIFF_FILE_OLD);
                }
                reset = diff_get_color_opt(o, DIFF_RESET);
-               emit_line_ws_markup(o, set, reset, line, len, '-',
+               if (!o->flags.dual_color_diffed_diffs)
+                       set_sign = NULL;
+               else {
+                       char c = !len ? 0 : line[0];
+
+                       set_sign = set;
+                       if (c == '+')
+                               set = diff_get_color_opt(o, DIFF_FILE_NEW_DIM);
+                       else if (c == '@')
+                               set = diff_get_color_opt(o, DIFF_FRAGINFO);
+                       else if (c == '-')
+                               set = diff_get_color_opt(o, DIFF_FILE_OLD_DIM);
+                       else
+                               set = diff_get_color_opt(o, DIFF_CONTEXT_DIM);
+               }
+               emit_line_ws_markup(o, set, reset, line, len, set_sign, '-',
                                    flags & DIFF_SYMBOL_CONTENT_WS_MASK, 0);
                break;
        case DIFF_SYMBOL_WORDS_PORCELAIN:
@@ -1484,6 +1551,7 @@ static void emit_hunk_header(struct emit_callback *ecbdata,
        const char *frag = diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO);
        const char *func = diff_get_color(ecbdata->color_diff, DIFF_FUNCINFO);
        const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
+       const char *reverse = ecbdata->color_diff ? GIT_COLOR_REVERSE : "";
        static const char atat[2] = { '@', '@' };
        const char *cp, *ep;
        struct strbuf msgbuf = STRBUF_INIT;
@@ -1504,6 +1572,8 @@ static void emit_hunk_header(struct emit_callback *ecbdata,
        ep += 2; /* skip over @@ */
 
        /* The hunk header in fraginfo color */
+       if (ecbdata->opt->flags.dual_color_diffed_diffs)
+               strbuf_addstr(&msgbuf, reverse);
        strbuf_addstr(&msgbuf, frag);
        strbuf_add(&msgbuf, line, ep - line);
        strbuf_addstr(&msgbuf, reset);
@@ -3397,13 +3467,16 @@ static void builtin_diff(const char *name_a,
                memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                memset(&ecbdata, 0, sizeof(ecbdata));
+               if (o->flags.suppress_diff_headers)
+                       lbl[0] = NULL;
                ecbdata.label_path = lbl;
                ecbdata.color_diff = want_color(o->use_color);
                ecbdata.ws_rule = whitespace_rule(name_b);
                if (ecbdata.ws_rule & WS_BLANK_AT_EOF)
                        check_blank_at_eof(&mf1, &mf2, &ecbdata);
                ecbdata.opt = o;
-               ecbdata.header = header.len ? &header : NULL;
+               if (header.len && !o->flags.suppress_diff_headers)
+                       ecbdata.header = &header;
                xpp.flags = o->xdl_opts;
                xpp.anchors = o->anchors;
                xpp.anchors_nr = o->anchors_nr;
@@ -3895,7 +3968,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
        temp->tempfile = mks_tempfile_ts(tempfile.buf, strlen(base) + 1);
        if (!temp->tempfile)
                die_errno("unable to create temp-file");
-       if (convert_to_working_tree(path,
+       if (convert_to_working_tree(&the_index, path,
                        (const char *)blob, (size_t)size, &buf)) {
                blob = buf.buf;
                size = buf.len;
@@ -4416,16 +4489,6 @@ void diff_setup_done(struct diff_options *options)
 
        if (options->detect_rename && options->rename_limit < 0)
                options->rename_limit = diff_rename_limit_default;
-       if (options->setup & DIFF_SETUP_USE_CACHE) {
-               if (!active_cache)
-                       /* read-cache does not die even when it fails
-                        * so it is safe for us to do this here.  Also
-                        * it does not smudge active_cache or active_nr
-                        * when it fails, so we do not have to worry about
-                        * cleaning it up ourselves either.
-                        */
-                       read_cache();
-       }
        if (hexsz < options->abbrev)
                options->abbrev = hexsz; /* full */
 
diff --git a/diff.h b/diff.h
index a14895b..89544e6 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -94,6 +94,8 @@ struct diff_flags {
        unsigned funccontext:1;
        unsigned default_follow_renames:1;
        unsigned stat_with_summary:1;
+       unsigned suppress_diff_headers:1;
+       unsigned dual_color_diffed_diffs:1;
 };
 
 static inline void diff_flags_or(struct diff_flags *a,
@@ -246,7 +248,13 @@ enum color_diff {
        DIFF_FILE_NEW_MOVED = 13,
        DIFF_FILE_NEW_MOVED_ALT = 14,
        DIFF_FILE_NEW_MOVED_DIM = 15,
-       DIFF_FILE_NEW_MOVED_ALT_DIM = 16
+       DIFF_FILE_NEW_MOVED_ALT_DIM = 16,
+       DIFF_CONTEXT_DIM = 17,
+       DIFF_FILE_OLD_DIM = 18,
+       DIFF_FILE_NEW_DIM = 19,
+       DIFF_CONTEXT_BOLD = 20,
+       DIFF_FILE_OLD_BOLD = 21,
+       DIFF_FILE_NEW_BOLD = 22,
 };
 const char *diff_get_color(int diff_use_color, enum color_diff ix);
 #define diff_get_color_opt(o, ix) \
@@ -258,15 +266,15 @@ const char *diff_line_prefix(struct diff_options *);
 
 extern const char mime_boundary_leader[];
 
-extern struct combine_diff_path *diff_tree_paths(
+struct combine_diff_path *diff_tree_paths(
        struct combine_diff_path *p, const struct object_id *oid,
        const struct object_id **parents_oid, int nparent,
        struct strbuf *base, struct diff_options *opt);
-extern int diff_tree_oid(const struct object_id *old_oid,
-                        const struct object_id *new_oid,
-                        const char *base, struct diff_options *opt);
-extern int diff_root_tree_oid(const struct object_id *new_oid, const char *base,
-                             struct diff_options *opt);
+int diff_tree_oid(const struct object_id *old_oid,
+                 const struct object_id *new_oid,
+                 const char *base, struct diff_options *opt);
+int diff_root_tree_oid(const struct object_id *new_oid, const char *base,
+                      struct diff_options *opt);
 
 struct combine_diff_path {
        struct combine_diff_path *next;
@@ -283,53 +291,52 @@ struct combine_diff_path {
        st_add4(sizeof(struct combine_diff_path), (l), 1, \
                st_mult(sizeof(struct combine_diff_parent), (n)))
 
-extern void show_combined_diff(struct combine_diff_path *elem, int num_parent,
-                             int dense, struct rev_info *);
+void show_combined_diff(struct combine_diff_path *elem, int num_parent,
+                       int dense, struct rev_info *);
 
-extern void diff_tree_combined(const struct object_id *oid, const struct oid_array *parents, int dense, struct rev_info *rev);
+void diff_tree_combined(const struct object_id *oid, const struct oid_array *parents, int dense, struct rev_info *rev);
 
-extern void diff_tree_combined_merge(const struct commit *commit, int dense, struct rev_info *rev);
+void diff_tree_combined_merge(const struct commit *commit, int dense, struct rev_info *rev);
 
 void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b);
 
-extern int diff_can_quit_early(struct diff_options *);
+int diff_can_quit_early(struct diff_options *);
 
-extern void diff_addremove(struct diff_options *,
-                          int addremove,
-                          unsigned mode,
-                          const struct object_id *oid,
-                          int oid_valid,
-                          const char *fullpath, unsigned dirty_submodule);
+void diff_addremove(struct diff_options *,
+                   int addremove,
+                   unsigned mode,
+                   const struct object_id *oid,
+                   int oid_valid,
+                   const char *fullpath, unsigned dirty_submodule);
 
-extern void diff_change(struct diff_options *,
-                       unsigned mode1, unsigned mode2,
-                       const struct object_id *old_oid,
-                       const struct object_id *new_oid,
-                       int old_oid_valid, int new_oid_valid,
-                       const char *fullpath,
-                       unsigned dirty_submodule1, unsigned dirty_submodule2);
+void diff_change(struct diff_options *,
+                unsigned mode1, unsigned mode2,
+                const struct object_id *old_oid,
+                const struct object_id *new_oid,
+                int old_oid_valid, int new_oid_valid,
+                const char *fullpath,
+                unsigned dirty_submodule1, unsigned dirty_submodule2);
 
-extern struct diff_filepair *diff_unmerge(struct diff_options *, const char *path);
+struct diff_filepair *diff_unmerge(struct diff_options *, const char *path);
 
 #define DIFF_SETUP_REVERSE             1
-#define DIFF_SETUP_USE_CACHE           2
 #define DIFF_SETUP_USE_SIZE_CACHE      4
 
 /*
  * Poor man's alternative to parse-option, to allow both stuck form
  * (--option=value) and separate form (--option value).
  */
-extern int parse_long_opt(const char *opt, const char **argv,
-                        const char **optarg);
-
-extern int git_diff_basic_config(const char *var, const char *value, void *cb);
-extern int git_diff_heuristic_config(const char *var, const char *value, void *cb);
-extern void init_diff_ui_defaults(void);
-extern int git_diff_ui_config(const char *var, const char *value, void *cb);
-extern void diff_setup(struct diff_options *);
-extern int diff_opt_parse(struct diff_options *, const char **, int, const char *);
-extern void diff_setup_done(struct diff_options *);
-extern int git_config_rename(const char *var, const char *value);
+int parse_long_opt(const char *opt, const char **argv,
+                  const char **optarg);
+
+int git_diff_basic_config(const char *var, const char *value, void *cb);
+int git_diff_heuristic_config(const char *var, const char *value, void *cb);
+void init_diff_ui_defaults(void);
+int git_diff_ui_config(const char *var, const char *value, void *cb);
+void diff_setup(struct diff_options *);
+int diff_opt_parse(struct diff_options *, const char **, int, const char *);
+void diff_setup_done(struct diff_options *);
+int git_config_rename(const char *var, const char *value);
 
 #define DIFF_DETECT_RENAME     1
 #define DIFF_DETECT_COPY       2
@@ -347,8 +354,8 @@ extern int git_config_rename(const char *var, const char *value);
 
 #define DIFF_PICKAXE_IGNORE_CASE       32
 
-extern void diffcore_std(struct diff_options *);
-extern void diffcore_fix_diff_index(struct diff_options *);
+void diffcore_std(struct diff_options *);
+void diffcore_fix_diff_index(struct diff_options *);
 
 #define COMMON_DIFF_OPTIONS_HELP \
 "\ncommon diff options:\n" \
@@ -378,9 +385,9 @@ extern void diffcore_fix_diff_index(struct diff_options *);
 "                show all files diff when -S is used and hit is found.\n" \
 "  -a  --text    treat all files as text.\n"
 
-extern int diff_queue_is_empty(void);
-extern void diff_flush(struct diff_options*);
-extern void diff_warn_rename_limit(const char *varname, int needed, int degraded_cc);
+int diff_queue_is_empty(void);
+void diff_flush(struct diff_options*);
+void diff_warn_rename_limit(const char *varname, int needed, int degraded_cc);
 
 /* diff-raw status letters */
 #define DIFF_STATUS_ADDED              'A'
@@ -402,24 +409,24 @@ extern void diff_warn_rename_limit(const char *varname, int needed, int degraded
  * This is different from find_unique_abbrev() in that
  * it stuffs the result with dots for alignment.
  */
-extern const char *diff_aligned_abbrev(const struct object_id *sha1, int);
+const char *diff_aligned_abbrev(const struct object_id *sha1, int);
 
 /* do not report anything on removed paths */
 #define DIFF_SILENT_ON_REMOVED 01
 /* report racily-clean paths as modified */
 #define DIFF_RACY_IS_MODIFIED 02
-extern int run_diff_files(struct rev_info *revs, unsigned int option);
-extern int run_diff_index(struct rev_info *revs, int cached);
+int run_diff_files(struct rev_info *revs, unsigned int option);
+int run_diff_index(struct rev_info *revs, int cached);
 
-extern int do_diff_cache(const struct object_id *, struct diff_options *);
-extern int diff_flush_patch_id(struct diff_options *, struct object_id *, int);
+int do_diff_cache(const struct object_id *, struct diff_options *);
+int diff_flush_patch_id(struct diff_options *, struct object_id *, int);
 
-extern int diff_result_code(struct diff_options *, int);
+int diff_result_code(struct diff_options *, int);
 
-extern void diff_no_index(struct rev_info *, int, const char **);
+void diff_no_index(struct rev_info *, int, const char **);
 
-extern int index_differs_from(const char *def, const struct diff_flags *flags,
-                             int ita_invisible_in_index);
+int index_differs_from(const char *def, const struct diff_flags *flags,
+                      int ita_invisible_in_index);
 
 /*
  * Fill the contents of the filespec "df", respecting any textconv defined by
@@ -432,30 +439,30 @@ extern int index_differs_from(const char *def, const struct diff_flags *flags,
  * struct. If it is non-NULL, then "outbuf" points to a newly allocated buffer
  * that should be freed by the caller.
  */
-extern size_t fill_textconv(struct userdiff_driver *driver,
-                           struct diff_filespec *df,
-                           char **outbuf);
+size_t fill_textconv(struct userdiff_driver *driver,
+                    struct diff_filespec *df,
+                    char **outbuf);
 
 /*
  * Look up the userdiff driver for the given filespec, and return it if
  * and only if it has textconv enabled (otherwise return NULL). The result
  * can be passed to fill_textconv().
  */
-extern struct userdiff_driver *get_textconv(struct diff_filespec *one);
+struct userdiff_driver *get_textconv(struct diff_filespec *one);
 
 /*
  * Prepare diff_filespec and convert it using diff textconv API
  * if the textconv driver exists.
  * Return 1 if the conversion succeeds, 0 otherwise.
  */
-extern int textconv_object(const char *path, unsigned mode, const struct object_id *oid, int oid_valid, char **buf, unsigned long *buf_size);
+int textconv_object(const char *path, unsigned mode, const struct object_id *oid, int oid_valid, char **buf, unsigned long *buf_size);
 
-extern int parse_rename_score(const char **cp_p);
+int parse_rename_score(const char **cp_p);
 
-extern long parse_algorithm_value(const char *value);
+long parse_algorithm_value(const char *value);
 
-extern void print_stat_summary(FILE *fp, int files,
-                              int insertions, int deletions);
-extern void setup_diff_pager(struct diff_options *);
+void print_stat_summary(FILE *fp, int files,
+                       int insertions, int deletions);
+void setup_diff_pager(struct diff_options *);
 
 #endif /* DIFF_H */
index a30da16..8d81a45 100644 (file)
@@ -4,6 +4,10 @@
 #ifndef DIFFCORE_H
 #define DIFFCORE_H
 
+#include "cache.h"
+
+struct diff_options;
+
 /* This header file is internal between diff.c and its diff transformers
  * (e.g. diffcore-rename, diffcore-pickaxe).  Never include this header
  * in anything else.
@@ -50,17 +54,17 @@ struct diff_filespec {
        struct userdiff_driver *driver;
 };
 
-extern struct diff_filespec *alloc_filespec(const char *);
-extern void free_filespec(struct diff_filespec *);
-extern void fill_filespec(struct diff_filespec *, const struct object_id *,
-                         int, unsigned short);
+struct diff_filespec *alloc_filespec(const char *);
+void free_filespec(struct diff_filespec *);
+void fill_filespec(struct diff_filespec *, const struct object_id *,
+                  int, unsigned short);
 
 #define CHECK_SIZE_ONLY 1
 #define CHECK_BINARY    2
-extern int diff_populate_filespec(struct diff_filespec *, unsigned int);
-extern void diff_free_filespec_data(struct diff_filespec *);
-extern void diff_free_filespec_blob(struct diff_filespec *);
-extern int diff_filespec_is_binary(struct diff_filespec *);
+int diff_populate_filespec(struct diff_filespec *, unsigned int);
+void diff_free_filespec_data(struct diff_filespec *);
+void diff_free_filespec_blob(struct diff_filespec *);
+int diff_filespec_is_binary(struct diff_filespec *);
 
 struct diff_filepair {
        struct diff_filespec *one;
@@ -86,9 +90,9 @@ struct diff_filepair {
 
 #define DIFF_PAIR_MODE_CHANGED(p) ((p)->one->mode != (p)->two->mode)
 
-extern void diff_free_filepair(struct diff_filepair *);
+void diff_free_filepair(struct diff_filepair *);
 
-extern int diff_unmodified_pair(struct diff_filepair *);
+int diff_unmodified_pair(struct diff_filepair *);
 
 struct diff_queue_struct {
        struct diff_filepair **queue;
@@ -102,16 +106,16 @@ struct diff_queue_struct {
        } while (0)
 
 extern struct diff_queue_struct diff_queued_diff;
-extern struct diff_filepair *diff_queue(struct diff_queue_struct *,
-                                       struct diff_filespec *,
-                                       struct diff_filespec *);
-extern void diff_q(struct diff_queue_struct *, struct diff_filepair *);
+struct diff_filepair *diff_queue(struct diff_queue_struct *,
+                                struct diff_filespec *,
+                                struct diff_filespec *);
+void diff_q(struct diff_queue_struct *, struct diff_filepair *);
 
-extern void diffcore_break(int);
-extern void diffcore_rename(struct diff_options *);
-extern void diffcore_merge_broken(void);
-extern void diffcore_pickaxe(struct diff_options *);
-extern void diffcore_order(const char *orderfile);