Merge branch 'bp/test-drop-caches-for-windows'
authorJunio C Hamano <gitster@pobox.com>
Thu, 2 Aug 2018 22:30:38 +0000 (15:30 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 2 Aug 2018 22:30:38 +0000 (15:30 -0700)
A test helper update for Windows.

* bp/test-drop-caches-for-windows:
  handle lower case drive letters on Windows

277 files changed:
.gitignore
.mailmap
Documentation/RelNotes/2.19.0.txt [new file with mode: 0644]
Documentation/SubmittingPatches
Documentation/config.txt
Documentation/git-apply.txt
Documentation/git-bisect-lk2009.txt
Documentation/git-branch.txt
Documentation/git-grep.txt
Documentation/git-help.txt
Documentation/git-imap-send.txt
Documentation/git-notes.txt
Documentation/git-rebase.txt
Documentation/git-send-email.txt
Documentation/git-show-index.txt
Documentation/git-status.txt
Documentation/git-submodule.txt
Documentation/git-svn.txt
Documentation/giteveryday.txt
Documentation/gitignore.txt
Documentation/gitsubmodules.txt
Documentation/glossary-content.txt
Documentation/revisions.txt
Documentation/technical/api-directory-listing.txt
Documentation/technical/api-gitattributes.txt
Documentation/technical/commit-graph-format.txt
Documentation/technical/commit-graph.txt
Documentation/technical/directory-rename-detection.txt [new file with mode: 0644]
Documentation/technical/pack-protocol.txt
Documentation/technical/protocol-v2.txt
GIT-VERSION-GEN
Makefile
RelNotes
advice.c
advice.h
alloc.c
alloc.h [new file with mode: 0644]
apply.c
apply.h
archive-tar.c
archive-zip.c
archive.c
bisect.c
blame.c
blame.h
blob.c
branch.c
builtin.h
builtin/am.c
builtin/blame.c
builtin/branch.c
builtin/cat-file.c
builtin/checkout.c
builtin/clean.c
builtin/clone.c
builtin/commit-tree.c
builtin/commit.c
builtin/config.c
builtin/describe.c
builtin/diff.c
builtin/difftool.c
builtin/fast-export.c
builtin/fetch.c
builtin/fmt-merge-msg.c
builtin/grep.c
builtin/hash-object.c
builtin/help.c
builtin/log.c
builtin/ls-tree.c
builtin/merge-tree.c
builtin/merge.c
builtin/mktag.c
builtin/mktree.c
builtin/name-rev.c
builtin/notes.c
builtin/pack-objects.c
builtin/prune.c
builtin/pull.c
builtin/receive-pack.c
builtin/reflog.c
builtin/remote.c
builtin/replace.c
builtin/reset.c
builtin/rev-list.c
builtin/rev-parse.c
builtin/send-pack.c
builtin/show-branch.c
builtin/show-index.c [moved from show-index.c with 96% similarity]
builtin/show-ref.c
builtin/submodule--helper.c
builtin/tag.c
builtin/unpack-file.c
builtin/unpack-objects.c
builtin/update-ref.c
builtin/verify-commit.c
bulk-checkin.c
bundle.c
cache-tree.c
cache.h
combine-diff.c
commit-graph.c
commit-graph.h
commit-slab-decl.h [new file with mode: 0644]
commit-slab-impl.h [new file with mode: 0644]
commit-slab.h
commit.c
commit.h
compat/vcbuild/README
config.c
config.h
connect.h
connected.c
connected.h
contrib/completion/git-completion.bash
contrib/credential/netrc/Makefile
contrib/credential/netrc/t-git-credential-netrc.sh
contrib/credential/netrc/test.pl
contrib/git-jump/README
contrib/git-jump/git-jump
convert.c
diff-lib.c
diff.c
diffcore-rename.c
dir.c
entry.c
environment.c
ewah/bitmap.c
ewah/ewah_bitmap.c
ewah/ewah_io.c
ewah/ewah_rlw.c
ewah/ewok.h
ewah/ewok_rlw.h
fast-import.c
fetch-object.c
fetch-pack.c
fetch-pack.h
fsck.c
generate-cmdlist.sh
git-add--interactive.perl
git-filter-branch.sh
git-p4.py
git-rebase--interactive.sh
git-rebase--merge.sh
git-rebase--preserve-merges.sh [new file with mode: 0644]
git-rebase.sh
git-send-email.perl
git-submodule.sh
git.c
gpg-interface.c
gpg-interface.h
grep.c
grep.h
help.c
help.h
list-objects-filter-options.c
list-objects-filter.c
list-objects.c
log-tree.c
mailmap.c
match-trees.c
merge-blobs.c
merge-recursive.c
notes-cache.c
notes-merge.c
notes.c
object-store.h
object.c
object.h
pack-bitmap-write.c
pack-bitmap.c
pack-bitmap.h
packfile.h
parse-options.c
path.c
path.h
read-cache.c
ref-filter.c
refs.c
refs/files-backend.c
refs/packed-backend.c
refs/refs-internal.h
refspec.c
refspec.h
remote-testsvn.c
remote.c
remote.h
repository.c
repository.h
rerere.c
revision.c
revision.h
send-pack.c
sequencer.c
sha1-file.c
sha1-name.c
shallow.c
string-list.c
submodule-config.c
submodule-config.h
submodule.c
submodule.h
t/check-non-portable-shell.pl
t/helper/test-pkt-line.c
t/lib-httpd.sh
t/lib-httpd/apache.conf
t/lib-httpd/apply-one-time-sed.sh [new file with mode: 0644]
t/lib-submodule-update.sh
t/t0001-init.sh
t/t0020-crlf.sh
t/t0070-fundamental.sh
t/t0410-partial-clone.sh
t/t1004-read-tree-m-u-wf.sh
t/t1410-reflog.sh
t/t2203-add-intent.sh
t/t3035-merge-sparse.sh [new file with mode: 0755]
t/t3200-branch.sh
t/t3401-rebase-and-am-rename.sh [new file with mode: 0755]
t/t3404-rebase-interactive.sh
t/t3405-rebase-malformed.sh
t/t3418-rebase-continue.sh
t/t3422-rebase-incompatible-options.sh [new file with mode: 0755]
t/t3423-rebase-reword.sh [new file with mode: 0755]
t/t3510-cherry-pick-sequence.sh
t/t3701-add-interactive.sh
t/t4011-diff-symlink.sh
t/t4014-format-patch.sh
t/t4018/php-abstract-class [new file with mode: 0644]
t/t4018/php-class [new file with mode: 0644]
t/t4018/php-final-class [new file with mode: 0644]
t/t4018/php-function [new file with mode: 0644]
t/t4018/php-interface [new file with mode: 0644]
t/t4018/php-method [new file with mode: 0644]
t/t4018/php-trait [new file with mode: 0644]
t/t4208-log-magic-pathspec.sh
t/t4254-am-corrupt.sh
t/t5317-pack-objects-filter-objects.sh
t/t5318-commit-graph.sh
t/t5407-post-rewrite-hook.sh
t/t5500-fetch-pack.sh
t/t5520-pull.sh
t/t5526-fetch-submodules.sh
t/t5537-fetch-shallow.sh
t/t5573-pull-verify-signatures.sh
t/t5616-partial-clone.sh
t/t5703-upload-pack-ref-in-want.sh [new file with mode: 0755]
t/t6036-recursive-corner-cases.sh
t/t6042-merge-rename-corner-cases.sh
t/t6046-merge-skip-unneeded-updates.sh
t/t6300-for-each-ref.sh
t/t7003-filter-branch.sh
t/t7030-verify-tag.sh
t/t7400-submodule-basic.sh
t/t7407-submodule-foreach.sh
t/t7508-status.sh
t/t7510-signed-commit.sh
t/t7612-merge-verify-signatures.sh
t/t7810-grep.sh
t/t9001-send-email.sh
t/t9104-git-svn-follow-parent.sh
t/t9833-errors.sh
t/t9902-completion.sh
tag.c
tag.h
transport-helper.c
transport-internal.h
transport.c
transport.h
tree-walk.c
tree.c
unicode-width.h
unpack-trees.c
upload-pack.c
userdiff.c
utf8.c
walker.c
wt-status.c
xdiff-interface.c

index 388cc4b..3284a1e 100644 (file)
 /git-rebase--helper
 /git-rebase--interactive
 /git-rebase--merge
+/git-rebase--preserve-merges
 /git-receive-pack
 /git-reflog
 /git-remote
index df7cf63..f165222 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -35,11 +35,13 @@ Chris Wright <chrisw@sous-sol.org> <chrisw@osdl.org>
 Cord Seele <cowose@gmail.com> <cowose@googlemail.com>
 Christian Couder <chriscool@tuxfamily.org> <christian.couder@gmail.com>
 Christian Stimming <stimming@tuhh.de> <chs@ckiste.goetheallee>
+Christopher Díaz Riveros <chrisadr@gentoo.org> Christopher Diaz Riveros
 Csaba Henk <csaba@gluster.com> <csaba@lowlife.hu>
 Dan Johnson <computerdruid@gmail.com>
 Dana L. How <danahow@gmail.com> <how@deathvalley.cswitch.com>
 Dana L. How <danahow@gmail.com> Dana How
 Daniel Barkalow <barkalow@iabervon.org>
+Daniel Knittl-Frank <knittl89@googlemail.com> knittl
 Daniel Trstenjak <daniel.trstenjak@gmail.com> <daniel.trstenjak@online.de>
 Daniel Trstenjak <daniel.trstenjak@gmail.com> <trsten@science-computing.de>
 David Brown <git@davidb.org> <davidb@quicinc.com>
@@ -57,6 +59,7 @@ Eric S. Raymond <esr@thyrsus.com>
 Eric Wong <e@80x24.org> <normalperson@yhbt.net>
 Erik Faye-Lund <kusmabite@gmail.com> <kusmabite@googlemail.com>
 Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com> <eyvind-git@orakel.ntnu.no>
+Fangyi Zhou <fangyi.zhou@yuriko.moe> Zhou Fangyi
 Florian Achleitner <florian.achleitner.2.6.31@gmail.com> <florian.achleitner2.6.31@gmail.com>
 Franck Bui-Huu <vagabon.xyz@gmail.com> <fbuihuu@gmail.com>
 Frank Lichtenheld <frank@lichtenheld.de> <djpig@debian.org>
@@ -86,6 +89,8 @@ Jason McMullan <mcmullan@netapp.com>
 Jason Riedy <ejr@eecs.berkeley.edu> <ejr@EECS.Berkeley.EDU>
 Jason Riedy <ejr@eecs.berkeley.edu> <ejr@cs.berkeley.edu>
 Jay Soffian <jaysoffian@gmail.com> <jaysoffian+git@gmail.com>
+Jean-Noël Avila <jn.avila@free.fr> Jean-Noel Avila
+Jean-Noël Avila <jn.avila@free.fr> Jean-Noël AVILA
 Jeff King <peff@peff.net> <peff@github.com>
 Jeff Muizelaar <jmuizelaar@mozilla.com> <jeff@infidigm.net>
 Jens Axboe <axboe@kernel.dk> <axboe@suse.de>
@@ -149,6 +154,7 @@ Matt Draisey <matt@draisey.ca> <mattdraisey@sympatico.ca>
 Matt Kraai <kraai@ftbfs.org> <matt.kraai@amo.abbott.com>
 Matt McCutchen <matt@mattmccutchen.net> <hashproduct@gmail.com>
 Matthias Kestenholz <matthias@spinlock.ch> <mk@spinlock.ch>
+Matthias Rüster <matthias.ruester@gmail.com> Matthias Ruester
 Matthias Urlichs <matthias@urlichs.de> <smurf@kiste.(none)>
 Matthias Urlichs <matthias@urlichs.de> <smurf@smurf.noris.de>
 Michael Coleman <tutufan@gmail.com>
@@ -213,6 +219,8 @@ Sean Estabrooks <seanlkml@sympatico.ca>
 Sebastian Schuberth <sschuberth@gmail.com> <sschuberth@visageimaging.com>
 Seth Falcon <seth@userprimary.net> <sfalcon@fhcrc.org>
 Shawn O. Pearce <spearce@spearce.org>
+Wei Shuyu <wsy@dogben.com> Shuyu Wei
+Sidhant Sharma <tigerkid001@gmail.com> Sidhant Sharma [:tk]
 Simon Hausmann <hausmann@kde.org> <simon@lst.de>
 Simon Hausmann <hausmann@kde.org> <shausman@trolltech.com>
 Stefan Beller <stefanbeller@gmail.com> <stefanbeller@googlemail.com>
@@ -253,7 +261,8 @@ Uwe Kleine-König <u.kleine-koenig@pengutronix.de> <ukleinek@informatik.uni-frei
 Uwe Kleine-König <u.kleine-koenig@pengutronix.de> <uzeisberger@io.fsforth.de>
 Uwe Kleine-König <u.kleine-koenig@pengutronix.de> <zeisberg@informatik.uni-freiburg.de>
 Ville Skyttä <ville.skytta@iki.fi> <scop@xemacs.org>
-Vitaly "_Vi" Shukela <public_vi@tut.by>
+Vitaly "_Vi" Shukela <vi0oss@gmail.com> <public_vi@tut.by>
+Vitaly "_Vi" Shukela <vi0oss@gmail.com> Vitaly _Vi Shukela
 W. Trevor King <wking@tremily.us> <wking@drexel.edu>
 William Pursell <bill.pursell@gmail.com>
 YONETANI Tomokazu <y0n3t4n1@gmail.com> <qhwt+git@les.ath.cx>
diff --git a/Documentation/RelNotes/2.19.0.txt b/Documentation/RelNotes/2.19.0.txt
new file mode 100644 (file)
index 0000000..7a5c5b8
--- /dev/null
@@ -0,0 +1,239 @@
+Git 2.19 Release Notes
+======================
+
+Updates since v2.18
+-------------------
+
+UI, Workflows & Features
+
+ * "git diff" compares the index and the working tree.  For paths
+   added with intent-to-add bit, the command shows the full contents
+   of them as added, but the paths themselves were not marked as new
+   files.  They are now shown as new by default.
+
+   "git apply" learned the "--intent-to-add" option so that an
+   otherwise working-tree-only application of a patch will add new
+   paths to the index marked with the "intent-to-add" bit.
+
+ * "git grep" learned the "--column" option that gives not just the
+   line number but the column number of the hit.
+
+ * The "-l" option in "git branch -l" is an unfortunate short-hand for
+   "--create-reflog", but many users, both old and new, somehow expect
+   it to be something else, perhaps "--list".  This step warns when "-l"
+   is used as a short-hand for "--create-reflog" and warns about the
+   future repurposing of the it when it is used.
+
+ * The userdiff pattern for .php has been updated.
+
+ * The content-transfer-encoding of the message "git send-email" sends
+   out by default was 8bit, which can cause trouble when there is an
+   overlong line to bust RFC 5322/2822 limit.  A new option 'auto' to
+   automatically switch to quoted-printable when there is such a line
+   in the payload has been introduced and is made the default.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * The bulk of "git submodule foreach" has been rewritten in C.
+
+ * The in-core "commit" object had an all-purpose "void *util" field,
+   which was tricky to use especially in library-ish part of the
+   code.  All of the existing uses of the field has been migrated to a
+   more dedicated "commit-slab" mechanism and the field is eliminated.
+
+ * A less often used command "git show-index" has been modernized.
+   (merge fb3010c31f jk/show-index later to maint).
+
+ * The conversion to pass "the_repository" and then "a_repository"
+   throughout the object access API continues.
+
+ * Continuing with the idea to programatically enumerate various
+   pieces of data required for command line completion, teach the
+   codebase to report the list of configuration variables
+   subcommands care about to help complete them.
+
+ * Separate "rebase -p" codepath out of "rebase -i" implementation to
+   slim down the latter and make it easier to manage.
+
+ * Make refspec parsing codepath more robust.
+
+ * Some flaky tests have been fixed.
+
+ * Continuing with the idea to programmatically enumerate various
+   pieces of data required for command line completion, the codebase
+   has been taught to enumerate options prefixed with "--no-" to
+   negate them.
+
+ * Build and test procedure for netrc credential helper (in contrib/)
+   has been updated.
+
+ * The conversion to pass "the_repository" and then "a_repository"
+   throughout the object access API continues.
+
+ * Remove unused function definitions and declarations from ewah
+   bitmap subsystem.
+
+ * Code preparation to make "git p4" closer to be usable with Python 3.
+
+ * Tighten the API to make it harder to misuse in-tree .gitmodules
+   file, even though it shares the same syntax with configuration
+   files, to read random configuration items from it.
+
+ * "git fast-import" has been updated to avoid attempting to create
+   delta against a zero-byte-long string, which is pointless.
+
+ * The codebase has been updated to compile cleanly with -pedantic
+   option.
+   (merge 2b647a05d7 bb/pedantic later to maint).
+
+ * The character display width table has been updated to match the
+   latest Unicode standard.
+   (merge 570951eea2 bb/unicode-11-width later to maint).
+
+ * test-lint now looks for broken use of "VAR=VAL shell_func" in test
+   scripts.
+
+
+Fixes since v2.18
+-----------------
+
+ * "git remote update" can take both a single remote nickname and a
+   nickname for remote groups, and the completion script (in contrib/)
+   has been taught about it.
+   (merge 9cd4382ad5 ls/complete-remote-update-names later to maint).
+
+ * "git fetch --shallow-since=<cutoff>" that specifies the cut-off
+   point that is newer than the existing history used to end up
+   grabbing the entire history.  Such a request now errors out.
+   (merge e34de73c56 nd/reject-empty-shallow-request later to maint).
+
+ * Fix for 2.17-era regression around `core.safecrlf`.
+   (merge 6cb09125be as/safecrlf-quiet-fix later to maint).
+
+ * The recent addition of "partial clone" experimental feature kicked
+   in when it shouldn't, namely, when there is no partial-clone filter
+   defined even if extensions.partialclone is set.
+   (merge cac1137dc4 jh/partial-clone later to maint).
+
+ * "git send-pack --signed" (hence "git push --signed" over the http
+   transport) did not read user ident from the config mechanism to
+   determine whom to sign the push certificate as, which has been
+   corrected.
+   (merge d067d98887 ms/send-pack-honor-config later to maint).
+
+ * "git fetch-pack --all" used to unnecessarily fail upon seeing an
+   annotated tag that points at an object other than a commit.
+   (merge c12c9df527 jk/fetch-all-peeled-fix later to maint).
+
+ * When user edits the patch in "git add -p" and the user's editor is
+   set to strip trailing whitespaces indiscriminately, an empty line
+   that is unchanged in the patch would become completely empty
+   (instead of a line with a sole SP on it).  The code introduced in
+   Git 2.17 timeframe failed to parse such a patch, but now it learned
+   to notice the situation and cope with it.
+   (merge f4d35a6b49 pw/add-p-recount later to maint).
+
+ * The code to try seeing if a fetch is necessary in a submodule
+   during a fetch with --recurse-submodules got confused when the path
+   to the submodule was changed in the range of commits in the
+   superproject, sometimes showing "(null)".  This has been corrected.
+
+ * "git submodule" did not correctly adjust core.worktree setting that
+   indicates whether/where a submodule repository has its associated
+   working tree across various state transitions, which has been
+   corrected.
+   (merge 984cd77ddb sb/submodule-core-worktree later to maint).
+
+ * Bugfix for "rebase -i" corner case regression.
+   (merge a9279c6785 pw/rebase-i-keep-reword-after-conflict later to maint).
+
+ * Recently added "--base" option to "git format-patch" command did
+   not correctly generate prereq patch ids.
+   (merge 15b76c1fb3 xy/format-patch-prereq-patch-id-fix later to maint).
+
+ * POSIX portability fix in Makefile to fix a glitch introduced a few
+   releases ago.
+   (merge 6600054e9b dj/runtime-prefix later to maint).
+
+ * "git filter-branch" when used with the "--state-branch" option
+   still attempted to rewrite the commits whose filtered result is
+   known from the previous attempt (which is recorded on the state
+   branch); the command has been corrected not to waste cycles doing
+   so.
+   (merge 709cfe848a mb/filter-branch-optim later to maint).
+
+ * Clarify that setting core.ignoreCase to deviate from reality would
+   not turn a case-incapable filesystem into a case-capable one.
+   (merge 48294b512a ms/core-icase-doc later to maint).
+
+ * "fsck.skipList" did not prevent a blob object listed there from
+   being inspected for is contents (e.g. we recently started to
+   inspect the contents of ".gitmodules" for certain malicious
+   patterns), which has been corrected.
+   (merge fb16287719 rj/submodule-fsck-skip later to maint).
+
+ * "git checkout --recurse-submodules another-branch" did not report
+   in which submodule it failed to update the working tree, which
+   resulted in an unhelpful error message.
+   (merge ba95d4e4bd sb/submodule-move-head-error-msg later to maint).
+
+ * "git rebase" behaved slightly differently depending on which one of
+   the three backends gets used; this has been documented and an
+   effort to make them more uniform has begun.
+   (merge b00bf1c9a8 en/rebase-consistency later to maint).
+
+ * The "--ignore-case" option of "git for-each-ref" (and its friends)
+   did not work correctly, which has been fixed.
+   (merge e674eb2528 jk/for-each-ref-icase later to maint).
+
+ * "git fetch" failed to correctly validate the set of objects it
+   received when making a shallow history deeper, which has been
+   corrected.
+   (merge cf1e7c0770 jt/connectivity-check-after-unshallow later to maint).
+
+ * Partial clone support of "git clone" has been updated to correctly
+   validate the objects it receives from the other side.  The server
+   side has been corrected to send objects that are directly
+   requested, even if they may match the filtering criteria (e.g. when
+   doing a "lazy blob" partial clone).
+   (merge a7e67c11b8 jt/partial-clone-fsck-connectivity later to maint).
+
+ * Handling of an empty range by "git cherry-pick" was inconsistent
+   depending on how the range ended up to be empty, which has been
+   corrected.
+   (merge c5e358d073 jk/empty-pick-fix later to maint).
+
+ * "git reset --merge" (hence "git merge ---abort") and "git reset --hard"
+   had trouble working correctly in a sparsely checked out working
+   tree after a conflict, which has been corrected.
+   (merge b33fdfc34c mk/merge-in-sparse-checkout later to maint).
+
+ * Correct a broken use of "VAR=VAL shell_func" in a test.
+   (merge 650161a277 jc/t3404-one-shot-export-fix later to maint).
+
+ * "git rev-parse ':/substring'" did not consider the history leading
+   only to HEAD when looking for a commit with the given substring,
+   when the HEAD is detached.  This has been fixed.
+   (merge 6b3351e799 wc/find-commit-with-pattern-on-detached-head later to maint).
+
+ * Build doc update for Windows.
+   (merge ede8d89bb1 nd/command-list later to maint).
+
+ * core.commentchar is now honored when preparing the list of commits
+   to replay in "rebase -i".
+
+ * 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).
+   (merge 5b26c3c941 en/merge-recursive-cleanup later to maint).
+   (merge 0dcbc0392e bw/config-refer-to-gitsubmodules-doc later to maint).
+   (merge bb4d000e87 bw/protocol-v2 later to maint).
+   (merge 928f0ab4ba vs/typofixes later to maint).
+   (merge d7f590be84 en/rebase-i-microfixes later to maint).
+   (merge 81d395cc85 js/rebase-recreate-merge later to maint).
+   (merge 51d1863168 tz/exclude-doc-smallfixes later to maint).
+   (merge a9aa3c0927 ds/commit-graph later to maint).
+   (merge 5cf8e06474 js/enhanced-version-info later to maint).
+   (merge 6aaded5509 tb/config-default later to maint).
+   (merge 022d2ac1f3 sb/blame-color later to maint).
index 2488544..b44fd51 100644 (file)
@@ -298,7 +298,7 @@ smaller project it is a good discipline to follow it.
 
 The sign-off is a simple line at the end of the explanation for
 the patch, which certifies that you wrote it or otherwise have
-the right to pass it on as a open-source patch.  The rules are
+the right to pass it on as an open-source patch.  The rules are
 pretty simple: if you can certify the below D-C-O:
 
 [[dco]]
@@ -403,7 +403,7 @@ don't demand).  +git log -p {litdd} _$area_you_are_modifying_+ would
 help you find out who they are.
 
 . You get comments and suggestions for improvements.  You may
-  even get them in a "on top of your change" patch form.
+  even get them in an "on top of your change" patch form.
 
 . Polish, refine, and re-send to the list and the people who
   spend their time to improve your patch.  Go back to step (2).
index ab641bf..43b2de7 100644 (file)
@@ -354,7 +354,7 @@ advice.*::
                Advice on what to do when you've accidentally added one
                git repo inside of another.
        ignoredHook::
-               Advice shown if an hook is ignored because the hook is not
+               Advice shown if a hook is ignored because the hook is not
                set as executable.
        waitingForEditor::
                Print a message to the terminal whenever Git is waiting for
@@ -390,16 +390,19 @@ core.hideDotFiles::
        default mode is 'dotGitOnly'.
 
 core.ignoreCase::
-       If true, this option enables various workarounds to enable
+       Internal variable which enables various workarounds to enable
        Git to work better on filesystems that are not case sensitive,
-       like FAT. For example, if a directory listing finds
-       "makefile" when Git expects "Makefile", Git will assume
+       like APFS, HFS+, FAT, NTFS, etc. For example, if a directory listing
+       finds "makefile" when Git expects "Makefile", Git will assume
        it is really the same file, and continue to remember it as
        "Makefile".
 +
 The default is false, except linkgit:git-clone[1] or linkgit:git-init[1]
 will probe and set core.ignoreCase true if appropriate when the repository
 is created.
++
+Git relies on the proper configuration of this variable for your operating
+and file system. Modifying this value may result in unexpected behavior.
 
 core.precomposeUnicode::
        This option is only used by Mac OS implementation of Git.
@@ -1162,7 +1165,8 @@ color.diff.<slot>::
 color.decorate.<slot>::
        Use customized color for 'git log --decorate' output.  `<slot>` is one
        of `branch`, `remoteBranch`, `tag`, `stash` or `HEAD` for local
-       branches, remote-tracking branches, tags, stash and HEAD, respectively.
+       branches, remote-tracking branches, tags, stash and HEAD, respectively
+       and `grafted` for grafted commits.
 
 color.grep::
        When set to `always`, always highlight matches.  When `false` (or
@@ -1181,8 +1185,10 @@ color.grep.<slot>::
        filename prefix (when not using `-h`)
 `function`;;
        function name lines (when using `-p`)
-`linenumber`;;
+`lineNumber`;;
        line number prefix (when using `-n`)
+`column`;;
+       column number prefix (when using `--column`)
 `match`;;
        matching text (same as setting `matchContext` and `matchSelected`)
 `matchContext`;;
@@ -1797,6 +1803,9 @@ gitweb.snapshot::
 grep.lineNumber::
        If set to true, enable `-n` option by default.
 
+grep.column::
+       If set to true, enable the `--column` option by default.
+
 grep.patternType::
        Set the default matching behavior. Using a value of 'basic', 'extended',
        'fixed', or 'perl' will enable the `--basic-regexp`, `--extended-regexp`,
@@ -3327,12 +3336,13 @@ submodule.<name>.ignore::
 submodule.<name>.active::
        Boolean value indicating if the submodule is of interest to git
        commands.  This config option takes precedence over the
-       submodule.active config option.
+       submodule.active config option. See linkgit:gitsubmodules[7] for
+       details.
 
 submodule.active::
        A repeated field which contains a pathspec used to match against a
        submodule's path to determine if the submodule is of interest to git
-       commands.
+       commands. See linkgit:gitsubmodules[7] for details.
 
 submodule.recurse::
        Specifies if commands recurse into submodules by default. This
@@ -3479,6 +3489,13 @@ Note that this configuration variable is ignored if it is seen in the
 repository-level config (this is a safety measure against fetching from
 untrusted repositories).
 
+uploadpack.allowRefInWant::
+       If this option is set, `upload-pack` will support the `ref-in-want`
+       feature of the protocol version 2 `fetch` command.  This feature
+       is intended for the benefit of load-balanced servers which may
+       not have the same view of what OIDs their refs point to due to
+       replication delay.
+
 url.<base>.insteadOf::
        Any URL that starts with this value will be rewritten to
        start, instead, with <base>. In cases where some site serves a
index 6722849..b9aa390 100644 (file)
@@ -9,7 +9,7 @@ git-apply - Apply a patch to files and/or to the index
 SYNOPSIS
 --------
 [verse]
-'git apply' [--stat] [--numstat] [--summary] [--check] [--index] [--3way]
+'git apply' [--stat] [--numstat] [--summary] [--check] [--index | --intent-to-add] [--3way]
          [--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]
          [--allow-binary-replacement | --binary] [--reject] [-z]
          [-p<n>] [-C<n>] [--inaccurate-eof] [--recount] [--cached]
@@ -74,6 +74,14 @@ OPTIONS
        cached data, apply the patch, and store the result in the index
        without using the working tree. This implies `--index`.
 
+--intent-to-add::
+       When applying the patch only to the working tree, mark new
+       files to be added to the index later (see `--intent-to-add`
+       option in linkgit:git-add[1]). This option is ignored unless
+       running in a Git repository and `--index` is not specified.
+       Note that `--index` could be implied by other options such
+       as `--cached` or `--3way`.
+
 -3::
 --3way::
        When the patch does not apply cleanly, fall back on 3-way merge if
index 78479b0..0f9ef2f 100644 (file)
@@ -1103,7 +1103,7 @@ _____________
 Combining test suites, git bisect and other systems together
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-We have seen that test suites an git bisect are very powerful when
+We have seen that test suites and git bisect are very powerful when
 used together. It can be even more powerful if you can combine them
 with other systems.
 
index 02eccbb..1072ca0 100644 (file)
@@ -91,7 +91,6 @@ OPTIONS
 -D::
        Shortcut for `--delete --force`.
 
--l::
 --create-reflog::
        Create the branch's reflog.  This activates recording of
        all changes made to the branch ref, enabling use of date
@@ -101,6 +100,8 @@ OPTIONS
        The negated form `--no-create-reflog` only overrides an earlier
        `--create-reflog`, but currently does not negate the setting of
        `core.logAllRefUpdates`.
++
+The `-l` option is a deprecated synonym for `--create-reflog`.
 
 -f::
 --force::
index 312409a..0de3493 100644 (file)
@@ -13,7 +13,7 @@ SYNOPSIS
           [-v | --invert-match] [-h|-H] [--full-name]
           [-E | --extended-regexp] [-G | --basic-regexp]
           [-P | --perl-regexp]
-          [-F | --fixed-strings] [-n | --line-number]
+          [-F | --fixed-strings] [-n | --line-number] [--column]
           [-l | --files-with-matches] [-L | --files-without-match]
           [(-O | --open-files-in-pager) [<pager>]]
           [-z | --null]
@@ -44,6 +44,9 @@ CONFIGURATION
 grep.lineNumber::
        If set to true, enable `-n` option by default.
 
+grep.column::
+       If set to true, enable the `--column` option by default.
+
 grep.patternType::
        Set the default matching behavior. Using a value of 'basic', 'extended',
        'fixed', or 'perl' will enable the `--basic-regexp`, `--extended-regexp`,
@@ -169,6 +172,10 @@ providing this option will cause it to die.
 --line-number::
        Prefix the line number to matching lines.
 
+--column::
+       Prefix the 1-indexed byte-offset of the first match from the start of the
+       matching line.
+
 -l::
 --files-with-matches::
 --name-only::
index a40fc38..83d25d8 100644 (file)
@@ -45,6 +45,11 @@ OPTIONS
        When used with `--verbose` print description for all recognized
        commands.
 
+-c::
+--config::
+       List all available configuration variables. This is a short
+       summary of the list in linkgit:git-config[1].
+
 -g::
 --guides::
        Prints a list of useful guides on the standard output. This
index 032613c..7b15744 100644 (file)
@@ -68,8 +68,8 @@ imap.tunnel::
        to the server. Required when imap.host is not set.
 
 imap.host::
-       A URL identifying the server. Use a `imap://` prefix for non-secure
-       connections and a `imaps://` prefix for secure connections.
+       A URL identifying the server. Use an `imap://` prefix for non-secure
+       connections and an `imaps://` prefix for secure connections.
        Ignored when imap.tunnel is set, but required otherwise.
 
 imap.user::
index e8dec1b..df2b64d 100644 (file)
@@ -199,7 +199,7 @@ OPTIONS
        .git/NOTES_MERGE_REF symref is updated to the resulting commit.
 
 --abort::
-       Abort/reset a in-progress 'git notes merge', i.e. a notes merge
+       Abort/reset an in-progress 'git notes merge', i.e. a notes merge
        with conflicts. This simply removes all files related to the
        notes merge.
 
index 0e20a66..a785041 100644 (file)
@@ -243,11 +243,15 @@ leave out at most one of A and B, in which case it defaults to HEAD.
 --keep-empty::
        Keep the commits that do not change anything from its
        parents in the result.
++
+See also INCOMPATIBLE OPTIONS below.
 
 --allow-empty-message::
        By default, rebasing commits with an empty message will fail.
        This option overrides that behavior, allowing commits with empty
        messages to be rebased.
++
+See also INCOMPATIBLE OPTIONS below.
 
 --skip::
        Restart the rebasing process by skipping the current patch.
@@ -271,6 +275,8 @@ branch on top of the <upstream> branch.  Because of this, when a merge
 conflict happens, the side reported as 'ours' is the so-far rebased
 series, starting with <upstream>, and 'theirs' is the working branch.  In
 other words, the sides are swapped.
++
+See also INCOMPATIBLE OPTIONS below.
 
 -s <strategy>::
 --strategy=<strategy>::
@@ -280,8 +286,10 @@ other words, the sides are swapped.
 +
 Because 'git rebase' replays each commit from the working branch
 on top of the <upstream> branch using the given strategy, using
-the 'ours' strategy simply discards all patches from the <branch>,
+the 'ours' strategy simply empties all patches from the <branch>,
 which makes little sense.
++
+See also INCOMPATIBLE OPTIONS below.
 
 -X <strategy-option>::
 --strategy-option=<strategy-option>::
@@ -289,6 +297,8 @@ which makes little sense.
        This implies `--merge` and, if no strategy has been
        specified, `-s recursive`.  Note the reversal of 'ours' and
        'theirs' as noted above for the `-m` option.
++
+See also INCOMPATIBLE OPTIONS below.
 
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
@@ -324,17 +334,21 @@ which makes little sense.
        and after each change.  When fewer lines of surrounding
        context exist they all must match.  By default no context is
        ever ignored.
++
+See also INCOMPATIBLE OPTIONS below.
 
--f::
+--no-ff::
 --force-rebase::
-       Force a rebase even if the current branch is up to date and
-       the command without `--force` would return without doing anything.
+-f::
+       Individually replay all rebased commits instead of fast-forwarding
+       over the unchanged ones.  This ensures that the entire history of
+       the rebased branch is composed of new commits.
 +
-You may find this (or --no-ff with an interactive rebase) helpful after
-reverting a topic branch merge, as this option recreates the topic branch with
-fresh commits so it can be remerged successfully without needing to "revert
-the reversion" (see the
-link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details).
+You may find this helpful after reverting a topic branch merge, as this option
+recreates the topic branch with fresh commits so it can be remerged
+successfully without needing to "revert the reversion" (see the
+link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for
+details).
 
 --fork-point::
 --no-fork-point::
@@ -355,19 +369,22 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
 --whitespace=<option>::
        These flag are passed to the 'git apply' program
        (see linkgit:git-apply[1]) that applies the patch.
-       Incompatible with the --interactive option.
++
+See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
 --ignore-date::
        These flags are passed to 'git am' to easily change the dates
        of the rebased commits (see linkgit:git-am[1]).
-       Incompatible with the --interactive option.
++
+See also INCOMPATIBLE OPTIONS below.
 
 --signoff::
        Add a Signed-off-by: trailer to all the rebased commits. Note
        that if `--interactive` is given then only commits marked to be
-       picked, edited or reworded will have the trailer added. Incompatible
-       with the `--preserve-merges` option.
+       picked, edited or reworded will have the trailer added.
++
+See also INCOMPATIBLE OPTIONS below.
 
 -i::
 --interactive::
@@ -378,6 +395,8 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
 The commit list format can be changed by setting the configuration option
 rebase.instructionFormat.  A customized instruction format will automatically
 have the long commit hash prepended to the format.
++
+See also INCOMPATIBLE OPTIONS below.
 
 -r::
 --rebase-merges[=(rebase-cousins|no-rebase-cousins)]::
@@ -404,7 +423,7 @@ It is currently only possible to recreate the merge commits using the
 `recursive` merge strategy; Different merge strategies can be used only via
 explicit `exec git merge -s <strategy> [...]` commands.
 +
-See also REBASING MERGES below.
+See also REBASING MERGES and INCOMPATIBLE OPTIONS below.
 
 -p::
 --preserve-merges::
@@ -415,6 +434,8 @@ See also REBASING MERGES below.
 This uses the `--interactive` machinery internally, but combining it
 with the `--interactive` option explicitly is generally not a good
 idea unless you know what you are doing (see BUGS below).
++
+See also INCOMPATIBLE OPTIONS below.
 
 -x <cmd>::
 --exec <cmd>::
@@ -437,6 +458,8 @@ squash/fixup series.
 +
 This uses the `--interactive` machinery internally, but it can be run
 without an explicit `--interactive`.
++
+See also INCOMPATIBLE OPTIONS below.
 
 --root::
        Rebase all commits reachable from <branch>, instead of
@@ -447,6 +470,8 @@ without an explicit `--interactive`.
        When used together with both --onto and --preserve-merges,
        'all' root commits will be rewritten to have <newbase> as parent
        instead.
++
+See also INCOMPATIBLE OPTIONS below.
 
 --autosquash::
 --no-autosquash::
@@ -461,11 +486,11 @@ without an explicit `--interactive`.
        too.  The recommended way to create fixup/squash commits is by using
        the `--fixup`/`--squash` options of linkgit:git-commit[1].
 +
-This option is only valid when the `--interactive` option is used.
-+
 If the `--autosquash` option is enabled by default using the
 configuration variable `rebase.autoSquash`, this option can be
 used to override and disable this setting.
++
+See also INCOMPATIBLE OPTIONS below.
 
 --autostash::
 --no-autostash::
@@ -475,17 +500,73 @@ used to override and disable this setting.
        with care: the final stash application after a successful
        rebase might result in non-trivial conflicts.
 
---no-ff::
-       With --interactive, cherry-pick all rebased commits instead of
-       fast-forwarding over the unchanged ones.  This ensures that the
-       entire history of the rebased branch is composed of new commits.
-+
-Without --interactive, this is a synonym for --force-rebase.
-+
-You may find this helpful after reverting a topic branch merge, as this option
-recreates the topic branch with fresh commits so it can be remerged
-successfully without needing to "revert the reversion" (see the
-link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details).
+INCOMPATIBLE OPTIONS
+--------------------
+
+git-rebase has many flags that are incompatible with each other,
+predominantly due to the fact that it has three different underlying
+implementations:
+
+ * one based on linkgit:git-am[1] (the default)
+ * one based on git-merge-recursive (merge backend)
+ * one based on linkgit:git-cherry-pick[1] (interactive backend)
+
+Flags only understood by the am backend:
+
+ * --committer-date-is-author-date
+ * --ignore-date
+ * --whitespace
+ * --ignore-whitespace
+ * -C
+
+Flags understood by both merge and interactive backends:
+
+ * --merge
+ * --strategy
+ * --strategy-option
+ * --allow-empty-message
+
+Flags only understood by the interactive backend:
+
+ * --[no-]autosquash
+ * --rebase-merges
+ * --preserve-merges
+ * --interactive
+ * --exec
+ * --keep-empty
+ * --autosquash
+ * --edit-todo
+ * --root when used in combination with --onto
+
+Other incompatible flag pairs:
+
+ * --preserve-merges and --interactive
+ * --preserve-merges and --signoff
+ * --preserve-merges and --rebase-merges
+ * --rebase-merges and --strategy
+ * --rebase-merges and --strategy-option
+
+BEHAVIORAL DIFFERENCES
+-----------------------
+
+ * empty commits:
+
+    am-based rebase will drop any "empty" commits, whether the
+    commit started empty (had no changes relative to its parent to
+    start with) or ended empty (all changes were already applied
+    upstream in other commits).
+
+    merge-based rebase does the same.
+
+    interactive-based rebase will by default drop commits that
+    started empty and halt if it hits a commit that ended up empty.
+    The `--keep-empty` option exists for interactive rebases to allow
+    it to keep commits that started empty.
+
+  * directory rename detection:
+
+    merge-based and interactive-based rebases work fine with
+    directory rename detection.  am-based rebases sometimes do not.
 
 include::merge-strategies.txt[]
 
@@ -804,7 +885,7 @@ The ripple effect of a "hard case" recovery is especially bad:
 case" recovery too!
 
 REBASING MERGES
------------------
+---------------
 
 The interactive rebase command was originally designed to handle
 individual patch series. As such, it makes sense to exclude merge
index 4f3efde..465a4ec 100644 (file)
@@ -137,15 +137,17 @@ Note that no attempts whatsoever are made to validate the encoding.
        Specify encoding of compose message. Default is the value of the
        'sendemail.composeencoding'; if that is unspecified, UTF-8 is assumed.
 
---transfer-encoding=(7bit|8bit|quoted-printable|base64)::
+--transfer-encoding=(7bit|8bit|quoted-printable|base64|auto)::
        Specify the transfer encoding to be used to send the message over SMTP.
        7bit will fail upon encountering a non-ASCII message.  quoted-printable
        can be useful when the repository contains files that contain carriage
        returns, but makes the raw patch email file (as saved from a MUA) much
        harder to inspect manually.  base64 is even more fool proof, but also
-       even more opaque.  Default is the value of the `sendemail.transferEncoding`
-       configuration value; if that is unspecified, git will use 8bit and not
-       add a Content-Transfer-Encoding header.
+       even more opaque.  auto will use 8bit when possible, and quoted-printable
+       otherwise.
++
+Default is the value of the `sendemail.transferEncoding` configuration
+value; if that is unspecified, default to `auto`.
 
 --xmailer::
 --no-xmailer::
@@ -398,8 +400,11 @@ have been specified, in which case default to 'compose'.
 +
 --
                *       Invoke the sendemail-validate hook if present (see linkgit:githooks[5]).
-               *       Warn of patches that contain lines longer than 998 characters; this
-                       is due to SMTP limits as described by http://www.ietf.org/rfc/rfc2821.txt.
+               *       Warn of patches that contain lines longer than
+                       998 characters unless a suitable transfer encoding
+                       ('auto', 'base64', or 'quoted-printable') is used;
+                       this is due to SMTP limits as described by
+                       http://www.ietf.org/rfc/rfc5322.txt.
 --
 +
 Default is the value of `sendemail.validate`; if this is not set,
index a8a9509..424e4ba 100644 (file)
@@ -14,13 +14,27 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Read the idx file for a Git packfile created with
-'git pack-objects' command from the standard input, and
-dump its contents.
+Read the `.idx` file for a Git packfile (created with
+linkgit:git-pack-objects[1] or linkgit:git-index-pack[1]) from the
+standard input, and dump its contents. The output consists of one object
+per line, with each line containing two or three space-separated
+columns:
 
-The information it outputs is subset of what you can get from
-'git verify-pack -v'; this command only shows the packfile
-offset and SHA-1 of each object.
+  - the first column is the offset in bytes of the object within the
+    corresponding packfile
+
+  - the second column is the object id of the object
+
+  - if the index version is 2 or higher, the third column contains the
+    CRC32 of the object data
+
+The objects are output in the order in which they are found in the index
+file, which should be (in a correctly constructed file) sorted by object
+id.
+
+Note that you can get more information on a packfile by calling
+linkgit:git-verify-pack[1]. However, as this command considers only the
+index file itself, it's both faster and more flexible.
 
 GIT
 ---
index c4467ff..d9f422d 100644 (file)
@@ -106,7 +106,7 @@ It is optional: it defaults to 'traditional'.
 The possible options are:
 +
        - 'traditional' - Shows ignored files and directories, unless
-                         --untracked-files=all is specifed, in which case
+                         --untracked-files=all is specified, in which case
                          individual files in ignored directories are
                          displayed.
        - 'no'          - Show no ignored files.
index ef9d9d2..ba3c4df 100644 (file)
@@ -183,12 +183,17 @@ information too.
 
 foreach [--recursive] <command>::
        Evaluates an arbitrary shell command in each checked out submodule.
-       The command has access to the variables $name, $path, $sha1 and
-       $toplevel:
+       The command has access to the variables $name, $sm_path, $displaypath,
+       $sha1 and $toplevel:
        $name is the name of the relevant submodule section in `.gitmodules`,
-       $path is the name of the submodule directory relative to the
-       superproject, $sha1 is the commit as recorded in the superproject,
-       and $toplevel is the absolute path to the top-level of the superproject.
+       $sm_path is the path of the submodule as recorded in the immediate
+       superproject, $displaypath contains the relative path from the
+       current working directory to the submodules root directory,
+       $sha1 is the commit as recorded in the immediate
+       superproject, and $toplevel is the absolute path to the top-level
+       of the immediate superproject.
+       Note that to avoid conflicts with '$PATH' on Windows, the '$path'
+       variable is now a deprecated synonym of '$sm_path' variable.
        Any submodules defined in the superproject but not checked out are
        ignored by this command. Unless given `--quiet`, foreach prints the name
        of each submodule before evaluating the command.
index 7ea24fc..b990295 100644 (file)
@@ -452,7 +452,7 @@ Any other arguments are passed directly to 'git log'
 
 'commit-diff'::
        Commits the diff of two tree-ish arguments from the
-       command-line.  This command does not rely on being inside an `git svn
+       command-line.  This command does not rely on being inside a `git svn
        init`-ed repository.  This command takes three arguments, (a) the
        original tree to diff against, (b) the new tree result, (c) the
        URL of the target Subversion repository.  The final argument
index 10c8ff9..9f2528f 100644 (file)
@@ -244,7 +244,7 @@ commands in addition to the ones needed by participants.
 
 This section can also be used by those who respond to `git
 request-pull` or pull-request on GitHub (www.github.com) to
-integrate the work of others into their history. An sub-area
+integrate the work of others into their history. A sub-area
 lieutenant for a repository will act both as a participant and
 as an integrator.
 
index ff5d7f9..d107daa 100644 (file)
@@ -7,7 +7,7 @@ gitignore - Specifies intentionally untracked files to ignore
 
 SYNOPSIS
 --------
-$HOME/.config/git/ignore, $GIT_DIR/info/exclude, .gitignore
+$XDG_CONFIG_HOME/git/ignore, $GIT_DIR/info/exclude, .gitignore
 
 DESCRIPTION
 -----------
index 3b9faab..504c5f1 100644 (file)
@@ -194,7 +194,7 @@ In the above config only the submodule 'bar' and 'baz' are active,
 
 Note that (c) is a historical artefact and will be ignored if the
 (a) and (b) specify that the submodule is not active. In other words,
-if we have an `submodule.<name>.active` set to `false` or if the
+if we have a `submodule.<name>.active` set to `false` or if the
 submodule's path is excluded in the pathspec in `submodule.active`, the
 url doesn't matter whether it is present or not. This is illustrated in
 the example that follows.
index 6c2d23d..0d2aa48 100644 (file)
@@ -334,7 +334,7 @@ The optional colon that terminates the "magic signature" can be
 omitted if the pattern begins with a character that does not belong to
 "magic signature" symbol set and is not a colon.
 +
-In the long form, the leading colon `:` is followed by a open
+In the long form, the leading colon `:` is followed by an open
 parenthesis `(`, a comma-separated list of zero or more "magic words",
 and a close parentheses `)`, and the remainder is the pattern to match
 against the path.
index 7d1bd44..72daa20 100644 (file)
@@ -184,7 +184,8 @@ existing tag object.
   A colon, followed by a slash, followed by a text, names
   a commit whose commit message matches the specified regular expression.
   This name returns the youngest matching commit which is
-  reachable from any ref. The regular expression can match any part of the
+  reachable from any ref, including HEAD.
+  The regular expression can match any part of the
   commit message. To match messages starting with a string, one can use
   e.g. ':/^foo'. The special sequence ':/!' is reserved for modifiers to what
   is matched. ':/!-foo' performs a negative match, while ':/!!foo' matches a
index 4f44ca2..5abb8e8 100644 (file)
@@ -54,7 +54,7 @@ The notable options are:
        this case, the contents are returned as individual entries.
 +
 If this is set, files and directories that explicitly match an ignore
-pattern are reported. Implicity ignored directories (directories that
+pattern are reported. Implicitly ignored directories (directories that
 do not match an ignore pattern, but whose contents are all ignored)
 are not reported, instead all of the contents are reported.
 
index e7cbb7c..45f0df6 100644 (file)
@@ -146,7 +146,7 @@ To get the values of all attributes associated with a file:
 
 * Iterate over the `attr_check.items[]` array to examine
   the attribute names and values.  The name of the attribute
-  described by a  `attr_check.items[]` object can be retrieved via
+  described by an `attr_check.items[]` object can be retrieved via
   `git_attr_name(check->items[i].attr)`.  (Please note that no items
   will be returned for unset attributes, so `ATTR_UNSET()` will return
   false for all returned `attr_check.items[]` objects.)
index ad6af81..cc0474b 100644 (file)
@@ -18,9 +18,9 @@ metadata, including:
   the graph file.
 
 These positional references are stored as unsigned 32-bit integers
-corresponding to the array position withing the list of commit OIDs. We
-use the most-significant bit for special purposes, so we can store at most
-(1 << 31) - 1 (around 2 billion) commits.
+corresponding to the array position within the list of commit OIDs. Due
+to some special constants we use to track parents, we can store at most
+(1 << 30) + (1 << 29) + (1 << 28) - 1 (around 1.8 billion) commits.
 
 == Commit graph files have the following format:
 
@@ -70,10 +70,10 @@ CHUNK DATA:
   OID Lookup (ID: {'O', 'I', 'D', 'L'}) (N * H bytes)
       The OIDs for all commits in the graph, sorted in ascending order.
 
-  Commit Data (ID: {'C', 'G', 'E', 'T' }) (N * (H + 16) bytes)
+  Commit Data (ID: {'C', 'D', 'A', 'T' }) (N * (H + 16) bytes)
     * The first H bytes are for the OID of the root tree.
     * The next 8 bytes are for the positions of the first two parents
-      of the ith commit. Stores value 0xffffffff if no parent in that
+      of the ith commit. Stores value 0x7000000 if no parent in that
       position. If there are more than two parents, the second value
       has its most-significant bit on and the other bits store an array
       position into the Large Edge List chunk.
index 0550c6d..e1a883e 100644 (file)
@@ -77,6 +77,29 @@ in the commit graph. We can treat these commits as having "infinite"
 generation number and walk until reaching commits with known generation
 number.
 
+We use the macro GENERATION_NUMBER_INFINITY = 0xFFFFFFFF to mark commits not
+in the commit-graph file. If a commit-graph file was written by a version
+of Git that did not compute generation numbers, then those commits will
+have generation number represented by the macro GENERATION_NUMBER_ZERO = 0.
+
+Since the commit-graph file is closed under reachability, we can guarantee
+the following weaker condition on all commits:
+
+    If A and B are commits with generation numbers N amd M, respectively,
+    and N < M, then A cannot reach B.
+
+Note how the strict inequality differs from the inequality when we have
+fully-computed generation numbers. Using strict inequality may result in
+walking a few extra commits, but the simplicity in dealing with commits
+with generation number *_INFINITY or *_ZERO is valuable.
+
+We use the macro GENERATION_NUMBER_MAX = 0x3FFFFFFF to for commits whose
+generation numbers are computed to be at least this value. We limit at
+this value since it is the largest value that can be stored in the
+commit-graph file using the 30 bits available to generation numbers. This
+presents another case where a commit can have generation number equal to
+that of a parent.
+
 Design Details
 --------------
 
@@ -98,18 +121,14 @@ Future Work
 - The 'commit-graph' subcommand does not have a "verify" mode that is
   necessary for integration with fsck.
 
-- The file format includes room for precomputed generation numbers. These
-  are not currently computed, so all generation numbers will be marked as
-  0 (or "uncomputed"). A later patch will include this calculation.
-
 - After computing and storing generation numbers, we must make graph
   walks aware of generation numbers to gain the performance benefits they
   enable. This will mostly be accomplished by swapping a commit-date-ordered
   priority queue with one ordered by generation number. The following
   operations are important candidates:
 
-    - paint_down_to_common()
     - 'log --topo-order'
+    - 'tag --merged'
 
 - Currently, parse_commit_gently() requires filling in the root tree
   object for a commit. This passes through lookup_tree() and consequently
diff --git a/Documentation/technical/directory-rename-detection.txt b/Documentation/technical/directory-rename-detection.txt
new file mode 100644 (file)
index 0000000..1c0086e
--- /dev/null
@@ -0,0 +1,115 @@
+Directory rename detection
+==========================
+
+Rename detection logic in diffcore-rename that checks for renames of
+individual files is aggregated and analyzed in merge-recursive for cases
+where combinations of renames indicate that a full directory has been
+renamed.
+
+Scope of abilities
+------------------
+
+It is perhaps easiest to start with an example:
+
+  * When all of x/a, x/b and x/c have moved to z/a, z/b and z/c, it is
+    likely that x/d added in the meantime would also want to move to z/d by
+    taking the hint that the entire directory 'x' moved to 'z'.
+
+More interesting possibilities exist, though, such as:
+
+  * one side of history renames x -> z, and the other renames some file to
+    x/e, causing the need for the merge to do a transitive rename.
+
+  * one side of history renames x -> z, but also renames all files within
+    x.  For example, x/a -> z/alpha, x/b -> z/bravo, etc.
+
+  * both 'x' and 'y' being merged into a single directory 'z', with a
+    directory rename being detected for both x->z and y->z.
+
+  * not all files in a directory being renamed to the same location;
+    i.e. perhaps most the files in 'x' are now found under 'z', but a few
+    are found under 'w'.
+
+  * a directory being renamed, which also contained a subdirectory that was
+    renamed to some entirely different location.  (And perhaps the inner
+    directory itself contained inner directories that were renamed to yet
+    other locations).
+
+  * combinations of the above; see t/t6043-merge-rename-directories.sh for
+    various interesting cases.
+
+Limitations -- applicability of directory renames
+-------------------------------------------------
+
+In order to prevent edge and corner cases resulting in either conflicts
+that cannot be represented in the index or which might be too complex for
+users to try to understand and resolve, a couple basic rules limit when
+directory rename detection applies:
+
+  1) If a given directory still exists on both sides of a merge, we do
+     not consider it to have been renamed.
+
+  2) If a subset of to-be-renamed files have a file or directory in the
+     way (or would be in the way of each other), "turn off" the directory
+     rename for those specific sub-paths and report the conflict to the
+     user.
+
+  3) If the other side of history did a directory rename to a path that
+     your side of history renamed away, then ignore that particular
+     rename from the other side of history for any implicit directory
+     renames (but warn the user).
+
+Limitations -- detailed rules and testcases
+-------------------------------------------
+
+t/t6043-merge-rename-directories.sh contains extensive tests and commentary
+which generate and explore the rules listed above.  It also lists a few
+additional rules:
+
+  a) If renames split a directory into two or more others, the directory
+     with the most renames, "wins".
+
+  b) Avoid directory-rename-detection for a path, if that path is the
+     source of a rename on either side of a merge.
+
+  c) Only apply implicit directory renames to directories if the other side
+     of history is the one doing the renaming.
+
+Limitations -- support in different commands
+--------------------------------------------
+
+Directory rename detection is supported by 'merge' and 'cherry-pick'.
+Other git commands which users might be surprised to see limited or no
+directory rename detection support in:
+
+  * diff
+
+    Folks have requested in the past that `git diff` detect directory
+    renames and somehow simplify its output.  It is not clear whether this
+    would be desirable or how the output should be simplified, so this was
+    simply not implemented.  Further, to implement this, directory rename
+    detection logic would need to move from merge-recursive to
+    diffcore-rename.
+
+  * am
+
+    git-am tries to avoid a full three way merge, instead calling
+    git-apply.  That prevents us from detecting renames at all, which may
+    defeat the directory rename detection.  There is a fallback, though; if
+    the initial git-apply fails and the user has specified the -3 option,
+    git-am will fall back to a three way merge.  However, git-am lacks the
+    necessary information to do a "real" three way merge.  Instead, it has
+    to use build_fake_ancestor() to get a merge base that is missing files
+    whose rename may have been important to detect for directory rename
+    detection to function.
+
+  * rebase
+
+    Since am-based rebases work by first generating a bunch of patches
+    (which no longer record what the original commits were and thus don't
+    have the necessary info from which we can find a real merge-base), and
+    then calling git-am, this implies that am-based rebases will not always
+    successfully detect directory renames either (see the 'am' section
+    above).  merged-based rebases (rebase -m) and cherry-pick-based rebases
+    (rebase -i) are not affected by this shortcoming, and fully support
+    directory rename detection.
index 7fee6b7..508a344 100644 (file)
@@ -284,7 +284,9 @@ information is sent back to the client in the next step.
 The client can optionally request that pack-objects omit various
 objects from the packfile using one of several filtering techniques.
 These are intended for use with partial clone and partial fetch
-operations.  See `rev-list` for possible "filter-spec" values.
+operations. An object that does not meet a filter-spec value is
+omitted unless explicitly requested in a 'want' line. See `rev-list`
+for possible filter-spec values.
 
 Once all the 'want's and 'shallow's (and optional 'deepen') are
 transferred, clients MUST send a flush-pkt, to tell the server side
index 49bda76..09e4e02 100644 (file)
@@ -64,9 +64,8 @@ When using the http:// or https:// transport a client makes a "smart"
 info/refs request as described in `http-protocol.txt` and requests that
 v2 be used by supplying "version=2" in the `Git-Protocol` header.
 
-   C: Git-Protocol: version=2
-   C:
    C: GET $GIT_URL/info/refs?service=git-upload-pack HTTP/1.0
+   C: Git-Protocol: version=2
 
 A v2 server would reply:
 
@@ -299,12 +298,21 @@ included in the client's request:
        for use with partial clone and partial fetch operations. See
        `rev-list` for possible "filter-spec" values.
 
+If the 'ref-in-want' feature is advertised, the following argument can
+be included in the client's request as well as the potential addition of
+the 'wanted-refs' section in the server's response as explained below.
+
+    want-ref <ref>
+       Indicates to the server that the client wants to retrieve a
+       particular ref, where <ref> is the full name of a ref on the
+       server.
+
 The response of `fetch` is broken into a number of sections separated by
 delimiter packets (0001), with each section beginning with its section
 header.
 
     output = *section
-    section = (acknowledgments | shallow-info | packfile)
+    section = (acknowledgments | shallow-info | wanted-refs | packfile)
              (flush-pkt | delim-pkt)
 
     acknowledgments = PKT-LINE("acknowledgments" LF)
@@ -319,6 +327,10 @@ header.
     shallow = "shallow" SP obj-id
     unshallow = "unshallow" SP obj-id
 
+    wanted-refs = PKT-LINE("wanted-refs" LF)
+                 *PKT-LINE(wanted-ref LF)
+    wanted-ref = obj-id SP refname
+
     packfile = PKT-LINE("packfile" LF)
               *PKT-LINE(%x01-03 *%x00-ff)
 
@@ -379,6 +391,19 @@ header.
        * This section is only included if a packfile section is also
          included in the response.
 
+    wanted-refs section
+       * This section is only included if the client has requested a
+         ref using a 'want-ref' line and if a packfile section is also
+         included in the response.
+
+       * Always begins with the section header "wanted-refs".
+
+       * The server will send a ref listing ("<oid> <refname>") for
+         each reference requested using 'want-ref' lines.
+
+       * The server MUST NOT send any refs which were not requested
+         using 'want-ref' lines.
+
     packfile section
        * This section is only included if the client has sent 'want'
          lines in its request and either requested that no more
index ed9d9e4..920678a 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.18.0
+DEF_VER=v2.18.GIT
 
 LF='
 '
index e4b503d..08e5c54 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -620,6 +620,7 @@ SCRIPT_LIB += git-mergetool--lib
 SCRIPT_LIB += git-parse-remote
 SCRIPT_LIB += git-rebase--am
 SCRIPT_LIB += git-rebase--interactive
+SCRIPT_LIB += git-rebase--preserve-merges
 SCRIPT_LIB += git-rebase--merge
 SCRIPT_LIB += git-sh-setup
 SCRIPT_LIB += git-sh-i18n
@@ -689,7 +690,6 @@ PROGRAM_OBJS += http-backend.o
 PROGRAM_OBJS += imap-send.o
 PROGRAM_OBJS += sh-i18n--envsubst.o
 PROGRAM_OBJS += shell.o
-PROGRAM_OBJS += show-index.o
 PROGRAM_OBJS += remote-testsvn.o
 
 # Binary suffix, set to .exe for Windows builds
@@ -1077,6 +1077,7 @@ BUILTIN_OBJS += builtin/send-pack.o
 BUILTIN_OBJS += builtin/serve.o
 BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
+BUILTIN_OBJS += builtin/show-index.o
 BUILTIN_OBJS += builtin/show-ref.o
 BUILTIN_OBJS += builtin/stripspace.o
 BUILTIN_OBJS += builtin/submodule--helper.o
@@ -2020,8 +2021,9 @@ version.sp version.s version.o: GIT-VERSION-FILE GIT-USER-AGENT
 version.sp version.s version.o: EXTRA_CPPFLAGS = \
        '-DGIT_VERSION="$(GIT_VERSION)"' \
        '-DGIT_USER_AGENT=$(GIT_USER_AGENT_CQ_SQ)' \
-       '-DGIT_BUILT_FROM_COMMIT="$(shell GIT_CEILING_DIRECTORIES=\"$(CURDIR)/..\" \
-               git rev-parse -q --verify HEAD || :)"'
+       '-DGIT_BUILT_FROM_COMMIT="$(shell \
+               GIT_CEILING_DIRECTORIES="$(CURDIR)/.." \
+               git rev-parse -q --verify HEAD 2>/dev/null)"'
 
 $(BUILT_INS): git$X
        $(QUIET_BUILT_IN)$(RM) $@ && \
@@ -2109,7 +2111,7 @@ $(SCRIPT_PERL_GEN): % : %.perl GIT-PERL-DEFINES GIT-PERL-HEADER GIT-VERSION-FILE
        $(QUIET_GEN)$(RM) $@ $@+ && \
        sed -e '1{' \
            -e '        s|#!.*perl|#!$(PERL_PATH_SQ)|' \
-           -e '        rGIT-PERL-HEADER' \
+           -e '        r GIT-PERL-HEADER' \
            -e '        G' \
            -e '}' \
            -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
@@ -2397,6 +2399,7 @@ LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
 LOCALIZED_SH = $(SCRIPT_SH)
 LOCALIZED_SH += git-parse-remote.sh
 LOCALIZED_SH += git-rebase--interactive.sh
+LOCALIZED_SH += git-rebase--preserve-merges.sh
 LOCALIZED_SH += git-sh-setup.sh
 LOCALIZED_PERL = $(SCRIPT_PERL)
 
index f6c58b3..5d139ba 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.18.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.19.0.txt
\ No newline at end of file
index 370a56d..52aa85b 100644 (file)
--- a/advice.c
+++ b/advice.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "config.h"
 #include "color.h"
+#include "help.h"
 
 int advice_push_update_rejected = 1;
 int advice_push_non_ff_current = 1;
@@ -16,6 +17,7 @@ int advice_implicit_identity = 1;
 int advice_detached_head = 1;
 int advice_set_upstream_failure = 1;
 int advice_object_name_warning = 1;
+int advice_amworkdir = 1;
 int advice_rm_hints = 1;
 int advice_add_embedded_repo = 1;
 int advice_ignored_hook = 1;
@@ -53,28 +55,29 @@ static struct {
        const char *name;
        int *preference;
 } advice_config[] = {
-       { "pushupdaterejected", &advice_push_update_rejected },
-       { "pushnonffcurrent", &advice_push_non_ff_current },
-       { "pushnonffmatching", &advice_push_non_ff_matching },
-       { "pushalreadyexists", &advice_push_already_exists },
-       { "pushfetchfirst", &advice_push_fetch_first },
-       { "pushneedsforce", &advice_push_needs_force },
-       { "statushints", &advice_status_hints },
-       { "statusuoption", &advice_status_u_option },
-       { "commitbeforemerge", &advice_commit_before_merge },
-       { "resolveconflict", &advice_resolve_conflict },
-       { "implicitidentity", &advice_implicit_identity },
-       { "detachedhead", &advice_detached_head },
-       { "setupstreamfailure", &advice_set_upstream_failure },
-       { "objectnamewarning", &advice_object_name_warning },
-       { "rmhints", &advice_rm_hints },
-       { "addembeddedrepo", &advice_add_embedded_repo },
-       { "ignoredhook", &advice_ignored_hook },
-       { "waitingforeditor", &advice_waiting_for_editor },
-       { "graftfiledeprecated", &advice_graft_file_deprecated },
+       { "pushUpdateRejected", &advice_push_update_rejected },
+       { "pushNonFFCurrent", &advice_push_non_ff_current },
+       { "pushNonFFMatching", &advice_push_non_ff_matching },
+       { "pushAlreadyExists", &advice_push_already_exists },
+       { "pushFetchFirst", &advice_push_fetch_first },
+       { "pushNeedsForce", &advice_push_needs_force },
+       { "statusHints", &advice_status_hints },
+       { "statusUoption", &advice_status_u_option },
+       { "commitBeforeMerge", &advice_commit_before_merge },
+       { "resolveConflict", &advice_resolve_conflict },
+       { "implicitIdentity", &advice_implicit_identity },
+       { "detachedHead", &advice_detached_head },
+       { "setupStreamFailure", &advice_set_upstream_failure },
+       { "objectNameWarning", &advice_object_name_warning },
+       { "amWorkDir", &advice_amworkdir },
+       { "rmHints", &advice_rm_hints },
+       { "addEmbeddedRepo", &advice_add_embedded_repo },
+       { "ignoredHook", &advice_ignored_hook },
+       { "waitingForEditor", &advice_waiting_for_editor },
+       { "graftFileDeprecated", &advice_graft_file_deprecated },
 
        /* make this an alias for backward compatibility */
-       { "pushnonfastforward", &advice_push_update_rejected }
+       { "pushNonFastForward", &advice_push_update_rejected }
 };
 
 void advise(const char *advice, ...)
@@ -122,7 +125,7 @@ int git_default_advice_config(const char *var, const char *value)
                return 0;
 
        for (i = 0; i < ARRAY_SIZE(advice_config); i++) {
-               if (strcmp(k, advice_config[i].name))
+               if (strcasecmp(k, advice_config[i].name))
                        continue;
                *advice_config[i].preference = git_config_bool(var, value);
                return 0;
@@ -131,6 +134,14 @@ int git_default_advice_config(const char *var, const char *value)
        return 0;
 }
 
+void list_config_advices(struct string_list *list, const char *prefix)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(advice_config); i++)
+               list_config_item(list, prefix, advice_config[i].name);
+}
+
 int error_resolve_conflict(const char *me)
 {
        if (!strcmp(me, "cherry-pick"))
index 9f5064e..7e93778 100644 (file)
--- a/advice.h
+++ b/advice.h
@@ -17,6 +17,7 @@ extern int advice_implicit_identity;
 extern int advice_detached_head;
 extern int advice_set_upstream_failure;
 extern int advice_object_name_warning;
+extern int advice_amworkdir;
 extern int advice_rm_hints;
 extern int advice_add_embedded_repo;
 extern int advice_ignored_hook;
diff --git a/alloc.c b/alloc.c
index cf4f8b6..c2fc5d6 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -4,8 +4,7 @@
  * Copyright (C) 2006 Linus Torvalds
  *
  * The standard malloc/free wastes too much space for objects, partly because
- * it maintains all the allocation infrastructure (which isn't needed, since
- * we never free an object descriptor anyway), but even more because it ends
+ * it maintains all the allocation infrastructure, but even more because it ends
  * up with maximal alignment because it doesn't know what the object alignment
  * for the new allocation is.
  */
@@ -15,6 +14,7 @@
 #include "tree.h"
 #include "commit.h"
 #include "tag.h"
+#include "alloc.h"
 
 #define BLOCKING 1024
 
@@ -30,8 +30,27 @@ struct alloc_state {
        int count; /* total number of nodes allocated */
        int nr;    /* number of nodes left in current allocation */
        void *p;   /* first free node in current allocation */
+
+       /* bookkeeping of allocations */
+       void **slabs;
+       int slab_nr, slab_alloc;
 };
 
+void *allocate_alloc_state(void)
+{
+       return xcalloc(1, sizeof(struct alloc_state));
+}
+
+void clear_alloc_state(struct alloc_state *s)
+{
+       while (s->slab_nr > 0) {
+               s->slab_nr--;
+               free(s->slabs[s->slab_nr]);
+       }
+
+       FREE_AND_NULL(s->slabs);
+}
+
 static inline void *alloc_node(struct alloc_state *s, size_t node_size)
 {
        void *ret;
@@ -39,61 +58,59 @@ static inline void *alloc_node(struct alloc_state *s, size_t node_size)
        if (!s->nr) {
                s->nr = BLOCKING;
                s->p = xmalloc(BLOCKING * node_size);
+
+               ALLOC_GROW(s->slabs, s->slab_nr + 1, s->slab_alloc);
+               s->slabs[s->slab_nr++] = s->p;
        }
        s->nr--;
        s->count++;
        ret = s->p;
        s->p = (char *)s->p + node_size;
        memset(ret, 0, node_size);
+
        return ret;
 }
 
-static struct alloc_state blob_state;
-void *alloc_blob_node(void)
+void *alloc_blob_node(struct repository *r)
 {
-       struct blob *b = alloc_node(&blob_state, sizeof(struct blob));
+       struct blob *b = alloc_node(r->parsed_objects->blob_state, sizeof(struct blob));
        b->object.type = OBJ_BLOB;
        return b;
 }
 
-static struct alloc_state tree_state;
-void *alloc_tree_node(void)
+void *alloc_tree_node(struct repository *r)
 {
-       struct tree *t = alloc_node(&tree_state, sizeof(struct tree));
+       struct tree *t = alloc_node(r->parsed_objects->tree_state, sizeof(struct tree));
        t->object.type = OBJ_TREE;
        return t;
 }
 
-static struct alloc_state tag_state;
-void *alloc_tag_node(void)
+void *alloc_tag_node(struct repository *r)
 {
-       struct tag *t = alloc_node(&tag_state, sizeof(struct tag));
+       struct tag *t = alloc_node(r->parsed_objects->tag_state, sizeof(struct tag));
        t->object.type = OBJ_TAG;
        return t;
 }
 
-static struct alloc_state object_state;
-void *alloc_object_node(void)
+void *alloc_object_node(struct repository *r)
 {
-       struct object *obj = alloc_node(&object_state, sizeof(union any_object));
+       struct object *obj = alloc_node(r->parsed_objects->object_state, sizeof(union any_object));
        obj->type = OBJ_NONE;
        return obj;
 }
 
-static struct alloc_state commit_state;
-
-unsigned int alloc_commit_index(void)
+unsigned int alloc_commit_index(struct repository *r)
 {
-       static unsigned int count;
-       return count++;
+       return r->parsed_objects->commit_count++;
 }
 
-void *alloc_commit_node(void)
+void *alloc_commit_node(struct repository *r)
 {
-       struct commit *c = alloc_node(&commit_state, sizeof(struct commit));
+       struct commit *c = alloc_node(r->parsed_objects->commit_state, sizeof(struct commit));
        c->object.type = OBJ_COMMIT;
-       c->index = alloc_commit_index();
+       c->index = alloc_commit_index(r);
        c->graph_pos = COMMIT_NOT_FROM_GRAPH;
+       c->generation = GENERATION_NUMBER_INFINITY;
        return c;
 }
 
@@ -104,9 +121,10 @@ static void report(const char *name, unsigned int count, size_t size)
 }
 
 #define REPORT(name, type)     \
-    report(#name, name##_state.count, name##_state.count * sizeof(type) >> 10)
+    report(#name, r->parsed_objects->name##_state->count, \
+                 r->parsed_objects->name##_state->count * sizeof(type) >> 10)
 
-void alloc_report(void)
+void alloc_report(struct repository *r)
 {
        REPORT(blob, struct blob);
        REPORT(tree, struct tree);
diff --git a/alloc.h b/alloc.h
new file mode 100644 (file)
index 0000000..3e4e828
--- /dev/null
+++ b/alloc.h
@@ -0,0 +1,19 @@
+#ifndef ALLOC_H
+#define ALLOC_H
+
+struct tree;
+struct commit;
+struct tag;
+
+void *alloc_blob_node(struct repository *r);
+void *alloc_tree_node(struct repository *r);
+void *alloc_commit_node(struct repository *r);
+void *alloc_tag_node(struct repository *r);
+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);
+void clear_alloc_state(struct alloc_state *s);
+
+#endif
diff --git a/apply.c b/apply.c
index d79e615..49752cd 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -9,6 +9,7 @@
 
 #include "cache.h"
 #include "config.h"
+#include "object-store.h"
 #include "blob.h"
 #include "delta.h"
 #include "diff.h"
@@ -141,6 +142,8 @@ int check_apply_state(struct apply_state *state, int force_apply)
                        return error(_("--cached outside a repository"));
                state->check_index = 1;
        }
+       if (state->ita_only && (state->check_index || is_not_gitdir))
+               state->ita_only = 0;
        if (state->check_index)
                state->unsafe_paths = 0;
 
@@ -4053,7 +4056,7 @@ static int preimage_oid_in_gitlink_patch(struct patch *p, struct object_id *oid)
        return get_oid_hex(p->old_sha1_prefix, oid);
 }
 
-/* Build an index that contains the just the files needed for a 3way merge */
+/* Build an index that contains just the files needed for a 3way merge */
 static int build_fake_ancestor(struct apply_state *state, struct patch *list)
 {
        struct patch *patch;
@@ -4242,7 +4245,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) {
+       if (state->update_index && !state->ita_only) {
                if (remove_file_from_cache(patch->old_name) < 0)
                        return error(_("unable to remove %s from index"), patch->old_name);
        }
@@ -4265,15 +4268,15 @@ static int add_index_file(struct apply_state *state,
        int namelen = strlen(path);
        unsigned ce_size = cache_entry_size(namelen);
 
-       if (!state->update_index)
-               return 0;
-
        ce = xcalloc(1, ce_size);
        memcpy(ce->name, path, namelen);
        ce->ce_mode = create_ce_mode(mode);
        ce->ce_flags = create_ce_flags(0);
        ce->ce_namelen = namelen;
-       if (S_ISGITLINK(mode)) {
+       if (state->ita_only) {
+               ce->ce_flags |= CE_INTENT_TO_ADD;
+               set_object_name_for_intent_to_add_entry(ce);
+       } else if (S_ISGITLINK(mode)) {
                const char *s;
 
                if (!skip_prefix(buf, "Subproject commit ", &s) ||
@@ -4465,8 +4468,9 @@ static int create_file(struct apply_state *state, struct patch *patch)
 
        if (patch->conflicted_threeway)
                return add_conflicted_stages_file(state, patch);
-       else
+       else if (state->update_index)
                return add_index_file(state, path, mode, buf, size);
+       return 0;
 }
 
 /* phase zero is to remove, phase one is to create */
@@ -4686,7 +4690,7 @@ static int apply_patch(struct apply_state *state,
        if (state->whitespace_error && (state->ws_error_action == die_on_ws_error))
                state->apply = 0;
 
-       state->update_index = state->check_index && state->apply;
+       state->update_index = (state->check_index || state->ita_only) && state->apply;
        if (state->update_index && !is_lock_file_locked(&state->lock_file)) {
                if (state->index_file)
                        hold_lock_file_for_update(&state->lock_file,
@@ -4941,6 +4945,8 @@ int apply_parse_options(int argc, const char **argv,
                        N_("instead of applying the patch, see if the patch is applicable")),
                OPT_BOOL(0, "index", &state->check_index,
                        N_("make sure the patch is applicable to the current index")),
+               OPT_BOOL('N', "intent-to-add", &state->ita_only,
+                       N_("mark new files with `git add --intent-to-add`")),
                OPT_BOOL(0, "cached", &state->cached,
                        N_("apply a patch without touching the working tree")),
                OPT_BOOL_F(0, "unsafe-paths", &state->unsafe_paths,
diff --git a/apply.h b/apply.h
index dc4a019..b80d8ba 100644 (file)
--- a/apply.h
+++ b/apply.h
@@ -45,6 +45,7 @@ struct apply_state {
        int check; /* preimage must match working tree, don't actually apply */
        int check_index; /* preimage must match the indexed version */
        int update_index; /* check_index && apply */
+       int ita_only;     /* add intent-to-add entries to the index */
 
        /* These control cosmetic aspect of the output */
        int diffstat; /* just show a diffstat, and don't actually apply */
index b6f58dd..7df8565 100644 (file)
@@ -5,6 +5,7 @@
 #include "config.h"
 #include "tar.h"
 #include "archive.h"
+#include "object-store.h"
 #include "streaming.h"
 #include "run-command.h"
 
index 74f3fe9..abc556e 100644 (file)
@@ -6,6 +6,7 @@
 #include "archive.h"
 #include "streaming.h"
 #include "utf8.h"
+#include "object-store.h"
 #include "userdiff.h"
 #include "xdiff-interface.h"
 
index 4fe7bec..875dab6 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "config.h"
 #include "refs.h"
+#include "object-store.h"
 #include "commit.h"
 #include "tree-walk.h"
 #include "attr.h"
index a579b50..6de1abd 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -12,6 +12,7 @@
 #include "bisect.h"
 #include "sha1-array.h"
 #include "argv-array.h"
+#include "commit-slab.h"
 
 static struct oid_array good_revs;
 static struct oid_array skipped_revs;
@@ -70,16 +71,19 @@ static void clear_distance(struct commit_list *list)
        }
 }
 
+define_commit_slab(commit_weight, int *);
+static struct commit_weight commit_weight;
+
 #define DEBUG_BISECT 0
 
 static inline int weight(struct commit_list *elem)
 {
-       return *((int*)(elem->item->util));
+       return **commit_weight_at(&commit_weight, elem->item);
 }
 
 static inline void weight_set(struct commit_list *elem, int weight)
 {
-       *((int*)(elem->item->util)) = weight;
+       **commit_weight_at(&commit_weight, elem->item) = weight;
 }
 
 static int count_interesting_parents(struct commit *commit)
@@ -265,7 +269,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
                struct commit *commit = p->item;
                unsigned flags = commit->object.flags;
 
-               p->item->util = &weights[n++];
+               *commit_weight_at(&commit_weight, p->item) = &weights[n++];
                switch (count_interesting_parents(commit)) {
                case 0:
                        if (!(flags & TREESAME)) {
@@ -372,6 +376,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
        int *weights;
 
        show_list("bisection 2 entry", 0, 0, *commit_list);
+       init_commit_weight(&commit_weight);
 
        /*
         * Count the number of total and tree-changing items on the
@@ -412,6 +417,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
        }
        free(weights);
        *commit_list = best;
+       clear_commit_weight(&commit_weight);
 }
 
 static int register_ref(const char *refname, const struct object_id *oid,
diff --git a/blame.c b/blame.c
index 14d0e0b..0c4490a 100644 (file)
--- a/blame.c
+++ b/blame.c
@@ -1,11 +1,31 @@
 #include "cache.h"
 #include "refs.h"
+#include "object-store.h"
 #include "cache-tree.h"
 #include "mergesort.h"
 #include "diff.h"
 #include "diffcore.h"
 #include "tag.h"
 #include "blame.h"
+#include "alloc.h"
+#include "commit-slab.h"
+
+define_commit_slab(blame_suspects, struct blame_origin *);
+static struct blame_suspects blame_suspects;
+
+struct blame_origin *get_blame_suspects(struct commit *commit)
+{
+       struct blame_origin **result;
+
+       result = blame_suspects_peek(&blame_suspects, commit);
+
+       return result ? *result : NULL;
+}
+
+static void set_blame_suspects(struct commit *commit, struct blame_origin *origin)
+{
+       *blame_suspects_at(&blame_suspects, commit) = origin;
+}
 
 void blame_origin_decref(struct blame_origin *o)
 {
@@ -15,12 +35,12 @@ void blame_origin_decref(struct blame_origin *o)
                        blame_origin_decref(o->previous);
                free(o->file.ptr);
                /* Should be present exactly once in commit chain */
-               for (p = o->commit->util; p; l = p, p = p->next) {
+               for (p = get_blame_suspects(o->commit); p; l = p, p = p->next) {
                        if (p == o) {
                                if (l)
                                        l->next = p->next;
                                else
-                                       o->commit->util = p->next;
+                                       set_blame_suspects(o->commit, p->next);
                                free(o);
                                return;
                        }
@@ -41,8 +61,8 @@ static struct blame_origin *make_origin(struct commit *commit, const char *path)
        FLEX_ALLOC_STR(o, path, path);
        o->commit = commit;
        o->refcnt = 1;
-       o->next = commit->util;
-       commit->util = o;
+       o->next = get_blame_suspects(commit);
+       set_blame_suspects(commit, o);
        return o;
 }
 
@@ -54,13 +74,13 @@ static struct blame_origin *get_origin(struct commit *commit, const char *path)
 {
        struct blame_origin *o, *l;
 
-       for (o = commit->util, l = NULL; o; l = o, o = o->next) {
+       for (o = get_blame_suspects(commit), l = NULL; o; l = o, o = o->next) {
                if (!strcmp(o->path, path)) {
                        /* bump to front */
                        if (l) {
                                l->next = o->next;
-                               o->next = commit->util;
-                               commit->util = o;
+                               o->next = get_blame_suspects(commit);
+                               set_blame_suspects(commit, o);
                        }
                        return blame_origin_incref(o);
                }
@@ -110,17 +130,19 @@ static void append_merge_parents(struct commit_list **tail)
        int merge_head;
        struct strbuf line = STRBUF_INIT;
 
-       merge_head = open(git_path_merge_head(), O_RDONLY);
+       merge_head = open(git_path_merge_head(the_repository), O_RDONLY);
        if (merge_head < 0) {
                if (errno == ENOENT)
                        return;
-               die("cannot open '%s' for reading", git_path_merge_head());
+               die("cannot open '%s' for reading",
+                   git_path_merge_head(the_repository));
        }
 
        while (!strbuf_getwholeline_fd(&line, merge_head, '\n')) {
                struct object_id oid;
                if (line.len < GIT_SHA1_HEXSZ || get_oid_hex(line.buf, &oid))
-                       die("unknown line in '%s': %s", git_path_merge_head(), line.buf);
+                       die("unknown line in '%s': %s",
+                           git_path_merge_head(the_repository), line.buf);
                tail = append_parent(tail, &oid);
        }
        close(merge_head);
@@ -161,7 +183,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
 
        read_cache();
        time(&now);
-       commit = alloc_commit_node();
+       commit = alloc_commit_node(the_repository);
        commit->object.parsed = 1;
        commit->date = now;
        parent_tail = &commit->parents;
@@ -478,7 +500,7 @@ static void queue_blames(struct blame_scoreboard *sb, struct blame_origin *porig
                porigin->suspects = blame_merge(porigin->suspects, sorted);
        else {
                struct blame_origin *o;
-               for (o = porigin->commit->util; o; o = o->next) {
+               for (o = get_blame_suspects(porigin->commit); o; o = o->next) {
                        if (o->suspects) {
                                porigin->suspects = sorted;
                                return;
@@ -525,7 +547,7 @@ static struct blame_origin *find_origin(struct commit *parent,
        const char *paths[2];
 
        /* First check any existing origins */
-       for (porigin = parent->util; porigin; porigin = porigin->next)
+       for (porigin = get_blame_suspects(parent); porigin; porigin = porigin->next)
                if (!strcmp(porigin->path, origin->path)) {
                        /*
                         * The same path between origin and its parent
@@ -1550,7 +1572,7 @@ void assign_blame(struct blame_scoreboard *sb, int opt)
 
        while (commit) {
                struct blame_entry *ent;
-               struct blame_origin *suspect = commit->util;
+               struct blame_origin *suspect = get_blame_suspects(commit);
 
                /* find one suspect to break down */
                while (suspect && !suspect->suspects)
@@ -1752,6 +1774,8 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam
        struct commit *final_commit = NULL;
        enum object_type type;
 
+       init_blame_suspects(&blame_suspects);
+
        if (sb->reverse && sb->contents_from)
                die(_("--contents and --reverse do not blend well."));
 
@@ -1815,7 +1839,7 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam
        }
 
        if (is_null_oid(&sb->final->object.oid)) {
-               o = sb->final->util;
+               o = get_blame_suspects(sb->final);
                sb->final_buf = xmemdupz(o->file.ptr, o->file.size);
                sb->final_buf_size = o->file.size;
        }
diff --git a/blame.h b/blame.h
index a6c915c..2092f95 100644 (file)
--- a/blame.h
+++ b/blame.h
@@ -172,4 +172,6 @@ extern void setup_scoreboard(struct blame_scoreboard *sb, const char *path, stru
 
 extern 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);
+
 #endif /* BLAME_H */
diff --git a/blob.c b/blob.c
index fa2ab4f..458dafa 100644 (file)
--- a/blob.c
+++ b/blob.c
@@ -1,5 +1,7 @@
 #include "cache.h"
 #include "blob.h"
+#include "repository.h"
+#include "alloc.h"
 
 const char *blob_type = "blob";
 
@@ -7,7 +9,8 @@ struct blob *lookup_blob(const struct object_id *oid)
 {
        struct object *obj = lookup_object(oid->hash);
        if (!obj)
-               return create_object(oid->hash, alloc_blob_node());
+               return create_object(the_repository, oid->hash,
+                                    alloc_blob_node(the_repository));
        return object_as_type(obj, OBJ_BLOB, 0);
 }
 
index f967c98..6a35dd3 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -340,13 +340,13 @@ void create_branch(const char *name, const char *start_name,
 
 void remove_branch_state(void)
 {
-       unlink(git_path_cherry_pick_head());
-       unlink(git_path_revert_head());
-       unlink(git_path_merge_head());
-       unlink(git_path_merge_rr());
-       unlink(git_path_merge_msg());
-       unlink(git_path_merge_mode());
-       unlink(git_path_squash_msg());
+       unlink(git_path_cherry_pick_head(the_repository));
+       unlink(git_path_revert_head(the_repository));
+       unlink(git_path_merge_head(the_repository));
+       unlink(git_path_merge_rr(the_repository));
+       unlink(git_path_merge_msg(the_repository));
+       unlink(git_path_merge_mode(the_repository));
+       unlink(git_path_squash_msg(the_repository));
 }
 
 void die_if_checked_out(const char *branch, int ignore_current_worktree)
index 4e0f647..0362f1c 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -220,6 +220,7 @@ extern int cmd_serve(int argc, const char **argv, const char *prefix);
 extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
 extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
+extern int cmd_show_index(int argc, const char **argv, const char *prefix);
 extern int cmd_status(int argc, const char **argv, const char *prefix);
 extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
 extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
index 2fc2d1e..6273ea5 100644 (file)
@@ -1827,15 +1827,11 @@ static void am_run(struct am_state *state, int resume)
                }
 
                if (apply_status) {
-                       int advice_amworkdir = 1;
-
                        printf_ln(_("Patch failed at %s %.*s"), msgnum(state),
                                linelen(state->msg), state->msg);
 
-                       git_config_get_bool("advice.amworkdir", &advice_amworkdir);
-
                        if (advice_amworkdir)
-                               printf_ln(_("Use 'git am --show-current-patch' to see the failed patch"));
+                               advise(_("Use 'git am --show-current-patch' to see the failed patch"));
 
                        die_user_resolve(state);
                }
index 3295718..468b17c 100644 (file)
@@ -9,6 +9,7 @@
 #include "config.h"
 #include "color.h"
 #include "builtin.h"
+#include "repository.h"
 #include "commit.h"
 #include "diff.h"
 #include "revision.h"
@@ -23,6 +24,7 @@
 #include "line-log.h"
 #include "dir.h"
 #include "progress.h"
+#include "object-store.h"
 #include "blame.h"
 #include "string-list.h"
 
@@ -543,7 +545,7 @@ static void output(struct blame_scoreboard *sb, int option)
                        struct commit *commit = ent->suspect->commit;
                        if (commit->object.flags & MORE_THAN_ONE_PATH)
                                continue;
-                       for (suspect = commit->util; suspect; suspect = suspect->next) {
+                       for (suspect = get_blame_suspects(commit); suspect; suspect = suspect->next) {
                                if (suspect->guilty && count++) {
                                        commit->object.flags |= MORE_THAN_ONE_PATH;
                                        break;
@@ -576,7 +578,7 @@ static int read_ancestry(const char *graft_file)
                /* The format is just "Commit Parent1 Parent2 ...\n" */
                struct commit_graft *graft = read_graft_line(&buf);
                if (graft)
-                       register_commit_graft(graft, 0);
+                       register_commit_graft(the_repository, graft, 0);
        }
        fclose(fp);
        strbuf_release(&buf);
@@ -1069,7 +1071,9 @@ parse_done:
                find_alignment(&sb, &output_option);
                if (!*repeated_meta_color &&
                    (output_option & OUTPUT_COLOR_LINE))
-                       strcpy(repeated_meta_color, GIT_COLOR_CYAN);
+                       xsnprintf(repeated_meta_color,
+                                 sizeof(repeated_meta_color),
+                                 "%s", GIT_COLOR_CYAN);
        }
        if (output_option & OUTPUT_ANNOTATE_COMPAT)
                output_option &= ~(OUTPUT_COLOR_LINE | OUTPUT_SHOW_AGE_WITH_COLOR);
index 5217ba3..0192d4a 100644 (file)
@@ -22,6 +22,7 @@
 #include "wt-status.h"
 #include "ref-filter.h"
 #include "worktree.h"
+#include "help.h"
 
 static const char * const builtin_branch_usage[] = {
        N_("git branch [<options>] [-r | -a] [--merged | --no-merged]"),
@@ -36,6 +37,7 @@ static const char * const builtin_branch_usage[] = {
 
 static const char *head;
 static struct object_id head_oid;
+static int used_deprecated_reflog_option;
 
 static int branch_use_color = -1;
 static char branch_colors[][COLOR_MAXLEN] = {
@@ -55,25 +57,19 @@ enum color_branch {
        BRANCH_COLOR_UPSTREAM = 5
 };
 
+static const char *color_branch_slots[] = {
+       [BRANCH_COLOR_RESET]    = "reset",
+       [BRANCH_COLOR_PLAIN]    = "plain",
+       [BRANCH_COLOR_REMOTE]   = "remote",
+       [BRANCH_COLOR_LOCAL]    = "local",
+       [BRANCH_COLOR_CURRENT]  = "current",
+       [BRANCH_COLOR_UPSTREAM] = "upstream",
+};
+
 static struct string_list output = STRING_LIST_INIT_DUP;
 static unsigned int colopts;
 
-static int parse_branch_color_slot(const char *slot)
-{
-       if (!strcasecmp(slot, "plain"))
-               return BRANCH_COLOR_PLAIN;
-       if (!strcasecmp(slot, "reset"))
-               return BRANCH_COLOR_RESET;
-       if (!strcasecmp(slot, "remote"))
-               return BRANCH_COLOR_REMOTE;
-       if (!strcasecmp(slot, "local"))
-               return BRANCH_COLOR_LOCAL;
-       if (!strcasecmp(slot, "current"))
-               return BRANCH_COLOR_CURRENT;
-       if (!strcasecmp(slot, "upstream"))
-               return BRANCH_COLOR_UPSTREAM;
-       return -1;
-}
+define_list_config_array(color_branch_slots);
 
 static int git_branch_config(const char *var, const char *value, void *cb)
 {
@@ -86,7 +82,7 @@ static int git_branch_config(const char *var, const char *value, void *cb)
                return 0;
        }
        if (skip_prefix(var, "color.branch.", &slot_name)) {
-               int slot = parse_branch_color_slot(slot_name);
+               int slot = LOOKUP_CONFIG(color_branch_slots, slot_name);
                if (slot < 0)
                        return 0;
                if (!value)
@@ -573,6 +569,14 @@ static int edit_branch_description(const char *branch_name)
        return 0;
 }
 
+static int deprecated_reflog_option_cb(const struct option *opt,
+                                      const char *arg, int unset)
+{
+       used_deprecated_reflog_option = 1;
+       *(int *)opt->value = !unset;
+       return 0;
+}
+
 int cmd_branch(int argc, const char **argv, const char *prefix)
 {
        int delete = 0, rename = 0, copy = 0, force = 0, list = 0;
@@ -615,7 +619,13 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                OPT_BIT('c', "copy", &copy, N_("copy a branch and its reflog"), 1),
                OPT_BIT('C', NULL, &copy, N_("copy a branch, even if target exists"), 2),
                OPT_BOOL(0, "list", &list, N_("list branch names")),
-               OPT_BOOL('l', "create-reflog", &reflog, N_("create the branch's reflog")),
+               OPT_BOOL(0, "create-reflog", &reflog, N_("create the branch's reflog")),
+               {
+                       OPTION_CALLBACK, 'l', NULL, &reflog, NULL,
+                       N_("deprecated synonym for --create-reflog"),
+                       PARSE_OPT_NOARG | PARSE_OPT_HIDDEN,
+                       deprecated_reflog_option_cb
+               },
                OPT_BOOL(0, "edit-description", &edit_description,
                         N_("edit the description for the branch")),
                OPT__FORCE(&force, N_("force creation, move/rename, deletion"), PARSE_OPT_NOCOMPLETE),
@@ -688,6 +698,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        if (list)
                setup_auto_pager("branch", 1);
 
+       if (used_deprecated_reflog_option && !list) {
+               warning("the '-l' alias for '--create-reflog' is deprecated;");
+               warning("it will be removed in a future version of Git");
+       }
+
        if (delete) {
                if (!argc)
                        die(_("branch name required"));
index 665b581..4a44b24 100644 (file)
@@ -13,6 +13,7 @@
 #include "tree-walk.h"
 #include "sha1-array.h"
 #include "packfile.h"
+#include "object-store.h"
 
 struct batch_options {
        int enabled;
index 2e1d237..2862765 100644 (file)
@@ -4,6 +4,7 @@
 #include "lockfile.h"
 #include "parse-options.h"
 #include "refs.h"
+#include "object-store.h"
 #include "commit.h"
 #include "tree.h"
 #include "tree-walk.h"
@@ -1120,10 +1121,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                OPT_SET_INT('t', "track",  &opts.track, N_("set upstream info for new branch"),
                        BRANCH_TRACK_EXPLICIT),
                OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new-branch"), N_("new unparented branch")),
-               OPT_SET_INT('2', "ours", &opts.writeout_stage, N_("checkout our version for unmerged files"),
-                           2),
-               OPT_SET_INT('3', "theirs", &opts.writeout_stage, N_("checkout their version for unmerged files"),
-                           3),
+               OPT_SET_INT_F('2', "ours", &opts.writeout_stage,
+                             N_("checkout our version for unmerged files"),
+                             2, PARSE_OPT_NONEG),
+               OPT_SET_INT_F('3', "theirs", &opts.writeout_stage,
+                             N_("checkout their version for unmerged files"),
+                             3, PARSE_OPT_NONEG),
                OPT__FORCE(&opts.force, N_("force checkout (throw away local modifications)"),
                           PARSE_OPT_NOCOMPLETE),
                OPT_BOOL('m', "merge", &opts.merge, N_("perform a 3-way merge with the new branch")),
index fad533a..ab402c2 100644 (file)
@@ -16,6 +16,7 @@
 #include "column.h"
 #include "color.h"
 #include "pathspec.h"
+#include "help.h"
 
 static int force = -1; /* unset */
 static int interactive;
@@ -42,6 +43,15 @@ enum color_clean {
        CLEAN_COLOR_ERROR = 5
 };
 
+static const char *color_interactive_slots[] = {
+       [CLEAN_COLOR_ERROR]  = "error",
+       [CLEAN_COLOR_HEADER] = "header",
+       [CLEAN_COLOR_HELP]   = "help",
+       [CLEAN_COLOR_PLAIN]  = "plain",
+       [CLEAN_COLOR_PROMPT] = "prompt",
+       [CLEAN_COLOR_RESET]  = "reset",
+};
+
 static int clean_use_color = -1;
 static char clean_colors[][COLOR_MAXLEN] = {
        [CLEAN_COLOR_ERROR] = GIT_COLOR_BOLD_RED,
@@ -82,22 +92,7 @@ struct menu_stuff {
        void *stuff;
 };
 
-static int parse_clean_color_slot(const char *var)
-{
-       if (!strcasecmp(var, "reset"))
-               return CLEAN_COLOR_RESET;
-       if (!strcasecmp(var, "plain"))
-               return CLEAN_COLOR_PLAIN;
-       if (!strcasecmp(var, "prompt"))
-               return CLEAN_COLOR_PROMPT;
-       if (!strcasecmp(var, "header"))
-               return CLEAN_COLOR_HEADER;
-       if (!strcasecmp(var, "help"))
-               return CLEAN_COLOR_HELP;
-       if (!strcasecmp(var, "error"))
-               return CLEAN_COLOR_ERROR;
-       return -1;
-}
+define_list_config_array(color_interactive_slots);
 
 static int git_clean_config(const char *var, const char *value, void *cb)
 {
@@ -113,7 +108,7 @@ static int git_clean_config(const char *var, const char *value, void *cb)
                return 0;
        }
        if (skip_prefix(var, "color.interactive.", &slot_name)) {
-               int slot = parse_clean_color_slot(slot_name);
+               int slot = LOOKUP_CONFIG(color_interactive_slots, slot_name);
                if (slot < 0)
                        return 0;
                if (!value)
index 99e73da..5c439f1 100644 (file)
@@ -15,6 +15,7 @@
 #include "fetch-pack.h"
 #include "refs.h"
 #include "refspec.h"
+#include "object-store.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "unpack-trees.h"
@@ -1077,7 +1078,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        if (option_required_reference.nr || option_optional_reference.nr)
                setup_reference();
 
-       refspec_item_init(&refspec, value.buf, REFSPEC_FETCH);
+       refspec_item_init_or_die(&refspec, value.buf, REFSPEC_FETCH);
 
        strbuf_reset(&value);
 
@@ -1155,7 +1156,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                        }
 
                if (!is_local && !complete_refs_before_fetch)
-                       transport_fetch_refs(transport, mapped_refs);
+                       transport_fetch_refs(transport, mapped_refs, NULL);
 
                remote_head = find_ref_by_name(refs, "HEAD");
                remote_head_points_at =
@@ -1197,11 +1198,11 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        if (is_local)
                clone_local(path, git_dir);
        else if (refs && complete_refs_before_fetch)
-               transport_fetch_refs(transport, mapped_refs);
+               transport_fetch_refs(transport, mapped_refs, NULL);
 
        update_remote_refs(refs, mapped_refs, remote_head_points_at,
                           branch_top.buf, reflog_msg.buf, transport,
-                          !is_local && !filter_options.choice);
+                          !is_local);
 
        update_head(our_head_points_at, remote_head, reflog_msg.buf);
 
index ecf4219..9fbd352 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include "cache.h"
 #include "config.h"
+#include "object-store.h"
 #include "commit.h"
 #include "tree.h"
 #include "builtin.h"
index a842fea..158e3f8 100644 (file)
@@ -32,6 +32,7 @@
 #include "column.h"
 #include "sequencer.h"
 #include "mailmap.h"
+#include "help.h"
 
 static const char * const builtin_commit_usage[] = {
        N_("git commit [<options>] [--] <pathspec>..."),
@@ -66,6 +67,18 @@ N_("If you wish to skip this commit, use:\n"
 "Then \"git cherry-pick --continue\" will resume cherry-picking\n"
 "the remaining commits.\n");
 
+static const char *color_status_slots[] = {
+       [WT_STATUS_HEADER]        = "header",
+       [WT_STATUS_UPDATED]       = "updated",
+       [WT_STATUS_CHANGED]       = "changed",
+       [WT_STATUS_UNTRACKED]     = "untracked",
+       [WT_STATUS_NOBRANCH]      = "noBranch",
+       [WT_STATUS_UNMERGED]      = "unmerged",
+       [WT_STATUS_LOCAL_BRANCH]  = "localBranch",
+       [WT_STATUS_REMOTE_BRANCH] = "remoteBranch",
+       [WT_STATUS_ONBRANCH]      = "branch",
+};
+
 static const char *use_message_buffer;
 static struct lock_file index_lock; /* real index */
 static struct lock_file false_lock; /* used only for partial commits */
@@ -155,9 +168,9 @@ static int opt_parse_rename_score(const struct option *opt, const char *arg, int
 
 static void determine_whence(struct wt_status *s)
 {
-       if (file_exists(git_path_merge_head()))
+       if (file_exists(git_path_merge_head(the_repository)))
                whence = FROM_MERGE;
-       else if (file_exists(git_path_cherry_pick_head())) {
+       else if (file_exists(git_path_cherry_pick_head(the_repository))) {
                whence = FROM_CHERRY_PICK;
                if (file_exists(git_path_seq_dir()))
                        sequencer_in_use = 1;
@@ -705,21 +718,21 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                if (have_option_m)
                        strbuf_addbuf(&sb, &message);
                hook_arg1 = "message";
-       } else if (!stat(git_path_merge_msg(), &statbuf)) {
+       } else if (!stat(git_path_merge_msg(the_repository), &statbuf)) {
                /*
                 * prepend SQUASH_MSG here if it exists and a
                 * "merge --squash" was originally performed
                 */
-               if (!stat(git_path_squash_msg(), &statbuf)) {
-                       if (strbuf_read_file(&sb, git_path_squash_msg(), 0) < 0)
+               if (!stat(git_path_squash_msg(the_repository), &statbuf)) {
+                       if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0)
                                die_errno(_("could not read SQUASH_MSG"));
                        hook_arg1 = "squash";
                } else
                        hook_arg1 = "merge";
-               if (strbuf_read_file(&sb, git_path_merge_msg(), 0) < 0)
+               if (strbuf_read_file(&sb, git_path_merge_msg(the_repository), 0) < 0)
                        die_errno(_("could not read MERGE_MSG"));
-       } else if (!stat(git_path_squash_msg(), &statbuf)) {
-               if (strbuf_read_file(&sb, git_path_squash_msg(), 0) < 0)
+       } else if (!stat(git_path_squash_msg(the_repository), &statbuf)) {
+               if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0)
                        die_errno(_("could not read SQUASH_MSG"));
                hook_arg1 = "squash";
        } else if (template_file) {
@@ -800,8 +813,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                                        "       %s\n"
                                        "and try again.\n"),
                                whence == FROM_MERGE ?
-                                       git_path_merge_head() :
-                                       git_path_cherry_pick_head());
+                                       git_path_merge_head(the_repository) :
+                                       git_path_cherry_pick_head(the_repository));
                }
 
                fprintf(s->fp, "\n");
@@ -1183,27 +1196,14 @@ static int dry_run_commit(int argc, const char **argv, const char *prefix,
        return commitable ? 0 : 1;
 }
 
+define_list_config_array_extra(color_status_slots, {"added"});
+
 static int parse_status_slot(const char *slot)
 {
-       if (!strcasecmp(slot, "header"))
-               return WT_STATUS_HEADER;
-       if (!strcasecmp(slot, "branch"))
-               return WT_STATUS_ONBRANCH;
-       if (!strcasecmp(slot, "updated") || !strcasecmp(slot, "added"))
+       if (!strcasecmp(slot, "added"))
                return WT_STATUS_UPDATED;
-       if (!strcasecmp(slot, "changed"))
-               return WT_STATUS_CHANGED;
-       if (!strcasecmp(slot, "untracked"))
-               return WT_STATUS_UNTRACKED;
-       if (!strcasecmp(slot, "nobranch"))
-               return WT_STATUS_NOBRANCH;
-       if (!strcasecmp(slot, "unmerged"))
-               return WT_STATUS_UNMERGED;
-       if (!strcasecmp(slot, "localBranch"))
-               return WT_STATUS_LOCAL_BRANCH;
-       if (!strcasecmp(slot, "remoteBranch"))
-               return WT_STATUS_REMOTE_BRANCH;
-       return -1;
+
+       return LOOKUP_CONFIG(color_status_slots, slot);
 }
 
 static int git_status_config(const char *k, const char *v, void *cb)
@@ -1564,7 +1564,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                if (!reflog_msg)
                        reflog_msg = "commit (merge)";
                pptr = commit_list_append(current_head, pptr);
-               fp = xfopen(git_path_merge_head(), "r");
+               fp = xfopen(git_path_merge_head(the_repository), "r");
                while (strbuf_getline_lf(&m, fp) != EOF) {
                        struct commit *parent;
 
@@ -1575,8 +1575,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                }
                fclose(fp);
                strbuf_release(&m);
-               if (!stat(git_path_merge_mode(), &statbuf)) {
-                       if (strbuf_read_file(&sb, git_path_merge_mode(), 0) < 0)
+               if (!stat(git_path_merge_mode(the_repository), &statbuf)) {
+                       if (strbuf_read_file(&sb, git_path_merge_mode(the_repository), 0) < 0)
                                die_errno(_("could not read MERGE_MODE"));
                        if (!strcmp(sb.buf, "no-ff"))
                                allow_fast_forward = 0;
@@ -1639,12 +1639,12 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                die("%s", err.buf);
        }
 
-       unlink(git_path_cherry_pick_head());
-       unlink(git_path_revert_head());
-       unlink(git_path_merge_head());
-       unlink(git_path_merge_msg());
-       unlink(git_path_merge_mode());
-       unlink(git_path_squash_msg());
+       unlink(git_path_cherry_pick_head(the_repository));
+       unlink(git_path_revert_head(the_repository));
+       unlink(git_path_merge_head(the_repository));
+       unlink(git_path_merge_msg(the_repository));
+       unlink(git_path_merge_mode(the_repository));
+       unlink(git_path_squash_msg(the_repository));
 
        if (commit_index_files())
                die (_("Repository has been updated, but unable to write\n"
index b29d26d..2c93a28 100644 (file)
@@ -67,7 +67,7 @@ static int show_origin;
        { OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
        PARSE_OPT_NONEG, option_parse_type, (i) }
 
-static struct option builtin_config_options[];
+static NORETURN void usage_builtin_config(void);
 
 static int option_parse_type(const struct option *opt, const char *arg,
                             int unset)
@@ -111,8 +111,7 @@ static int option_parse_type(const struct option *opt, const char *arg,
                 * --type=int'.
                 */
                error("only one type at a time.");
-               usage_with_options(builtin_config_usage,
-                       builtin_config_options);
+               usage_builtin_config();
        }
        *to_type = new_type;
 
@@ -157,11 +156,16 @@ static struct option builtin_config_options[] = {
        OPT_END(),
 };
 
+static NORETURN void usage_builtin_config(void)
+{
+       usage_with_options(builtin_config_usage, builtin_config_options);
+}
+
 static void check_argc(int argc, int min, int max) {
        if (argc >= min && argc <= max)
                return;
        error("wrong number of arguments");
-       usage_with_options(builtin_config_usage, builtin_config_options);
+       usage_builtin_config();
 }
 
 static void show_config_origin(struct strbuf *buf)
@@ -596,7 +600,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
        if (use_global_config + use_system_config + use_local_config +
            !!given_config_source.file + !!given_config_source.blob > 1) {
                error("only one config file at a time.");
-               usage_with_options(builtin_config_usage, builtin_config_options);
+               usage_builtin_config();
        }
 
        if (use_local_config && nongit)
@@ -660,12 +664,12 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 
        if ((actions & (ACTION_GET_COLOR|ACTION_GET_COLORBOOL)) && type) {
                error("--get-color and variable type are incoherent");
-               usage_with_options(builtin_config_usage, builtin_config_options);
+               usage_builtin_config();
        }
 
        if (HAS_MULTI_BITS(actions)) {
                error("only one action at a time.");
-               usage_with_options(builtin_config_usage, builtin_config_options);
+               usage_builtin_config();
        }
        if (actions == 0)
                switch (argc) {
@@ -673,25 +677,24 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                case 2: actions = ACTION_SET; break;
                case 3: actions = ACTION_SET_ALL; break;
                default:
-                       usage_with_options(builtin_config_usage, builtin_config_options);
+                       usage_builtin_config();
                }
        if (omit_values &&
            !(actions == ACTION_LIST || actions == ACTION_GET_REGEXP)) {
                error("--name-only is only applicable to --list or --get-regexp");
-               usage_with_options(builtin_config_usage, builtin_config_options);
+               usage_builtin_config();
        }
 
        if (show_origin && !(actions &
                (ACTION_GET|ACTION_GET_ALL|ACTION_GET_REGEXP|ACTION_LIST))) {
                error("--show-origin is only applicable to --get, --get-all, "
                          "--get-regexp, and --list.");
-               usage_with_options(builtin_config_usage, builtin_config_options);
+               usage_builtin_config();
        }
 
        if (default_value && !(actions & ACTION_GET)) {
                error("--default is only applicable to --get");
-               usage_with_options(builtin_config_usage,
-                       builtin_config_options);
+               usage_builtin_config();
        }
 
        if (actions & PAGING_ACTIONS)
index cf1ae77..1e87f68 100644 (file)
 #include "hashmap.h"
 #include "argv-array.h"
 #include "run-command.h"
+#include "object-store.h"
 #include "revision.h"
 #include "list-objects.h"
+#include "commit-slab.h"
 
 #define MAX_TAGS       (FLAG_BITS - 1)
 
+define_commit_slab(commit_names, struct commit_name *);
+
 static const char * const describe_usage[] = {
        N_("git describe [<options>] [<commit-ish>...]"),
        N_("git describe [<options>] --dirty"),
@@ -37,6 +41,7 @@ static struct string_list patterns = STRING_LIST_INIT_NODUP;
 static struct string_list exclude_patterns = STRING_LIST_INIT_NODUP;
 static int always;
 static const char *suffix, *dirty, *broken;
+static struct commit_names commit_names;
 
 /* diff-index command arguments to check if working tree is dirty. */
 static const char *diff_index_args[] = {
@@ -321,11 +326,14 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
        if (!have_util) {
                struct hashmap_iter iter;
                struct commit *c;
-               struct commit_name *n = hashmap_iter_first(&names, &iter);
+               struct commit_name *n;
+
+               init_commit_names(&commit_names);
+               n = hashmap_iter_first(&names, &iter);
                for (; n; n = hashmap_iter_next(&iter)) {
                        c = lookup_commit_reference_gently(&n->peeled, 1);
                        if (c)
-                               c->util = n;
+                               *commit_names_at(&commit_names, c) = n;
                }
                have_util = 1;
        }
@@ -336,8 +344,11 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
        while (list) {
                struct commit *c = pop_commit(&list);
                struct commit_list *parents = c->parents;
+               struct commit_name **slot;
+
                seen_commits++;
-               n = c->util;
+               slot = commit_names_peek(&commit_names, c);
+               n = slot ? *slot : NULL;
                if (n) {
                        if (!tags && !all && n->prio < 2) {
                                unannotated_cnt++;
index bfefff3..b709b6e 100644 (file)
@@ -352,6 +352,13 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
        rev.diffopt.flags.allow_external = 1;
        rev.diffopt.flags.allow_textconv = 1;
 
+       /*
+        * Default to intent-to-add entries invisible in the
+        * index. This makes them show up as new files in diff-files
+        * and not at all in diff-cached.
+        */
+       rev.diffopt.ita_invisible_in_index = 1;
+
        if (nongit)
                die(_("Not a git repository"));
        argc = setup_revisions(argc, argv, &rev, NULL);
index bc97d4a..51f6c9c 100644 (file)
@@ -20,6 +20,7 @@
 #include "argv-array.h"
 #include "strbuf.h"
 #include "lockfile.h"
+#include "object-store.h"
 #include "dir.h"
 
 static char *diff_gui_tool;
index 6c97687..9ee6a4d 100644 (file)
@@ -8,6 +8,7 @@
 #include "config.h"
 #include "refs.h"
 #include "refspec.h"
+#include "object-store.h"
 #include "commit.h"
 #include "object.h"
 #include "tag.h"
@@ -22,6 +23,7 @@
 #include "quote.h"
 #include "remote.h"
 #include "blob.h"
+#include "commit-slab.h"
 
 static const char *fast_export_usage[] = {
        N_("git fast-export [rev-list-opts]"),
@@ -38,6 +40,7 @@ static int full_tree;
 static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
 static struct refspec refspecs = REFSPEC_INIT_FETCH;
 static int anonymize;
+static struct revision_sources revision_sources;
 
 static int parse_opt_signed_tag_mode(const struct option *opt,
                                     const char *arg, int unset)
@@ -589,7 +592,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
                if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
                        export_blob(&diff_queued_diff.queue[i]->two->oid);
 
-       refname = commit->util;
+       refname = *revision_sources_at(&revision_sources, commit);
        if (anonymize) {
                refname = anonymize_refname(refname);
                anonymize_ident_line(&committer, &committer_end);
@@ -861,10 +864,11 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
                 * This ref will not be updated through a commit, lets make
                 * sure it gets properly updated eventually.
                 */
-               if (commit->util || commit->object.flags & SHOWN)
+               if (*revision_sources_at(&revision_sources, commit) ||
+                   commit->object.flags & SHOWN)
                        string_list_append(&extra_refs, full_name)->util = commit;
-               if (!commit->util)
-                       commit->util = full_name;
+               if (!*revision_sources_at(&revision_sources, commit))
+                       *revision_sources_at(&revision_sources, commit) = full_name;
        }
 }
 
@@ -1028,8 +1032,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        git_config(git_default_config, NULL);
 
        init_revisions(&revs, prefix);
+       init_revision_sources(&revision_sources);
        revs.topo_order = 1;
-       revs.show_source = 1;
+       revs.sources = &revision_sources;
        revs.rewrite_parents = 1;
        argc = parse_options(argc, argv, prefix, options, fast_export_usage,
                        PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
index ea5b966..ac06f6a 100644 (file)
@@ -6,6 +6,7 @@
 #include "repository.h"
 #include "refs.h"
 #include "refspec.h"
+#include "object-store.h"
 #include "commit.h"
 #include "builtin.h"
 #include "string-list.h"
@@ -93,19 +94,6 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
        return git_default_config(k, v, cb);
 }
 
-static int gitmodules_fetch_config(const char *var, const char *value, void *cb)
-{
-       if (!strcmp(var, "submodule.fetchjobs")) {
-               max_children = parse_submodule_fetchjobs(var, value);
-               return 0;
-       } else if (!strcmp(var, "fetch.recursesubmodules")) {
-               recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
-               return 0;
-       }
-
-       return 0;
-}
-
 static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
 {
        /*
@@ -254,9 +242,9 @@ static int will_fetch(struct ref **head, const unsigned char *sha1)
        return 0;
 }
 
-static void find_non_local_tags(struct transport *transport,
-                       struct ref **head,
-                       struct ref ***tail)
+static void find_non_local_tags(const struct ref *refs,
+                               struct ref **head,
+                               struct ref ***tail)
 {
        struct string_list existing_refs = STRING_LIST_INIT_DUP;
        struct string_list remote_refs = STRING_LIST_INIT_NODUP;
@@ -264,7 +252,7 @@ static void find_non_local_tags(struct transport *transport,
        struct string_list_item *item = NULL;
 
        for_each_ref(add_existing, &existing_refs);
-       for (ref = transport_get_remote_refs(transport, NULL); ref; ref = ref->next) {
+       for (ref = refs; ref; ref = ref->next) {
                if (!starts_with(ref->name, "refs/tags/"))
                        continue;
 
@@ -338,7 +326,8 @@ static void find_non_local_tags(struct transport *transport,
        string_list_clear(&remote_refs, 0);
 }
 
-static struct ref *get_ref_map(struct transport *transport,
+static struct ref *get_ref_map(struct remote *remote,
+                              const struct ref *remote_refs,
                               struct refspec *rs,
                               int tags, int *autotags)
 {
@@ -346,26 +335,11 @@ static struct ref *get_ref_map(struct transport *transport,
        struct ref *rm;
        struct ref *ref_map = NULL;
        struct ref **tail = &ref_map;
-       struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
 
        /* opportunistically-updated references: */
        struct ref *orefs = NULL, **oref_tail = &orefs;
 
-       const struct ref *remote_refs;
-
-       if (rs->nr)
-               refspec_ref_prefixes(rs, &ref_prefixes);
-       else if (transport->remote && transport->remote->fetch.nr)
-               refspec_ref_prefixes(&transport->remote->fetch, &ref_prefixes);
-
-       if (ref_prefixes.argc &&
-           (tags == TAGS_SET || (tags == TAGS_DEFAULT && !rs->nr))) {
-               argv_array_push(&ref_prefixes, "refs/tags/");
-       }
-
-       remote_refs = transport_get_remote_refs(transport, &ref_prefixes);
-
-       argv_array_clear(&ref_prefixes);
+       struct string_list existing_refs = STRING_LIST_INIT_DUP;
 
        if (rs->nr) {
                struct refspec *fetch_refspec;
@@ -402,7 +376,7 @@ static struct ref *get_ref_map(struct transport *transport,
                if (refmap.nr)
                        fetch_refspec = &refmap;
                else
-                       fetch_refspec = &transport->remote->fetch;
+                       fetch_refspec = &remote->fetch;
 
                for (i = 0; i < fetch_refspec->nr; i++)
                        get_fetch_map(ref_map, &fetch_refspec->items[i], &oref_tail, 1);
@@ -410,7 +384,6 @@ static struct ref *get_ref_map(struct transport *transport,
                die("--refmap option is only meaningful with command-line refspec(s).");
        } else {
                /* Use the defaults */
-               struct remote *remote = transport->remote;
                struct branch *branch = branch_get(NULL);
                int has_merge = branch_has_merge_config(branch);
                if (remote &&
@@ -449,7 +422,7 @@ static struct ref *get_ref_map(struct transport *transport,
                /* also fetch all tags */
                get_fetch_map(remote_refs, tag_refspec, &tail, 0);
        else if (tags == TAGS_DEFAULT && *autotags)
-               find_non_local_tags(transport, &ref_map, &tail);
+               find_non_local_tags(remote_refs, &ref_map, &tail);
 
        /* Now append any refs to be updated opportunistically: */
        *tail = orefs;
@@ -458,7 +431,23 @@ static struct ref *get_ref_map(struct transport *transport,
                tail = &rm->next;
        }
 
-       return ref_remove_duplicates(ref_map);
+       ref_map = ref_remove_duplicates(ref_map);
+
+       for_each_ref(add_existing, &existing_refs);
+       for (rm = ref_map; rm; rm = rm->next) {
+               if (rm->peer_ref) {
+                       struct string_list_item *peer_item =
+                               string_list_lookup(&existing_refs,
+                                                  rm->peer_ref->name);
+                       if (peer_item) {
+                               struct object_id *old_oid = peer_item->util;
+                               oidcpy(&rm->peer_ref->old_oid, old_oid);
+                       }
+               }
+       }
+       string_list_clear(&existing_refs, 1);
+
+       return ref_map;
 }
 
 #define STORE_REF_ERROR_OTHER 1
@@ -768,7 +757,7 @@ static int iterate_ref_map(void *cb_data, struct object_id *oid)
 }
 
 static int store_updated_refs(const char *raw_url, const char *remote_name,
-               struct ref *ref_map)
+                             int connectivity_checked, struct ref *ref_map)
 {
        FILE *fp;
        struct commit *commit;
@@ -777,7 +766,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
        const char *what, *kind;
        struct ref *rm;
        char *url;
-       const char *filename = dry_run ? "/dev/null" : git_path_fetch_head();
+       const char *filename = dry_run ? "/dev/null" : git_path_fetch_head(the_repository);
        int want_status;
        int summary_width = transport_summary_width(ref_map);
 
@@ -790,10 +779,12 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
        else
                url = xstrdup("foreign");
 
-       rm = ref_map;
-       if (check_connected(iterate_ref_map, &rm, NULL)) {
-               rc = error(_("%s did not send all necessary objects\n"), url);
-               goto abort;
+       if (!connectivity_checked) {
+               rm = ref_map;
+               if (check_connected(iterate_ref_map, &rm, NULL)) {
+                       rc = error(_("%s did not send all necessary objects\n"), url);
+                       goto abort;
+               }
        }
 
        prepare_format_display(ref_map);
@@ -945,15 +936,32 @@ static int quickfetch(struct ref *ref_map)
        return check_connected(iterate_ref_map, &rm, &opt);
 }
 
-static int fetch_refs(struct transport *transport, struct ref *ref_map)
+static int fetch_refs(struct transport *transport, struct ref *ref_map,
+                     struct ref **updated_remote_refs)
 {
        int ret = quickfetch(ref_map);
        if (ret)
-               ret = transport_fetch_refs(transport, ref_map);
+               ret = transport_fetch_refs(transport, ref_map,
+                                          updated_remote_refs);
        if (!ret)
-               ret |= store_updated_refs(transport->url,
-                               transport->remote->name,
-                               ref_map);
+               /*
+                * Keep the new pack's ".keep" file around to allow the caller
+                * time to update refs to reference the new objects.
+                */
+               return 0;
+       transport_unlock_pack(transport);
+       return ret;
+}
+
+/* Update local refs based on the ref values fetched from a remote */
+static int consume_refs(struct transport *transport, struct ref *ref_map)
+{
+       int connectivity_checked = transport->smart_options
+               ? transport->smart_options->connectivity_checked : 0;
+       int ret = store_updated_refs(transport->url,
+                                    transport->remote->name,
+                                    connectivity_checked,
+                                    ref_map);
        transport_unlock_pack(transport);
        return ret;
 }
@@ -1029,7 +1037,7 @@ static void check_not_current_branch(struct ref *ref_map)
 
 static int truncate_fetch_head(void)
 {
-       const char *filename = git_path_fetch_head();
+       const char *filename = git_path_fetch_head(the_repository);
        FILE *fp = fopen_for_writing(filename);
 
        if (!fp)
@@ -1099,7 +1107,8 @@ static void backfill_tags(struct transport *transport, struct ref *ref_map)
        transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
        transport_set_option(transport, TRANS_OPT_DEPTH, "0");
        transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
-       fetch_refs(transport, ref_map);
+       if (!fetch_refs(transport, ref_map, NULL))
+               consume_refs(transport, ref_map);
 
        if (gsecondary) {
                transport_disconnect(gsecondary);
@@ -1110,13 +1119,12 @@ static void backfill_tags(struct transport *transport, struct ref *ref_map)
 static int do_fetch(struct transport *transport,
                    struct refspec *rs)
 {
-       struct string_list existing_refs = STRING_LIST_INIT_DUP;
        struct ref *ref_map;
-       struct ref *rm;
        int autotags = (transport->remote->fetch_tags == 1);
        int retcode = 0;
-
-       for_each_ref(add_existing, &existing_refs);
+       const struct ref *remote_refs;
+       struct ref *updated_remote_refs = NULL;
+       struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
 
        if (tags == TAGS_DEFAULT) {
                if (transport->remote->fetch_tags == 2)
@@ -1132,22 +1140,24 @@ static int do_fetch(struct transport *transport,
                        goto cleanup;
        }
 
-       ref_map = get_ref_map(transport, rs, tags, &autotags);
-       if (!update_head_ok)
-               check_not_current_branch(ref_map);
+       if (rs->nr)
+               refspec_ref_prefixes(rs, &ref_prefixes);
+       else if (transport->remote && transport->remote->fetch.nr)
+               refspec_ref_prefixes(&transport->remote->fetch, &ref_prefixes);
 
-       for (rm = ref_map; rm; rm = rm->next) {
-               if (rm->peer_ref) {
-                       struct string_list_item *peer_item =
-                               string_list_lookup(&existing_refs,
-                                                  rm->peer_ref->name);
-                       if (peer_item) {
-                               struct object_id *old_oid = peer_item->util;
-                               oidcpy(&rm->peer_ref->old_oid, old_oid);
-                       }
-               }
+       if (ref_prefixes.argc &&
+           (tags == TAGS_SET || (tags == TAGS_DEFAULT && !rs->nr))) {
+               argv_array_push(&ref_prefixes, "refs/tags/");
        }
 
+       remote_refs = transport_get_remote_refs(transport, &ref_prefixes);
+       argv_array_clear(&ref_prefixes);
+
+       ref_map = get_ref_map(transport->remote, remote_refs, rs,
+                             tags, &autotags);
+       if (!update_head_ok)
+               check_not_current_branch(ref_map);
+
        if (tags == TAGS_DEFAULT && autotags)
                transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
        if (prune) {
@@ -1164,7 +1174,24 @@ static int do_fetch(struct transport *transport,
                                   transport->url);
                }
        }
-       if (fetch_refs(transport, ref_map)) {
+
+       if (fetch_refs(transport, ref_map, &updated_remote_refs)) {
+               free_refs(ref_map);
+               retcode = 1;
+               goto cleanup;
+       }
+       if (updated_remote_refs) {
+               /*
+                * Regenerate ref_map using the updated remote refs.  This is
+                * to account for additional information which may be provided
+                * by the transport (e.g. shallow info).
+                */
+               free_refs(ref_map);
+               ref_map = get_ref_map(transport->remote, updated_remote_refs, rs,
+                                     tags, &autotags);
+               free_refs(updated_remote_refs);
+       }
+       if (consume_refs(transport, ref_map)) {
                free_refs(ref_map);
                retcode = 1;
                goto cleanup;
@@ -1176,14 +1203,13 @@ static int do_fetch(struct transport *transport,
        if (tags == TAGS_DEFAULT && autotags) {
                struct ref **tail = &ref_map;
                ref_map = NULL;
-               find_non_local_tags(transport, &ref_map, &tail);
+               find_non_local_tags(remote_refs, &ref_map, &tail);
                if (ref_map)
                        backfill_tags(transport, ref_map);
                free_refs(ref_map);
        }
 
  cleanup:
-       string_list_clear(&existing_refs, 1);
        return retcode;
 }
 
@@ -1433,7 +1459,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        for (i = 1; i < argc; i++)
                strbuf_addf(&default_rla, " %s", argv[i]);
 
-       config_from_gitmodules(gitmodules_fetch_config, NULL);
+       fetch_config_from_gitmodules(&max_children, &recurse_submodules);
        git_config(git_fetch_config, NULL);
 
        argc = parse_options(argc, argv, prefix,
@@ -1449,7 +1475,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        if (unshallow) {
                if (depth)
                        die(_("--depth and --unshallow cannot be used together"));
-               else if (!is_repository_shallow())
+               else if (!is_repository_shallow(the_repository))
                        die(_("--unshallow on a complete repository does not make sense"));
                else
                        depth = xstrfmt("%d", INFINITE_DEPTH);
index bd680be..1b526ad 100644 (file)
@@ -2,6 +2,7 @@
 #include "cache.h"
 #include "config.h"
 #include "refs.h"
+#include "object-store.h"
 #include "commit.h"
 #include "diff.h"
 #include "revision.h"
index ee753a4..61bcaf6 100644 (file)
@@ -828,6 +828,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                            GREP_PATTERN_TYPE_PCRE),
                OPT_GROUP(""),
                OPT_BOOL('n', "line-number", &opt.linenum, N_("show line numbers")),
+               OPT_BOOL(0, "column", &opt.columnnum, N_("show column number of first match")),
                OPT_NEGBIT('h', NULL, &opt.pathname, N_("don't show filenames"), 1),
                OPT_BIT('H', NULL, &opt.pathname, N_("show filenames"), 1),
                OPT_NEGBIT(0, "full-name", &opt.relative,
index a9a3a19..9ada4f4 100644 (file)
@@ -6,6 +6,7 @@
  */
 #include "builtin.h"
 #include "config.h"
+#include "object-store.h"
 #include "blob.h"
 #include "quote.h"
 #include "parse-options.h"
index 58e0a55..8d4f6dd 100644 (file)
@@ -37,6 +37,7 @@ static const char *html_path;
 
 static int show_all = 0;
 static int show_guides = 0;
+static int show_config;
 static int verbose;
 static unsigned int colopts;
 static enum help_format help_format = HELP_FORMAT_NONE;
@@ -45,6 +46,8 @@ static struct option builtin_help_options[] = {
        OPT_BOOL('a', "all", &show_all, N_("print all available commands")),
        OPT_HIDDEN_BOOL(0, "exclude-guides", &exclude_guides, N_("exclude guides")),
        OPT_BOOL('g', "guides", &show_guides, N_("print list of useful guides")),
+       OPT_BOOL('c', "config", &show_config, N_("print all configuration variable names")),
+       OPT_SET_INT_F(0, "config-for-completion", &show_config, "", 2, PARSE_OPT_HIDDEN),
        OPT_SET_INT('m', "man", &help_format, N_("show man page"), HELP_FORMAT_MAN),
        OPT_SET_INT('w', "web", &help_format, N_("show manual in web browser"),
                        HELP_FORMAT_WEB),
@@ -444,6 +447,19 @@ int cmd_help(int argc, const char **argv, const char *prefix)
                list_commands(colopts, &main_cmds, &other_cmds);
        }
 
+       if (show_config) {
+               int for_human = show_config == 1;
+
+               if (!for_human) {
+                       list_config_help(for_human);
+                       return 0;
+               }
+               setup_pager();
+               list_config_help(for_human);
+               printf("\n%s\n", _("'git help config' for more information"));
+               return 0;
+       }
+
        if (show_guides)
                list_common_guides_help();
 
index 4686f68..805f89d 100644 (file)
@@ -7,6 +7,7 @@
 #include "cache.h"
 #include "config.h"
 #include "refs.h"
+#include "object-store.h"
 #include "color.h"
 #include "commit.h"
 #include "diff.h"
@@ -28,6 +29,7 @@
 #include "mailmap.h"
 #include "gpg-interface.h"
 #include "progress.h"
+#include "commit-slab.h"
 
 #define MAIL_DEFAULT_WRAP 72
 
@@ -148,6 +150,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
        static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
        struct decoration_filter decoration_filter = {&decorate_refs_include,
                                                      &decorate_refs_exclude};
+       static struct revision_sources revision_sources;
 
        const struct option builtin_log_options[] = {
                OPT__QUIET(&quiet, N_("suppress diff output")),
@@ -194,8 +197,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
            rev->diffopt.filter || rev->diffopt.flags.follow_renames)
                rev->always_show_header = 0;
 
-       if (source)
-               rev->show_source = 1;
+       if (source) {
+               init_revision_sources(&revision_sources);
+               rev->sources = &revision_sources;
+       }
 
        if (mailmap) {
                rev->mailmap = xcalloc(1, sizeof(struct string_list));
@@ -1337,6 +1342,8 @@ static struct commit *get_base_commit(const char *base_commit,
        return base;
 }
 
+define_commit_slab(commit_base, int);
+
 static void prepare_bases(struct base_tree_info *bases,
                          struct commit *base,
                          struct commit **list,
@@ -1345,11 +1352,13 @@ static void prepare_bases(struct base_tree_info *bases,
        struct commit *commit;
        struct rev_info revs;
        struct diff_options diffopt;
+       struct commit_base commit_base;
        int i;
 
        if (!base)
                return;
 
+       init_commit_base(&commit_base);
        diff_setup(&diffopt);
        diffopt.flags.recursive = 1;
        diff_setup_done(&diffopt);
@@ -1362,7 +1371,7 @@ static void prepare_bases(struct base_tree_info *bases,
        for (i = 0; i < total; i++) {
                list[i]->object.flags &= ~UNINTERESTING;
                add_pending_object(&revs, &list[i]->object, "rev_list");
-               list[i]->util = (void *)1;
+               *commit_base_at(&commit_base, list[i]) = 1;
        }
        base->object.flags |= UNINTERESTING;
        add_pending_object(&revs, &base->object, "base");
@@ -1376,7 +1385,7 @@ static void prepare_bases(struct base_tree_info *bases,
        while ((commit = get_revision(&revs)) != NULL) {
                struct object_id oid;
                struct object_id *patch_id;
-               if (commit->util)
+               if (*commit_base_at(&commit_base, commit))
                        continue;
                if (commit_patch_id(commit, &diffopt, &oid, 0))
                        die(_("cannot get patch id"));
@@ -1385,6 +1394,7 @@ static void prepare_bases(struct base_tree_info *bases,
                oidcpy(patch_id, &oid);
                bases->nr_patch_id++;
        }
+       clear_commit_base(&commit_base);
 }
 
 static void print_bases(struct base_tree_info *bases, FILE *file)
@@ -1746,6 +1756,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        if (base_commit || base_auto) {
                struct commit *base = get_base_commit(base_commit, list, nr);
                reset_revision_walk();
+               clear_object_flags(UNINTERESTING);
                prepare_bases(&bases, base, list, nr);
        }
 
index 409da4e..fe3b952 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include "cache.h"
 #include "config.h"
+#include "object-store.h"
 #include "blob.h"
 #include "tree.h"
 #include "commit.h"
index bf01e05..8a8d579 100644 (file)
@@ -1,6 +1,7 @@
 #include "builtin.h"
 #include "tree-walk.h"
 #include "xdiff-interface.h"
+#include "object-store.h"
 #include "blob.h"
 #include "exec-cmd.h"
 #include "merge-blobs.h"
index b00d6f4..d1b547d 100644 (file)
@@ -247,9 +247,9 @@ static struct option builtin_merge_options[] = {
 /* Cleans up metadata that is uninteresting after a succeeded merge. */
 static void drop_save(void)
 {
-       unlink(git_path_merge_head());
-       unlink(git_path_merge_msg());
-       unlink(git_path_merge_mode());
+       unlink(git_path_merge_head(the_repository));
+       unlink(git_path_merge_msg(the_repository));
+       unlink(git_path_merge_mode(the_repository));
 }
 
 static int save_state(struct object_id *stash)
@@ -382,7 +382,7 @@ static void squash_message(struct commit *commit, struct commit_list *remotehead
                        oid_to_hex(&commit->object.oid));
                pretty_print_commit(&ctx, commit, &out);
        }
-       write_file_buf(git_path_squash_msg(), out.buf, out.len);
+       write_file_buf(git_path_squash_msg(the_repository), out.buf, out.len);
        strbuf_release(&out);
 }
 
@@ -445,6 +445,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
        struct object_id branch_head;
        struct strbuf buf = STRBUF_INIT;
        struct strbuf bname = STRBUF_INIT;
+       struct merge_remote_desc *desc;
        const char *ptr;
        char *found_ref;
        int len, early;
@@ -517,16 +518,13 @@ static void merge_name(const char *remote, struct strbuf *msg)
                strbuf_release(&truname);
        }
 
-       if (remote_head->util) {
-               struct merge_remote_desc *desc;
-               desc = merge_remote_util(remote_head);
-               if (desc && desc->obj && desc->obj->type == OBJ_TAG) {
-                       strbuf_addf(msg, "%s\t\t%s '%s'\n",
-                                   oid_to_hex(&desc->obj->oid),
-                                   type_name(desc->obj->type),
-                                   remote);
-                       goto cleanup;
-               }
+       desc = merge_remote_util(remote_head);
+       if (desc && desc->obj && desc->obj->type == OBJ_TAG) {
+               strbuf_addf(msg, "%s\t\t%s '%s'\n",
+                           oid_to_hex(&desc->obj->oid),
+                           type_name(desc->obj->type),
+                           remote);
+               goto cleanup;
        }
 
        strbuf_addf(msg, "%s\t\tcommit '%s'\n",
@@ -743,7 +741,7 @@ static void add_strategies(const char *string, unsigned attr)
 
 static void read_merge_msg(struct strbuf *msg)
 {
-       const char *filename = git_path_merge_msg();
+       const char *filename = git_path_merge_msg(the_repository);
        strbuf_reset(msg);
        if (strbuf_read_file(msg, filename, 0) < 0)
                die_errno(_("Could not read from '%s'"), filename);
@@ -780,18 +778,18 @@ static void prepare_to_commit(struct commit_list *remoteheads)
        if (signoff)
                append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0);
        write_merge_heads(remoteheads);
-       write_file_buf(git_path_merge_msg(), msg.buf, msg.len);
+       write_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len);
        if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg",
-                           git_path_merge_msg(), "merge", NULL))
+                           git_path_merge_msg(the_repository), "merge", NULL))
                abort_commit(remoteheads, NULL);
        if (0 < option_edit) {
-               if (launch_editor(git_path_merge_msg(), NULL, NULL))
+               if (launch_editor(git_path_merge_msg(the_repository), NULL, NULL))
                        abort_commit(remoteheads, NULL);
        }
 
        if (verify_msg && run_commit_hook(0 < option_edit, get_index_file(),
                                          "commit-msg",
-                                         git_path_merge_msg(), NULL))
+                                         git_path_merge_msg(the_repository), NULL))
                abort_commit(remoteheads, NULL);
 
        read_merge_msg(&msg);
@@ -861,7 +859,7 @@ static int suggest_conflicts(void)
        FILE *fp;
        struct strbuf msgbuf = STRBUF_INIT;
 
-       filename = git_path_merge_msg();
+       filename = git_path_merge_msg(the_repository);
        fp = xfopen(filename, "a");
 
        append_conflicts_hint(&msgbuf);
@@ -934,19 +932,22 @@ static void write_merge_heads(struct commit_list *remoteheads)
        for (j = remoteheads; j; j = j->next) {
                struct object_id *oid;
                struct commit *c = j->item;
-               if (c->util && merge_remote_util(c)->obj) {
-                       oid = &merge_remote_util(c)->obj->oid;
+               struct merge_remote_desc *desc;
+
+               desc = merge_remote_util(c);
+               if (desc && desc->obj) {
+                       oid = &desc->obj->oid;
                } else {
                        oid = &c->object.oid;
                }
                strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
        }
-       write_file_buf(git_path_merge_head(), buf.buf, buf.len);
+       write_file_buf(git_path_merge_head(the_repository), buf.buf, buf.len);
 
        strbuf_reset(&buf);
        if (fast_forward == FF_NO)
                strbuf_addstr(&buf, "no-ff");
-       write_file_buf(git_path_merge_mode(), buf.buf, buf.len);
+       write_file_buf(git_path_merge_mode(the_repository), buf.buf, buf.len);
        strbuf_release(&buf);
 }
 
@@ -954,7 +955,8 @@ static void write_merge_state(struct commit_list *remoteheads)
 {
        write_merge_heads(remoteheads);
        strbuf_addch(&merge_msg, '\n');
-       write_file_buf(git_path_merge_msg(), merge_msg.buf, merge_msg.len);
+       write_file_buf(git_path_merge_msg(the_repository), merge_msg.buf,
+                      merge_msg.len);
 }
 
 static int default_edit_option(void)
@@ -1037,7 +1039,7 @@ static void handle_fetch_head(struct commit_list **remotes, struct strbuf *merge
        if (!merge_names)
                merge_names = &fetch_head_file;
 
-       filename = git_path_fetch_head();
+       filename = git_path_fetch_head(the_repository);
        fd = open(filename, O_RDONLY);
        if (fd < 0)
                die_errno(_("could not open '%s' for reading"), filename);
@@ -1185,14 +1187,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
        branch = branch_to_free = resolve_refdup("HEAD", 0, &head_oid, NULL);
        if (branch)
                skip_prefix(branch, "refs/heads/", &branch);
+
+       init_diff_ui_defaults();
+       git_config(git_merge_config, NULL);
+
        if (!branch || is_null_oid(&head_oid))
                head_commit = NULL;
        else
                head_commit = lookup_commit_or_die(&head_oid, "HEAD");
 
-       init_diff_ui_defaults();
-       git_config(git_merge_config, NULL);
-
        if (branch_mergeoptions)
                parse_branch_merge_options(branch_mergeoptions);
        argc = parse_options(argc, argv, prefix, builtin_merge_options,
@@ -1211,7 +1214,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                        usage_msg_opt(_("--abort expects no arguments"),
                              builtin_merge_usage, builtin_merge_options);
 
-               if (!file_exists(git_path_merge_head()))
+               if (!file_exists(git_path_merge_head(the_repository)))
                        die(_("There is no merge to abort (MERGE_HEAD missing)."));
 
                /* Invoke 'git reset --merge' */
@@ -1227,7 +1230,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                        usage_msg_opt(_("--continue expects no arguments"),
                              builtin_merge_usage, builtin_merge_options);
 
-               if (!file_exists(git_path_merge_head()))
+               if (!file_exists(git_path_merge_head(the_repository)))
                        die(_("There is no merge in progress (MERGE_HEAD missing)."));
 
                /* Invoke 'git commit' */
@@ -1238,7 +1241,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
        if (read_cache_unmerged())
                die_resolve_conflict("merge");
 
-       if (file_exists(git_path_merge_head())) {
+       if (file_exists(git_path_merge_head(the_repository))) {
                /*
                 * There is no unmerged entry, don't advise 'git
                 * add/rm <file>', just 'git commit'.
@@ -1249,7 +1252,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                else
                        die(_("You have not concluded your merge (MERGE_HEAD exists)."));
        }
-       if (file_exists(git_path_cherry_pick_head())) {
+       if (file_exists(git_path_cherry_pick_head(the_repository))) {
                if (advice_resolve_conflict)
                        die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
                            "Please, commit your changes before you merge."));
index 82a6e86..6fb7dc8 100644 (file)
@@ -1,6 +1,7 @@
 #include "builtin.h"
 #include "tag.h"
 #include "replace-object.h"
+#include "object-store.h"
 
 /*
  * A signature file has a very simple fixed format: four lines
index bb76b46..2dc4ad6 100644 (file)
@@ -7,6 +7,7 @@
 #include "quote.h"
 #include "tree.h"
 #include "parse-options.h"
+#include "object-store.h"
 
 static struct treeent {
        unsigned mode;
index 387ddf8..0eb4403 100644 (file)
@@ -6,6 +6,7 @@
 #include "refs.h"
 #include "parse-options.h"
 #include "sha1-lookup.h"
+#include "commit-slab.h"
 
 #define CUTOFF_DATE_SLOP 86400 /* one day */
 
@@ -17,11 +18,26 @@ typedef struct rev_name {
        int from_tag;
 } rev_name;
 
+define_commit_slab(commit_rev_name, struct rev_name *);
+
 static timestamp_t cutoff = TIME_MAX;
+static struct commit_rev_name rev_names;
 
 /* How many generations are maximally preferred over _one_ merge traversal? */
 #define MERGE_TRAVERSAL_WEIGHT 65535
 
+static struct rev_name *get_commit_rev_name(struct commit *commit)
+{
+       struct rev_name **slot = commit_rev_name_peek(&rev_names, commit);
+
+       return slot ? *slot : NULL;
+}
+
+static void set_commit_rev_name(struct commit *commit, struct rev_name *name)
+{
+       *commit_rev_name_at(&rev_names, commit) = name;
+}
+
 static int is_better_name(struct rev_name *name,
                          const char *tip_name,
                          timestamp_t taggerdate,
@@ -65,7 +81,7 @@ static void name_rev(struct commit *commit,
                int generation, int distance, int from_tag,
                int deref)
 {
-       struct rev_name *name = (struct rev_name *)commit->util;
+       struct rev_name *name = get_commit_rev_name(commit);
        struct commit_list *parents;
        int parent_number = 1;
        char *to_free = NULL;
@@ -84,7 +100,7 @@ static void name_rev(struct commit *commit,
 
        if (name == NULL) {
                name = xmalloc(sizeof(rev_name));
-               commit->util = name;
+               set_commit_rev_name(commit, name);
                goto copy_data;
        } else if (is_better_name(name, tip_name, taggerdate,
                                  generation, distance, from_tag)) {
@@ -296,7 +312,7 @@ static const char *get_rev_name(const struct object *o, struct strbuf *buf)
        if (o->type != OBJ_COMMIT)
                return get_exact_ref_match(o);
        c = (struct commit *) o;
-       n = c->util;
+       n = get_commit_rev_name(c);
        if (!n)
                return NULL;
 
@@ -413,6 +429,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
                OPT_END(),
        };
 
+       init_commit_rev_name(&rev_names);
        git_config(git_default_config, NULL);
        argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
        if (all + transform_stdin + !!argc > 1) {
index 6981e2d..a0a1840 100644 (file)
@@ -11,6 +11,7 @@
 #include "config.h"
 #include "builtin.h"
 #include "notes.h"
+#include "object-store.h"
 #include "blob.h"
 #include "pretty.h"
 #include "refs.h"
index 71056d8..ebc8cef 100644 (file)
@@ -2929,11 +2929,13 @@ static int pack_options_allow_reuse(void)
 
 static int get_object_list_from_bitmap(struct rev_info *revs)
 {
-       if (prepare_bitmap_walk(revs) < 0)
+       struct bitmap_index *bitmap_git;
+       if (!(bitmap_git = prepare_bitmap_walk(revs)))
                return -1;
 
        if (pack_options_allow_reuse() &&
            !reuse_partial_packfile_from_bitmap(
+                       bitmap_git,
                        &reuse_packfile,
                        &reuse_packfile_objects,
                        &reuse_packfile_offset)) {
@@ -2942,7 +2944,8 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
                display_progress(progress_state, nr_result);
        }
 
-       traverse_bitmap_commit_list(&add_object_entry_from_bitmap);
+       traverse_bitmap_commit_list(bitmap_git, &add_object_entry_from_bitmap);
+       free_bitmap_index(bitmap_git);
        return 0;
 }
 
@@ -2969,7 +2972,7 @@ static void get_object_list(int ac, const char **av)
        setup_revisions(ac, av, &revs, NULL);
 
        /* make sure shallows are read */
-       is_repository_shallow();
+       is_repository_shallow(the_repository);
 
        while (fgets(line, sizeof(line), stdin) != NULL) {
                int len = strlen(line);
@@ -2987,7 +2990,7 @@ static void get_object_list(int ac, const char **av)
                                struct object_id oid;
                                if (get_oid_hex(line + 10, &oid))
                                        die("not an SHA-1 '%s'", line + 10);
-                               register_shallow(&oid);
+                               register_shallow(the_repository, &oid);
                                use_bitmap_index = 0;
                                continue;
                        }
@@ -3299,7 +3302,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                use_bitmap_index = use_bitmap_index_default;
 
        /* "hard" reasons not to use bitmaps; these just won't work at all */
-       if (!use_internal_rev_list || (!pack_to_stdout && write_bitmap_index) || is_repository_shallow())
+       if (!use_internal_rev_list || (!pack_to_stdout && write_bitmap_index) || is_repository_shallow(the_repository))
                use_bitmap_index = 0;
 
        if (pack_to_stdout || !rev_list_all)
index 518ffbe..70ec35a 100644 (file)
@@ -6,6 +6,7 @@
 #include "reachable.h"
 #include "parse-options.h"
 #include "progress.h"
+#include "object-store.h"
 
 static const char * const prune_usage[] = {
        N_("git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]"),
@@ -159,7 +160,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
        remove_temporary_files(s);
        free(s);
 
-       if (is_repository_shallow())
+       if (is_repository_shallow(the_repository))
                prune_shallow(show_only);
 
        return 0;
index 49cc3be..7197b22 100644 (file)
@@ -356,7 +356,7 @@ static int git_pull_config(const char *var, const char *value, void *cb)
  */
 static void get_merge_heads(struct oid_array *merge_heads)
 {
-       const char *filename = git_path_fetch_head();
+       const char *filename = git_path_fetch_head(the_repository);
        FILE *fp;
        struct strbuf sb = STRBUF_INIT;
        struct object_id oid;
@@ -684,7 +684,7 @@ static const char *get_tracking_branch(const char *remote, const char *refspec)
        const char *spec_src;
        const char *merge_branch;
 
-       refspec_item_init(&spec, refspec, REFSPEC_FETCH);
+       refspec_item_init_or_die(&spec, refspec, REFSPEC_FETCH);
        spec_src = spec.src;
        if (!*spec_src || !strcmp(spec_src, "HEAD"))
                spec_src = "HEAD";
@@ -864,7 +864,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
        if (read_cache_unmerged())
                die_resolve_conflict("pull");
 
-       if (file_exists(git_path_merge_head()))
+       if (file_exists(git_path_merge_head(the_repository)))
                die_conclude_merge();
 
        if (get_oid("HEAD", &orig_head))
index 68d36e0..f1c5d07 100644 (file)
@@ -25,6 +25,7 @@
 #include "tmp-objdir.h"
 #include "oidset.h"
 #include "packfile.h"
+#include "object-store.h"
 #include "protocol.h"
 
 static const char * const receive_pack_usage[] = {
@@ -629,8 +630,6 @@ static void prepare_push_cert_sha1(struct child_process *proc)
                return;
 
        if (!already_done) {
-               struct strbuf gpg_output = STRBUF_INIT;
-               struct strbuf gpg_status = STRBUF_INIT;
                int bogs /* beginning_of_gpg_sig */;
 
                already_done = 1;
@@ -639,22 +638,11 @@ static void prepare_push_cert_sha1(struct child_process *proc)
                        oidclr(&push_cert_oid);
 
                memset(&sigcheck, '\0', sizeof(sigcheck));
-               sigcheck.result = 'N';
 
                bogs = parse_signature(push_cert.buf, push_cert.len);
-               if (verify_signed_buffer(push_cert.buf, bogs,
-                                        push_cert.buf + bogs, push_cert.len - bogs,
-                                        &gpg_output, &gpg_status) < 0) {
-                       ; /* error running gpg */
-               } else {
-                       sigcheck.payload = push_cert.buf;
-                       sigcheck.gpg_output = gpg_output.buf;
-                       sigcheck.gpg_status = gpg_status.buf;
-                       parse_gpg_output(&sigcheck);
-               }
+               check_signature(push_cert.buf, bogs, push_cert.buf + bogs,
+                               push_cert.len - bogs, &sigcheck);
 
-               strbuf_release(&gpg_output);
-               strbuf_release(&gpg_status);
                nonce_status = check_nonce(push_cert.buf, bogs);
        }
        if (!is_null_oid(&push_cert_oid)) {
@@ -905,7 +893,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
         * not lose these new roots..
         */
        for (i = 0; i < extra.nr; i++)
-               register_shallow(&extra.oid[i]);
+               register_shallow(the_repository, &extra.oid[i]);
 
        si->shallow_ref[cmd->index] = 0;
        oid_array_clear(&extra);
index a48984d..0091192 100644 (file)
@@ -1,6 +1,7 @@
 #include "builtin.h"
 #include "config.h"
 #include "lockfile.h"
+#include "object-store.h"
 #include "commit.h"
 #include "refs.h"
 #include "dir.h"
index 1a82d85..c74ee88 100644 (file)
@@ -8,6 +8,7 @@
 #include "run-command.h"
 #include "refs.h"
 #include "refspec.h"
+#include "object-store.h"
 #include "argv-array.h"
 
 static const char * const builtin_remote_usage[] = {
index 6da2411..deabda2 100644 (file)
@@ -487,7 +487,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle)
 
 static int convert_graft_file(int force)
 {
-       const char *graft_file = get_graft_file();
+       const char *graft_file = get_graft_file(the_repository);
        FILE *fp = fopen_or_warn(graft_file, "r");
        struct strbuf buf = STRBUF_INIT, err = STRBUF_INIT;
        struct argv_array args = ARGV_ARRAY_INIT;
index a862c70..ffe41c9 100644 (file)
@@ -39,7 +39,7 @@ static const char *reset_type_names[] = {
 
 static inline int is_merge(void)
 {
-       return !access(git_path_merge_head(), F_OK);
+       return !access(git_path_merge_head(the_repository), F_OK);
 }
 
 static int reset_index(const struct object_id *oid, int reset_type, int quiet)
index fadd3ec..6fcb0ff 100644 (file)
@@ -6,6 +6,7 @@
 #include "list-objects.h"
 #include "list-objects-filter.h"
 #include "list-objects-filter-options.h"
+#include "object-store.h"
 #include "pack.h"
 #include "pack-bitmap.h"
 #include "builtin.h"
@@ -16,6 +17,7 @@
 #include "reflog-walk.h"
 #include "oidset.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static const char rev_list_usage[] =
 "git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
@@ -514,17 +516,21 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
                if (revs.count && !revs.left_right && !revs.cherry_mark) {
                        uint32_t commit_count;
                        int max_count = revs.max_count;
-                       if (!prepare_bitmap_walk(&revs)) {
-                               count_bitmap_commit_list(&commit_count, NULL, NULL, NULL);
+                       struct bitmap_index *bitmap_git;
+                       if ((bitmap_git = prepare_bitmap_walk(&revs))) {
+                               count_bitmap_commit_list(bitmap_git, &commit_count, NULL, NULL, NULL);
                                if (max_count >= 0 && max_count < commit_count)
                                        commit_count = max_count;
                                printf("%d\n", commit_count);
+                               free_bitmap_index(bitmap_git);
                                return 0;
                        }
                } else if (revs.max_count < 0 &&
                           revs.tag_objects && revs.tree_objects && revs.blob_objects) {
-                       if (!prepare_bitmap_walk(&revs)) {
-                               traverse_bitmap_commit_list(&show_object_fast);
+                       struct bitmap_index *bitmap_git;
+                       if ((bitmap_git = prepare_bitmap_walk(&revs))) {
+                               traverse_bitmap_commit_list(bitmap_git, &show_object_fast);
+                               free_bitmap_index(bitmap_git);
                                return 0;
                        }
                }
index 4f49e96..2a6cb29 100644 (file)
@@ -883,7 +883,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                continue;
                        }
                        if (!strcmp(arg, "--is-shallow-repository")) {
-                               printf("%s\n", is_repository_shallow() ? "true"
+                               printf("%s\n",
+                                               is_repository_shallow(the_repository) ? "true"
                                                : "false");
                                continue;
                        }
index 4923b10..42fd8d1 100644 (file)
@@ -121,7 +121,7 @@ static int send_pack_config(const char *k, const char *v, void *cb)
                        }
                }
        }
-       return 0;
+       return git_default_config(k, v, cb);
 }
 
 int cmd_send_pack(int argc, const char **argv, const char *prefix)
index 6c2148b..f2e985c 100644 (file)
@@ -7,6 +7,7 @@
 #include "argv-array.h"
 #include "parse-options.h"
 #include "dir.h"
+#include "commit-slab.h"
 
 static const char* show_branch_usage[] = {
     N_("git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
@@ -21,6 +22,11 @@ static int showbranch_use_color = -1;
 
 static struct argv_array default_args = ARGV_ARRAY_INIT;
 
+/*
+ * TODO: convert this use of commit->object.flags to commit-slab
+ * instead to store a pointer to ref name directly. Then use the same
+ * UNINTERESTING definition from revision.h here.
+ */
 #define UNINTERESTING  01
 
 #define REV_SHIFT       2
@@ -59,15 +65,27 @@ struct commit_name {
        int generation; /* how many parents away from head_name */
 };
 
+define_commit_slab(commit_name_slab, struct commit_name *);
+static struct commit_name_slab name_slab;
+
+static struct commit_name *commit_to_name(struct commit *commit)
+{
+       return *commit_name_slab_at(&name_slab, commit);
+}
+
+
 /* Name the commit as nth generation ancestor of head_name;
  * we count only the first-parent relationship for naming purposes.
  */
 static void name_commit(struct commit *commit, const char *head_name, int nth)
 {
        struct commit_name *name;
-       if (!commit->util)
-               commit->util = xmalloc(sizeof(struct commit_name));
-       name = commit->util;
+
+       name = *commit_name_slab_at(&name_slab, commit);
+       if (!name) {
+               name = xmalloc(sizeof(*name));
+               *commit_name_slab_at(&name_slab, commit) = name;
+       }
        name->head_name = head_name;
        name->generation = nth;
 }
@@ -79,8 +97,8 @@ static void name_commit(struct commit *commit, const char *head_name, int nth)
  */
 static void name_parent(struct commit *commit, struct commit *parent)
 {
-       struct commit_name *commit_name = commit->util;
-       struct commit_name *parent_name = parent->util;
+       struct commit_name *commit_name = commit_to_name(commit);
+       struct commit_name *parent_name = commit_to_name(parent);
        if (!commit_name)
                return;
        if (!parent_name ||
@@ -94,12 +112,12 @@ static int name_first_parent_chain(struct commit *c)
        int i = 0;
        while (c) {
                struct commit *p;
-               if (!c->util)
+               if (!commit_to_name(c))
                        break;
                if (!c->parents)
                        break;
                p = c->parents->item;
-               if (!p->util) {
+               if (!commit_to_name(p)) {
                        name_parent(c, p);
                        i++;
                }
@@ -122,7 +140,7 @@ static void name_commits(struct commit_list *list,
        /* First give names to the given heads */
        for (cl = list; cl; cl = cl->next) {
                c = cl->item;
-               if (c->util)
+               if (commit_to_name(c))
                        continue;
                for (i = 0; i < num_rev; i++) {
                        if (rev[i] == c) {
@@ -148,9 +166,9 @@ static void name_commits(struct commit_list *list,
                        struct commit_name *n;
                        int nth;
                        c = cl->item;
-                       if (!c->util)
+                       if (!commit_to_name(c))
                                continue;
-                       n = c->util;
+                       n = commit_to_name(c);
                        parents = c->parents;
                        nth = 0;
                        while (parents) {
@@ -158,7 +176,7 @@ static void name_commits(struct commit_list *list,
                                struct strbuf newname = STRBUF_INIT;
                                parents = parents->next;
                                nth++;
-                               if (p->util)
+                               if (commit_to_name(p))
                                        continue;
                                switch (n->generation) {
                                case 0:
@@ -271,7 +289,7 @@ static void show_one_commit(struct commit *commit, int no_name)
 {
        struct strbuf pretty = STRBUF_INIT;
        const char *pretty_str = "(unavailable)";
-       struct commit_name *name = commit->util;
+       struct commit_name *name = commit_to_name(commit);
 
        if (commit->object.parsed) {
                pp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);
@@ -660,6 +678,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                OPT_END()
        };
 
+       init_commit_name_slab(&name_slab);
+
        git_config(git_show_branch_config, NULL);
 
        /* If nothing is specified, try the default first */
similarity index 96%
rename from show-index.c
rename to builtin/show-index.c
index 1ead41e..a6e6788 100644 (file)
@@ -1,10 +1,11 @@
+#include "builtin.h"
 #include "cache.h"
 #include "pack.h"
 
 static const char show_index_usage[] =
 "git show-index";
 
-int cmd_main(int argc, const char **argv)
+int cmd_show_index(int argc, const char **argv, const char *prefix)
 {
        int i;
        unsigned nr;
index f2eb1a7..2f13f13 100644 (file)
@@ -1,6 +1,7 @@
 #include "builtin.h"
 #include "cache.h"
 #include "refs.h"
+#include "object-store.h"
 #include "object.h"
 #include "tag.h"
 #include "string-list.h"
index bd250ca..a3c4564 100644 (file)
@@ -55,7 +55,7 @@ static char *get_default_remote(void)
 
 static int print_default_remote(int argc, const char **argv, const char *prefix)
 {
-       const char *remote;
+       char *remote;
 
        if (argc != 1)
                die(_("submodule--helper print-default-remote takes no arguments"));
@@ -64,6 +64,7 @@ static int print_default_remote(int argc, const char **argv, const char *prefix)
        if (remote)
                printf("%s\n", remote);
 
+       free(remote);
        return 0;
 }
 
@@ -440,6 +441,149 @@ static void for_each_listed_submodule(const struct module_list *list,
                fn(list->entries[i], cb_data);
 }
 
+struct cb_foreach {
+       int argc;
+       const char **argv;
+       const char *prefix;
+       int quiet;
+       int recursive;
+};
+#define CB_FOREACH_INIT { 0 }
+
+static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
+                                      void *cb_data)
+{
+       struct cb_foreach *info = cb_data;
+       const char *path = list_item->name;
+       const struct object_id *ce_oid = &list_item->oid;
+
+       const struct submodule *sub;
+       struct child_process cp = CHILD_PROCESS_INIT;
+       char *displaypath;
+
+       displaypath = get_submodule_displaypath(path, info->prefix);
+
+       sub = submodule_from_path(the_repository, &null_oid, path);
+
+       if (!sub)
+               die(_("No url found for submodule path '%s' in .gitmodules"),
+                       displaypath);
+
+       if (!is_submodule_populated_gently(path, NULL))
+               goto cleanup;
+
+       prepare_submodule_repo_env(&cp.env_array);
+
+       /*
+        * For the purpose of executing <command> in the submodule,
+        * separate shell is used for the purpose of running the
+        * child process.
+        */
+       cp.use_shell = 1;
+       cp.dir = path;
+
+       /*
+        * NEEDSWORK: the command currently has access to the variables $name,
+        * $sm_path, $displaypath, $sha1 and $toplevel only when the command
+        * contains a single argument. This is done for maintaining a faithful
+        * translation from shell script.
+        */
+       if (info->argc == 1) {
+               char *toplevel = xgetcwd();
+               struct strbuf sb = STRBUF_INIT;
+
+               argv_array_pushf(&cp.env_array, "name=%s", sub->name);
+               argv_array_pushf(&cp.env_array, "sm_path=%s", path);
+               argv_array_pushf(&cp.env_array, "displaypath=%s", displaypath);
+               argv_array_pushf(&cp.env_array, "sha1=%s",
+                               oid_to_hex(ce_oid));
+               argv_array_pushf(&cp.env_array, "toplevel=%s", toplevel);
+
+               /*
+                * Since the path variable was accessible from the script
+                * before porting, it is also made available after porting.
+                * The environment variable "PATH" has a very special purpose
+                * on windows. And since environment variables are
+                * case-insensitive in windows, it interferes with the
+                * existing PATH variable. Hence, to avoid that, we expose
+                * path via the args argv_array and not via env_array.
+                */
+               sq_quote_buf(&sb, path);
+               argv_array_pushf(&cp.args, "path=%s; %s",
+                                sb.buf, info->argv[0]);
+               strbuf_release(&sb);
+               free(toplevel);
+       } else {
+               argv_array_pushv(&cp.args, info->argv);
+       }
+
+       if (!info->quiet)
+               printf(_("Entering '%s'\n"), displaypath);
+
+       if (info->argv[0] && run_command(&cp))
+               die(_("run_command returned non-zero status for %s\n."),
+                       displaypath);
+
+       if (info->recursive) {
+               struct child_process cpr = CHILD_PROCESS_INIT;
+
+               cpr.git_cmd = 1;
+               cpr.dir = path;
+               prepare_submodule_repo_env(&cpr.env_array);
+
+               argv_array_pushl(&cpr.args, "--super-prefix", NULL);
+               argv_array_pushf(&cpr.args, "%s/", displaypath);
+               argv_array_pushl(&cpr.args, "submodule--helper", "foreach", "--recursive",
+                               NULL);
+
+               if (info->quiet)
+                       argv_array_push(&cpr.args, "--quiet");
+
+               argv_array_pushv(&cpr.args, info->argv);
+
+               if (run_command(&cpr))
+                       die(_("run_command returned non-zero status while"
+                               "recursing in the nested submodules of %s\n."),
+                               displaypath);
+       }
+
+cleanup:
+       free(displaypath);
+}
+
+static int module_foreach(int argc, const char **argv, const char *prefix)
+{
+       struct cb_foreach info = CB_FOREACH_INIT;
+       struct pathspec pathspec;
+       struct module_list list = MODULE_LIST_INIT;
+
+       struct option module_foreach_options[] = {
+               OPT__QUIET(&info.quiet, N_("Suppress output of entering each submodule command")),
+               OPT_BOOL(0, "recursive", &info.recursive,
+                        N_("Recurse into nested submodules")),
+               OPT_END()
+       };
+
+       const char *const git_submodule_helper_usage[] = {
+               N_("git submodule--helper foreach [--quiet] [--recursive] <command>"),
+               NULL
+       };
+
+       argc = parse_options(argc, argv, prefix, module_foreach_options,
+                            git_submodule_helper_usage, PARSE_OPT_KEEP_UNKNOWN);
+
+       if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
+               return 1;
+
+       info.argc = argc;
+       info.argv = argv;
+       info.prefix = prefix;
+
+       for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);
+
+       return 0;
+}
+
 struct init_cb {
        const char *prefix;
        unsigned int flags;
@@ -980,6 +1124,8 @@ static void deinit_submodule(const char *path, const char *prefix,
                if (!(flags & OPT_QUIET))
                        printf(format, displaypath);
 
+               submodule_unset_core_worktree(sub);
+
                strbuf_release(&sb_rm);
        }
 
@@ -1562,8 +1708,8 @@ static int update_clone_task_finished(int result,
        return 0;
 }
 
-static int gitmodules_update_clone_config(const char *var, const char *value,
-                                         void *cb)
+static int git_update_clone_config(const char *var, const char *value,
+                                  void *cb)
 {
        int *max_jobs = cb;
        if (!strcmp(var, "submodule.fetchjobs"))
@@ -1613,8 +1759,8 @@ static int update_clone(int argc, const char **argv, const char *prefix)
        };
        suc.prefix = prefix;
 
-       config_from_gitmodules(gitmodules_update_clone_config, &max_jobs);
-       git_config(gitmodules_update_clone_config, &max_jobs);
+       update_clone_config_from_gitmodules(&max_jobs);
+       git_config(git_update_clone_config, &max_jobs);
 
        argc = parse_options(argc, argv, prefix, module_update_clone_options,
                             git_submodule_helper_usage, 0);
@@ -1860,6 +2006,29 @@ static int check_name(int argc, const char **argv, const char *prefix)
        return 0;
 }
 
+static int connect_gitdir_workingtree(int argc, const char **argv, const char *prefix)
+{
+       struct strbuf sb = STRBUF_INIT;
+       const char *name, *path;
+       char *sm_gitdir;
+
+       if (argc != 3)
+               BUG("submodule--helper connect-gitdir-workingtree <name> <path>");
+
+       name = argv[1];
+       path = argv[2];
+
+       strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name);
+       sm_gitdir = absolute_pathdup(sb.buf);
+
+       connect_work_tree_and_git_dir(path, sm_gitdir, 0);
+
+       strbuf_release(&sb);
+       free(sm_gitdir);
+
+       return 0;
+}
+
 #define SUPPORT_SUPER_PREFIX (1<<0)
 
 struct cmd_struct {
@@ -1873,9 +2042,11 @@ static struct cmd_struct commands[] = {
        {"name", module_name, 0},
        {"clone", module_clone, 0},
        {"update-clone", update_clone, 0},
+       {"connect-gitdir-workingtree", connect_gitdir_workingtree, 0},
        {"relative-path", resolve_relative_path, 0},
        {"resolve-relative-url", resolve_relative_url, 0},
        {"resolve-relative-url-test", resolve_relative_url_test, 0},
+       {"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
        {"init", module_init, SUPPORT_SUPER_PREFIX},
        {"status", module_status, SUPPORT_SUPER_PREFIX},
        {"print-default-remote", print_default_remote, 0},
index 5d0dd11..9919b03 100644 (file)
@@ -10,6 +10,7 @@
 #include "config.h"
 #include "builtin.h"
 #include "refs.h"
+#include "object-store.h"
 #include "tag.h"
 #include "run-command.h"
 #include "parse-options.h"
index 300eb59..5865222 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "config.h"
+#include "object-store.h"
 
 static char *create_temp_file(struct object_id *oid)
 {
index 6e81ca8..cf585fc 100644 (file)
@@ -1,6 +1,7 @@
 #include "builtin.h"
 #include "cache.h"
 #include "config.h"
+#include "object-store.h"
 #include "object.h"
 #include "delta.h"
 #include "pack.h"
index 4b4714b..4fa3c0a 100644 (file)
@@ -311,11 +311,12 @@ static const char *parse_cmd_verify(struct ref_transaction *transaction,
 
 static const char *parse_cmd_option(struct strbuf *input, const char *next)
 {
-       if (!strncmp(next, "no-deref", 8) && next[8] == line_termination)
+       const char *rest;
+       if (skip_prefix(next, "no-deref", &rest) && *rest == line_termination)
                update_flags |= REF_NO_DEREF;
        else
                die("option unknown: %s", next);
-       return next + 8;
+       return rest;
 }
 
 static void update_refs_stdin(struct ref_transaction *transaction)
@@ -332,16 +333,16 @@ static void update_refs_stdin(struct ref_transaction *transaction)
                        die("empty command in input");
                else if (isspace(*next))
                        die("whitespace before command: %s", next);
-               else if (starts_with(next, "update "))
-                       next = parse_cmd_update(transaction, &input, next + 7);
-               else if (starts_with(next, "create "))
-                       next = parse_cmd_create(transaction, &input, next + 7);
-               else if (starts_with(next, "delete "))
-                       next = parse_cmd_delete(transaction, &input, next + 7);
-               else if (starts_with(next, "verify "))
-                       next = parse_cmd_verify(transaction, &input, next + 7);
-               else if (starts_with(next, "option "))
-                       next = parse_cmd_option(&input, next + 7);
+               else if (skip_prefix(next, "update ", &next))
+                       next = parse_cmd_update(transaction, &input, next);
+               else if (skip_prefix(next, "create ", &next))
+                       next = parse_cmd_create(transaction, &input, next);
+               else if (skip_prefix(next, "delete ", &next))
+                       next = parse_cmd_delete(transaction, &input, next);
+               else if (skip_prefix(next, "verify ", &next))
+                       next = parse_cmd_verify(transaction, &input, next);
+               else if (skip_prefix(next, "option ", &next))
+                       next = parse_cmd_option(&input, next);
                else
                        die("unknown command: %s", next);
 
index dcdaada..f6922da 100644 (file)
@@ -8,6 +8,7 @@
 #include "cache.h"
 #include "config.h"
 #include "builtin.h"
+#include "object-store.h"
 #include "commit.h"
 #include "run-command.h"
 #include <signal.h>
index b7e131c..9f3b644 100644 (file)
@@ -8,6 +8,7 @@
 #include "pack.h"
 #include "strbuf.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static struct bulk_checkin_state {
        unsigned plugged:1;
index 160bbfd..ba18e25 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "lockfile.h"
 #include "bundle.h"
+#include "object-store.h"
 #include "object.h"
 #include "commit.h"
 #include "diff.h"
index 2566382..6b46711 100644 (file)
@@ -3,6 +3,7 @@
 #include "tree.h"
 #include "tree-walk.h"
 #include "cache-tree.h"
+#include "object-store.h"
 
 #ifndef DEBUG
 #define DEBUG 0
diff --git a/cache.h b/cache.h
index 89a107a..8b44765 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -484,7 +484,7 @@ extern const char *get_git_dir(void);
 extern const char *get_git_common_dir(void);
 extern char *get_object_directory(void);
 extern char *get_index_file(void);
-extern char *get_graft_file(void);
+extern char *get_graft_file(struct repository *r);
 extern void set_git_dir(const char *path);
 extern int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
 extern int get_common_dir(struct strbuf *sb, const char *gitdir);
@@ -1192,32 +1192,6 @@ extern char *xdg_config_home(const char *filename);
  */
 extern char *xdg_cache_home(const char *filename);
 
-extern void *read_object_file_extended(const struct object_id *oid,
-                                      enum object_type *type,
-                                      unsigned long *size, int lookup_replace);
-static inline void *read_object_file(const struct object_id *oid, enum object_type *type, unsigned long *size)
-{
-       return read_object_file_extended(oid, type, size, 1);
-}
-
-/* Read and unpack an object file into memory, write memory to an object file */
-int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);
-
-extern int hash_object_file(const void *buf, unsigned long len,
-                           const char *type, struct object_id *oid);
-
-extern int write_object_file(const void *buf, unsigned long len,
-                            const char *type, struct object_id *oid);
-
-extern int hash_object_file_literally(const void *buf, unsigned long len,
-                                     const char *type, struct object_id *oid,
-                                     unsigned flags);
-
-extern int pretend_object_file(void *, unsigned long, enum object_type,
-                              struct object_id *oid);
-
-extern int force_object_loose(const struct object_id *oid, time_t mtime);
-
 extern int git_open_cloexec(const char *name, int flags);
 #define git_open(name) git_open_cloexec(name, O_RDONLY)
 extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
@@ -1227,43 +1201,6 @@ extern int check_object_signature(const struct object_id *oid, void *buf, unsign
 
 extern int finalize_object_file(const char *tmpfile, const char *filename);
 
-/*
- * Open the loose object at path, check its hash, and return the contents,
- * type, and size. If the object is a blob, then "contents" may return NULL,
- * to allow streaming of large blobs.
- *
- * Returns 0 on success, negative on error (details may be written to stderr).
- */
-int read_loose_object(const char *path,
-                     const struct object_id *expected_oid,
-                     enum object_type *type,
-                     unsigned long *size,
-                     void **contents);
-
-/*
- * Convenience for sha1_object_info_extended() with a NULL struct
- * object_info. OBJECT_INFO_SKIP_CACHED is automatically set; pass
- * nonzero flags to also set other flags.
- */
-extern int has_sha1_file_with_flags(const unsigned char *sha1, int flags);
-static inline int has_sha1_file(const unsigned char *sha1)
-{
-       return has_sha1_file_with_flags(sha1, 0);
-}
-
-/* Same as the above, except for struct object_id. */
-extern int has_object_file(const struct object_id *oid);
-extern int has_object_file_with_flags(const struct object_id *oid, int flags);
-
-/*
- * Return true iff an alternate object database has a loose object
- * with the specified name.  This function does not respect replace
- * references.
- */
-extern int has_loose_object_nonlocal(const struct object_id *oid);
-
-extern void assert_oid_type(const struct object_id *oid, enum object_type expect);
-
 /* Helper to check and "touch" a file */
 extern int check_and_freshen_file(const char *fn, int freshen);
 
@@ -1631,60 +1568,6 @@ int for_each_loose_file_in_objdir_buf(struct strbuf *path,
 #define FOR_EACH_OBJECT_LOCAL_ONLY 0x1
 extern int for_each_loose_object(each_loose_object_fn, void *, unsigned flags);
 
-struct object_info {
-       /* Request */
-       enum object_type *typep;
-       unsigned long *sizep;
-       off_t *disk_sizep;
-       unsigned char *delta_base_sha1;
-       struct strbuf *type_name;
-       void **contentp;
-
-       /* Response */
-       enum {
-               OI_CACHED,
-               OI_LOOSE,
-               OI_PACKED,
-               OI_DBCACHED
-       } whence;
-       union {
-               /*
-                * struct {
-                *      ... Nothing to expose in this case
-                * } cached;
-                * struct {
-                *      ... Nothing to expose in this case
-                * } loose;
-                */
-               struct {
-                       struct packed_git *pack;
-                       off_t offset;
-                       unsigned int is_delta;
-               } packed;
-       } u;
-};
-
-/*
- * Initializer for a "struct object_info" that wants no items. You may
- * also memset() the memory to all-zeroes.
- */
-#define OBJECT_INFO_INIT {NULL}
-
-/* Invoke lookup_replace_object() on the given hash */
-#define OBJECT_INFO_LOOKUP_REPLACE 1
-/* Allow reading from a loose object file of unknown/bogus type */
-#define OBJECT_INFO_ALLOW_UNKNOWN_TYPE 2
-/* Do not check cached storage */
-#define OBJECT_INFO_SKIP_CACHED 4
-/* Do not retry packed storage after checking packed and loose storage */
-#define OBJECT_INFO_QUICK 8
-/* Do not check loose object */
-#define OBJECT_INFO_IGNORE_LOOSE 16
-
-int oid_object_info_extended(struct repository *r,
-                            const struct object_id *,
-                            struct object_info *, 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.
@@ -1770,15 +1653,6 @@ extern const char *excludes_file;
 int decode_85(char *dst, const char *line, int linelen);
 void encode_85(char *buf, const unsigned char *data, int bytes);
 
-/* alloc.c */
-extern void *alloc_blob_node(void);
-extern void *alloc_tree_node(void);
-extern void *alloc_commit_node(void);
-extern void *alloc_tag_node(void);
-extern void *alloc_object_node(void);
-extern void alloc_report(void);
-extern unsigned int alloc_commit_index(void);
-
 /* pkt-line.c */
 void packet_trace_identity(const char *prog);
 
index 2ef4959..de7695e 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "object-store.h"
 #include "commit.h"
 #include "blob.h"
 #include "diff.h"
index 4c61270..b63a1fc 100644 (file)
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "config.h"
+#include "dir.h"
 #include "git-compat-util.h"
 #include "lockfile.h"
 #include "pack.h"
@@ -248,6 +249,13 @@ static struct commit_list **insert_parent_or_die(struct commit_graph *g,
        return &commit_list_insert(c, pptr)->next;
 }
 
+static void fill_commit_graph_info(struct commit *item, struct commit_graph *g, uint32_t pos)
+{
+       const unsigned char *commit_data = g->chunk_commit_data + GRAPH_DATA_WIDTH * pos;
+       item->graph_pos = pos;
+       item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
+}
+
 static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uint32_t pos)
 {
        uint32_t edge_value;
@@ -265,6 +273,8 @@ static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uin
        date_low = get_be32(commit_data + g->hash_len + 12);
        item->date = (timestamp_t)((date_high << 32) | date_low);
 
+       item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
+
        pptr = &item->parents;
 
        edge_value = get_be32(commit_data + g->hash_len);
@@ -293,31 +303,40 @@ static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uin
        return 1;
 }
 
+static int find_commit_in_graph(struct commit *item, struct commit_graph *g, uint32_t *pos)
+{
+       if (item->graph_pos != COMMIT_NOT_FROM_GRAPH) {
+               *pos = item->graph_pos;
+               return 1;
+       } else {
+               return bsearch_graph(g, &(item->object.oid), pos);
+       }
+}
+
 int parse_commit_in_graph(struct commit *item)
 {
+       uint32_t pos;
+
        if (!core_commit_graph)
                return 0;
        if (item->object.parsed)
                return 1;
-
        prepare_commit_graph();
-       if (commit_graph) {
-               uint32_t pos;
-               int found;
-               if (item->graph_pos != COMMIT_NOT_FROM_GRAPH) {
-                       pos = item->graph_pos;
-                       found = 1;
-               } else {
-                       found = bsearch_graph(commit_graph, &(item->object.oid), &pos);
-               }
-
-               if (found)
-                       return fill_commit_in_graph(item, commit_graph, pos);
-       }
-
+       if (commit_graph && find_commit_in_graph(item, commit_graph, &pos))
+               return fill_commit_in_graph(item, commit_graph, pos);
        return 0;
 }
 
+void load_commit_graph_info(struct commit *item)
+{
+       uint32_t pos;
+       if (!core_commit_graph)
+               return;
+       prepare_commit_graph();
+       if (commit_graph && find_commit_in_graph(item, commit_graph, &pos))
+               fill_commit_graph_info(item, commit_graph, pos);
+}
+
 static struct tree *load_tree_for_commit(struct commit_graph *g, struct commit *c)
 {
        struct object_id oid;
@@ -440,6 +459,8 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
                else
                        packedDate[0] = 0;
 
+               packedDate[0] |= htonl((*list)->generation << 2);
+
                packedDate[1] = htonl((*list)->date);
                hashwrite(f, packedDate, 8);
 
@@ -572,6 +593,45 @@ static void close_reachable(struct packed_oid_list *oids)
        }
 }
 
+static void compute_generation_numbers(struct packed_commit_list* commits)
+{
+       int i;
+       struct commit_list *list = NULL;
+
+       for (i = 0; i < commits->nr; i++) {
+               if (commits->list[i]->generation != GENERATION_NUMBER_INFINITY &&
+                   commits->list[i]->generation != GENERATION_NUMBER_ZERO)
+                       continue;
+
+               commit_list_insert(commits->list[i], &list);
+               while (list) {
+                       struct commit *current = list->item;
+                       struct commit_list *parent;
+                       int all_parents_computed = 1;
+                       uint32_t max_generation = 0;
+
+                       for (parent = current->parents; parent; parent = parent->next) {
+                               if (parent->item->generation == GENERATION_NUMBER_INFINITY ||
+                                   parent->item->generation == GENERATION_NUMBER_ZERO) {
+                                       all_parents_computed = 0;
+                                       commit_list_insert(parent->item, &list);
+                                       break;
+                               } else if (parent->item->generation > max_generation) {
+                                       max_generation = parent->item->generation;
+                               }
+                       }
+
+                       if (all_parents_computed) {
+                               current->generation = max_generation + 1;
+                               pop_commit(&list);
+
+                               if (current->generation > GENERATION_NUMBER_MAX)
+                                       current->generation = GENERATION_NUMBER_MAX;
+                       }
+               }
+       }
+}
+
 void write_commit_graph(const char *obj_dir,
                        const char **pack_indexes,
                        int nr_packs,
@@ -584,7 +644,6 @@ void write_commit_graph(const char *obj_dir,
        struct hashfile *f;
        uint32_t i, count_distinct = 0;
        char *graph_name;
-       int fd;
        struct lock_file lk = LOCK_INIT;
        uint32_t chunk_ids[5];
        uint64_t chunk_offsets[5];
@@ -695,24 +754,14 @@ void write_commit_graph(const char *obj_dir,
        if (commits.nr >= GRAPH_PARENT_MISSING)
                die(_("too many commits to write graph"));
 
-       graph_name = get_commit_graph_filename(obj_dir);
-       fd = hold_lock_file_for_update(&lk, graph_name, 0);
-
-       if (fd < 0) {
-               struct strbuf folder = STRBUF_INIT;
-               strbuf_addstr(&folder, graph_name);
-               strbuf_setlen(&folder, strrchr(folder.buf, '/') - folder.buf);
-
-               if (mkdir(folder.buf, 0777) < 0)
-                       die_errno(_("cannot mkdir %s"), folder.buf);
-               strbuf_release(&folder);
-
-               fd = hold_lock_file_for_update(&lk, graph_name, LOCK_DIE_ON_ERROR);
+       compute_generation_numbers(&commits);
 
-               if (fd < 0)
-                       die_errno("unable to create '%s'", graph_name);
-       }
+       graph_name = get_commit_graph_filename(obj_dir);
+       if (safe_create_leading_directories(graph_name))
+               die_errno(_("unable to create leading directories of %s"),
+                         graph_name);
 
+       hold_lock_file_for_update(&lk, graph_name, LOCK_DIE_ON_ERROR);
        f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
 
        hashwrite_be32(f, GRAPH_SIGNATURE);
index 260a468..96cccb1 100644 (file)
@@ -17,6 +17,14 @@ char *get_commit_graph_filename(const char *obj_dir);
  */
 int parse_commit_in_graph(struct commit *item);
 
+/*
+ * It is possible that we loaded commit contents from the commit buffer,
+ * but we also want to ensure the commit-graph content is correctly
+ * checked and filled. Fill the graph_pos and generation members of
+ * the given commit.
+ */
+void load_commit_graph_info(struct commit *item);
+
 struct tree *get_commit_tree_in_graph(const struct commit *c);
 
 struct commit_graph {
diff --git a/commit-slab-decl.h b/commit-slab-decl.h
new file mode 100644 (file)
index 0000000..adc7b46
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef COMMIT_SLAB_HDR_H
+#define COMMIT_SLAB_HDR_H
+
+/* allocate ~512kB at once, allowing for malloc overhead */
+#ifndef COMMIT_SLAB_SIZE
+#define COMMIT_SLAB_SIZE (512*1024-32)
+#endif
+
+#define declare_commit_slab(slabname, elemtype)                        \
+                                                                       \
+struct slabname {                                                      \
+       unsigned slab_size;                                             \
+       unsigned stride;                                                \
+       unsigned slab_count;                                            \
+       elemtype **slab;                                                \
+}
+
+/*
+ * Statically initialize a commit slab named "var". Note that this
+ * evaluates "stride" multiple times! Example:
+ *
+ *   struct indegree indegrees = COMMIT_SLAB_INIT(1, indegrees);
+ *
+ */
+#define COMMIT_SLAB_INIT(stride, var) { \
+       COMMIT_SLAB_SIZE / sizeof(**((var).slab)) / (stride), \
+       (stride), 0, NULL \
+}
+
+#define declare_commit_slab_prototypes(slabname, elemtype)             \
+                                                                       \
+void init_ ##slabname## _with_stride(struct slabname *s, unsigned stride); \
+void init_ ##slabname(struct slabname *s);                             \
+void clear_ ##slabname(struct slabname *s);                            \
+elemtype *slabname## _at_peek(struct slabname *s, const struct commit *c, int add_if_missing); \
+elemtype *slabname## _at(struct slabname *s, const struct commit *c);  \
+elemtype *slabname## _peek(struct slabname *s, const struct commit *c)
+
+#define define_shared_commit_slab(slabname, elemtype) \
+       declare_commit_slab(slabname, elemtype); \
+       declare_commit_slab_prototypes(slabname, elemtype)
+
+#endif /* COMMIT_SLAB_HDR_H */
diff --git a/commit-slab-impl.h b/commit-slab-impl.h
new file mode 100644 (file)
index 0000000..87a9cad
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef COMMIT_SLAB_IMPL_H
+#define COMMIT_SLAB_IMPL_H
+
+#define MAYBE_UNUSED __attribute__((__unused__))
+
+#define implement_static_commit_slab(slabname, elemtype) \
+       implement_commit_slab(slabname, elemtype, static MAYBE_UNUSED)
+
+#define implement_shared_commit_slab(slabname, elemtype) \
+       implement_commit_slab(slabname, elemtype, )
+
+#define implement_commit_slab(slabname, elemtype, scope)               \
+                                                                       \
+static int stat_ ##slabname## realloc;                                 \
+                                                                       \
+scope void init_ ##slabname## _with_stride(struct slabname *s,         \
+                                                  unsigned stride)     \
+{                                                                      \
+       unsigned int elem_size;                                         \
+       if (!stride)                                                    \
+               stride = 1;                                             \
+       s->stride = stride;                                             \
+       elem_size = sizeof(elemtype) * stride;                          \
+       s->slab_size = COMMIT_SLAB_SIZE / elem_size;                    \
+       s->slab_count = 0;                                              \
+       s->slab = NULL;                                                 \
+}                                                                      \
+                                                                       \
+scope void init_ ##slabname(struct slabname *s)                                \
+{                                                                      \
+       init_ ##slabname## _with_stride(s, 1);                          \
+}                                                                      \
+                                                                       \
+scope void clear_ ##slabname(struct slabname *s)                       \
+{                                                                      \
+       unsigned int i;                                                 \
+       for (i = 0; i < s->slab_count; i++)                             \
+               free(s->slab[i]);                                       \
+       s->slab_count = 0;                                              \
+       FREE_AND_NULL(s->slab);                                         \
+}                                                                      \
+                                                                       \
+scope elemtype *slabname## _at_peek(struct slabname *s,                        \
+                                                 const struct commit *c, \
+                                                 int add_if_missing)   \
+{                                                                      \
+       unsigned int nth_slab, nth_slot;                                \
+                                                                       \
+       nth_slab = c->index / s->slab_size;                             \
+       nth_slot = c->index % s->slab_size;                             \
+                                                                       \
+       if (s->slab_count <= nth_slab) {                                \
+               unsigned int i;                                         \
+               if (!add_if_missing)                                    \
+                       return NULL;                                    \
+               REALLOC_ARRAY(s->slab, nth_slab + 1);                   \
+               stat_ ##slabname## realloc++;                           \
+               for (i = s->slab_count; i <= nth_slab; i++)             \
+                       s->slab[i] = NULL;                              \
+               s->slab_count = nth_slab + 1;                           \
+       }                                                               \
+       if (!s->slab[nth_slab]) {                                       \
+               if (!add_if_missing)                                    \
+                       return NULL;                                    \
+               s->slab[nth_slab] = xcalloc(s->slab_size,               \
+                                           sizeof(**s->slab) * s->stride);             \
+       }                                                               \
+       return &s->slab[nth_slab][nth_slot * s->stride];                \
+}                                                                      \
+                                                                       \
+scope elemtype *slabname## _at(struct slabname *s,                     \
+                                            const struct commit *c)    \
+{                                                                      \
+       return slabname##_at_peek(s, c, 1);                             \
+}                                                                      \
+                                                                       \
+scope elemtype *slabname## _peek(struct slabname *s,                   \
+                                            const struct commit *c)    \
+{                                                                      \
+       return slabname##_at_peek(s, c, 0);                             \
+}                                                                      \
+                                                                       \
+struct slabname
+
+/*
+ * Note that this redundant forward declaration is required
+ * to allow a terminating semicolon, which makes instantiations look
+ * like function declarations.  I.e., the expansion of
+ *
+ *    implement_commit_slab(indegree, int, static);
+ *
+ * ends in 'struct indegree;'.  This would otherwise
+ * be a syntax error according (at least) to ISO C.  It's hard to
+ * catch because GCC silently parses it by default.
+ */
+
+#endif /* COMMIT_SLAB_IMPL_H */
index dcaab8c..69bf0c8 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef COMMIT_SLAB_H
 #define COMMIT_SLAB_H
 
+#include "commit-slab-decl.h"
+#include "commit-slab-impl.h"
+
 /*
  * define_commit_slab(slabname, elemtype) creates boilerplate code to define
  * a new struct (struct slabname) that is used to associate a piece of data
  *   leaking memory.
  */
 
-/* allocate ~512kB at once, allowing for malloc overhead */
-#ifndef COMMIT_SLAB_SIZE
-#define COMMIT_SLAB_SIZE (512*1024-32)
-#endif
-
-#define MAYBE_UNUSED __attribute__((__unused__))
-
-#define define_commit_slab(slabname, elemtype)                                 \
-                                                                       \
-struct slabname {                                                      \
-       unsigned slab_size;                                             \
-       unsigned stride;                                                \
-       unsigned slab_count;                                            \
-       elemtype **slab;                                                \
-};                                                                     \
-static int stat_ ##slabname## realloc;                                 \
-                                                                       \
-static MAYBE_UNUSED void init_ ##slabname## _with_stride(struct slabname *s, \
-                                                  unsigned stride)     \
-{                                                                      \
-       unsigned int elem_size;                                         \
-       if (!stride)                                                    \
-               stride = 1;                                             \
-       s->stride = stride;                                             \
-       elem_size = sizeof(elemtype) * stride;                          \
-       s->slab_size = COMMIT_SLAB_SIZE / elem_size;                    \
-       s->slab_count = 0;                                              \
-       s->slab = NULL;                                                 \
-}                                                                      \
-                                                                       \
-static MAYBE_UNUSED void init_ ##slabname(struct slabname *s)          \
-{                                                                      \
-       init_ ##slabname## _with_stride(s, 1);                          \
-}                                                                      \
-                                                                       \
-static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s)         \
-{                                                                      \
-       unsigned int i;                                                 \
-       for (i = 0; i < s->slab_count; i++)                             \
-               free(s->slab[i]);                                       \
-       s->slab_count = 0;                                              \
-       FREE_AND_NULL(s->slab);                                         \
-}                                                                      \
-                                                                       \
-static MAYBE_UNUSED elemtype *slabname## _at_peek(struct slabname *s,  \
-                                                 const struct commit *c, \
-                                                 int add_if_missing)   \
-{                                                                      \
-       unsigned int nth_slab, nth_slot;                                \
-                                                                       \
-       nth_slab = c->index / s->slab_size;                             \
-       nth_slot = c->index % s->slab_size;                             \
-                                                                       \
-       if (s->slab_count <= nth_slab) {                                \
-               unsigned int i;                                         \
-               if (!add_if_missing)                                    \
-                       return NULL;                                    \
-               REALLOC_ARRAY(s->slab, nth_slab + 1);                   \
-               stat_ ##slabname## realloc++;                           \
-               for (i = s->slab_count; i <= nth_slab; i++)             \
-                       s->slab[i] = NULL;                              \
-               s->slab_count = nth_slab + 1;                           \
-       }                                                               \
-       if (!s->slab[nth_slab]) {                                       \
-               if (!add_if_missing)                                    \
-                       return NULL;                                    \
-               s->slab[nth_slab] = xcalloc(s->slab_size,               \
-                                           sizeof(**s->slab) * s->stride);             \
-       }                                                               \
-       return &s->slab[nth_slab][nth_slot * s->stride];                \
-}                                                                      \
-                                                                       \
-static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s,       \
-                                            const struct commit *c)    \
-{                                                                      \
-       return slabname##_at_peek(s, c, 1);                             \
-}                                                                      \
-                                                                       \
-static MAYBE_UNUSED elemtype *slabname## _peek(struct slabname *s,     \
-                                            const struct commit *c)    \
-{                                                                      \
-       return slabname##_at_peek(s, c, 0);                             \
-}                                                                      \
-                                                                       \
-struct slabname
-
-/*
- * Note that this redundant forward declaration is required
- * to allow a terminating semicolon, which makes instantiations look
- * like function declarations.  I.e., the expansion of
- *
- *    define_commit_slab(indegree, int);
- *
- * ends in 'struct indegree;'.  This would otherwise
- * be a syntax error according (at least) to ISO C.  It's hard to
- * catch because GCC silently parses it by default.
- */
-
-/*
- * Statically initialize a commit slab named "var". Note that this
- * evaluates "stride" multiple times! Example:
- *
- *   struct indegree indegrees = COMMIT_SLAB_INIT(1, indegrees);
- *
- */
-#define COMMIT_SLAB_INIT(stride, var) { \
-       COMMIT_SLAB_SIZE / sizeof(**((var).slab)) / (stride), \
-       (stride), 0, NULL \
-}
+#define define_commit_slab(slabname, elemtype) \
+       declare_commit_slab(slabname, elemtype); \
+       implement_static_commit_slab(slabname, elemtype)
 
 #endif /* COMMIT_SLAB_H */
index 0030e79..a7c0b5f 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -2,11 +2,14 @@
 #include "tag.h"
 #include "commit.h"
 #include "commit-graph.h"
+#include "repository.h"
+#include "object-store.h"
 #include "pkt-line.h"
 #include "utf8.h"
 #include "diff.h"
 #include "revision.h"
 #include "notes.h"
+#include "alloc.h"
 #include "gpg-interface.h"
 #include "mergesort.h"
 #include "commit-slab.h"
@@ -52,7 +55,8 @@ struct commit *lookup_commit(const struct object_id *oid)
 {
        struct object *obj = lookup_object(oid->hash);
        if (!obj)
-               return create_object(oid->hash, alloc_commit_node());
+               return create_object(the_repository, oid->hash,
+                                    alloc_commit_node(the_repository));
        return object_as_type(obj, OBJ_COMMIT, 0);
 }
 
@@ -96,41 +100,44 @@ static timestamp_t parse_commit_date(const char *buf, const char *tail)
        return parse_timestamp(dateptr, NULL, 10);
 }
 
-static struct commit_graft **commit_graft;
-static int commit_graft_alloc, commit_graft_nr;
-
 static const unsigned char *commit_graft_sha1_access(size_t index, void *table)
 {
        struct commit_graft **commit_graft_table = table;
        return commit_graft_table[index]->oid.hash;
 }
 
-static int commit_graft_pos(const unsigned char *sha1)
+static int commit_graft_pos(struct repository *r, const unsigned char *sha1)
 {
-       return sha1_pos(sha1, commit_graft, commit_graft_nr,
+       return sha1_pos(sha1, r->parsed_objects->grafts,
+                       r->parsed_objects->grafts_nr,
                        commit_graft_sha1_access);
 }
 
-int register_commit_graft(struct commit_graft *graft, int ignore_dups)
+int register_commit_graft(struct repository *r, struct commit_graft *graft,
+                         int ignore_dups)
 {
-       int pos = commit_graft_pos(graft->oid.hash);
+       int pos = commit_graft_pos(r, graft->oid.hash);
 
        if (0 <= pos) {
                if (ignore_dups)
                        free(graft);
                else {
-                       free(commit_graft[pos]);
-                       commit_graft[pos] = graft;
+                       free(r->parsed_objects->grafts[pos]);
+                       r->parsed_objects->grafts[pos] = graft;
                }
                return 1;
        }
        pos = -pos - 1;
-       ALLOC_GROW(commit_graft, commit_graft_nr + 1, commit_graft_alloc);
-       commit_graft_nr++;
-       if (pos < commit_graft_nr)
-               MOVE_ARRAY(commit_graft + pos + 1, commit_graft + pos,
-                          commit_graft_nr - pos - 1);
-       commit_graft[pos] = graft;
+       ALLOC_GROW(r->parsed_objects->grafts,
+                  r->parsed_objects->grafts_nr + 1,
+                  r->parsed_objects->grafts_alloc);
+       r->parsed_objects->grafts_nr++;
+       if (pos < r->parsed_objects->grafts_nr)
+               memmove(r->parsed_objects->grafts + pos + 1,
+                       r->parsed_objects->grafts + pos,
+                       (r->parsed_objects->grafts_nr - pos - 1) *
+                       sizeof(*r->parsed_objects->grafts));
+       r->parsed_objects->grafts[pos] = graft;
        return 0;
 }
 
@@ -172,7 +179,7 @@ bad_graft_data:
        return NULL;
 }
 
-static int read_graft_file(const char *graft_file)
+static int read_graft_file(struct repository *r, const char *graft_file)
 {
        FILE *fp = fopen_or_warn(graft_file, "r");
        struct strbuf buf = STRBUF_INIT;
@@ -192,7 +199,7 @@ static int read_graft_file(const char *graft_file)
                struct commit_graft *graft = read_graft_line(&buf);
                if (!graft)
                        continue;
-               if (register_commit_graft(graft, 1))
+               if (register_commit_graft(r, graft, 1))
                        error("duplicate graft data: %s", buf.buf);
        }
        fclose(fp);
@@ -200,50 +207,50 @@ static int read_graft_file(const char *graft_file)
        return 0;
 }
 
-static void prepare_commit_graft(void)
+static void prepare_commit_graft(struct repository *r)
 {
-       static int commit_graft_prepared;
        char *graft_file;
 
-       if (commit_graft_prepared)
+       if (r->parsed_objects->commit_graft_prepared)
                return;
        if (!startup_info->have_repository)
                return;
 
-       graft_file = get_graft_file();
-       read_graft_file(graft_file);
+       graft_file = get_graft_file(r);
+       read_graft_file(r, graft_file);
        /* make sure shallows are read */
-       is_repository_shallow();
-       commit_graft_prepared = 1;
+       is_repository_shallow(r);
+       r->parsed_objects->commit_graft_prepared = 1;
 }
 
-struct commit_graft *lookup_commit_graft(const struct object_id *oid)
+struct commit_graft *lookup_commit_graft(struct repository *r, const struct object_id *oid)
 {
        int pos;
-       prepare_commit_graft();
-       pos = commit_graft_pos(oid->hash);
+       prepare_commit_graft(r);
+       pos = commit_graft_pos(r, oid->hash);
        if (pos < 0)
                return NULL;
-       return commit_graft[pos];
+       return r->parsed_objects->grafts[pos];
 }
 
 int for_each_commit_graft(each_commit_graft_fn fn, void *cb_data)
 {
        int i, ret;
-       for (i = ret = 0; i < commit_graft_nr && !ret; i++)
-               ret = fn(commit_graft[i], cb_data);
+       for (i = ret = 0; i < the_repository->parsed_objects->grafts_nr && !ret; i++)
+               ret = fn(the_repository->parsed_objects->grafts[i], cb_data);
        return ret;
 }
 
 int unregister_shallow(const struct object_id *oid)
 {
-       int pos = commit_graft_pos(oid->hash);
+       int pos = commit_graft_pos(the_repository, oid->hash);
        if (pos < 0)
                return -1;
-       if (pos + 1 < commit_graft_nr)
-               MOVE_ARRAY(commit_graft + pos, commit_graft + pos + 1,
-                          commit_graft_nr - pos - 1);
-       commit_graft_nr--;
+       if (pos + 1 < the_repository->parsed_objects->grafts_nr)
+               MOVE_ARRAY(the_repository->parsed_objects->grafts + pos,
+                          the_repository->parsed_objects->grafts + pos + 1,
+                          the_repository->parsed_objects->grafts_nr - pos - 1);
+       the_repository->parsed_objects->grafts_nr--;
        return 0;
 }
 
@@ -325,6 +332,17 @@ struct object_id *get_commit_tree_oid(const struct commit *commit)
        return &get_commit_tree(commit)->object.oid;
 }
 
+void release_commit_memory(struct commit *c)
+{
+       c->maybe_tree = NULL;
+       c->index = 0;
+       free_commit_buffer(c);
+       free_commit_list(c->parents);
+       /* TODO: what about commit->util? */
+
+       c->object.parsed = 0;
+}
+
 const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep)
 {
        struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
@@ -344,7 +362,7 @@ const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep)
        return ret;
 }
 
-int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size)
+int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size, int check_graph)
 {
        const char *tail = buffer;
        const char *bufptr = buffer;
@@ -368,7 +386,7 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s
        bufptr += tree_entry_len + 1; /* "tree " + "hex sha1" + "\n" */
        pptr = &item->parents;
 
-       graft = lookup_commit_graft(&item->object.oid);
+       graft = lookup_commit_graft(the_repository, &item->object.oid);
        while (bufptr + parent_entry_len < tail && !memcmp(bufptr, "parent ", 7)) {
                struct commit *new_parent;
 
@@ -399,6 +417,9 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s
        }
        item->date = parse_commit_date(bufptr, tail);
 
+       if (check_graph)
+               load_commit_graph_info(item);
+
        return 0;
 }
 
@@ -425,7 +446,7 @@ int parse_commit_gently(struct commit *item, int quiet_on_missing)
                return error("Object %s not a commit",
                             oid_to_hex(&item->object.oid));
        }
-       ret = parse_commit_buffer(item, buffer, size);
+       ret = parse_commit_buffer(item, buffer, size, 0);
        if (save_commit_buffer && !ret) {
                set_commit_buffer(item, buffer, size);
                return 0;
@@ -653,6 +674,24 @@ static int compare_commits_by_author_date(const void *a_, const void *b_,
        return 0;
 }
 
+int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_, void *unused)
+{
+       const struct commit *a = a_, *b = b_;
+
+       /* newer commits first */
+       if (a->generation < b->generation)
+               return 1;
+       else if (a->generation > b->generation)
+               return -1;
+
+       /* use date as a heuristic when generations are equal */
+       if (a->date < b->date)
+               return 1;
+       else if (a->date > b->date)
+               return -1;
+       return 0;
+}
+
 int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused)
 {
        const struct commit *a = a_, *b = b_;
@@ -800,11 +839,14 @@ static int queue_has_nonstale(struct prio_queue *queue)
 }
 
 /* all input commits in one and twos[] must have been parsed! */
-static struct commit_list *paint_down_to_common(struct commit *one, int n, struct commit **twos)
+static struct commit_list *paint_down_to_common(struct commit *one, int n,
+                                               struct commit **twos,
+                                               int min_generation)
 {
-       struct prio_queue queue = { compare_commits_by_commit_date };
+       struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
        struct commit_list *result = NULL;
        int i;
+       uint32_t last_gen = GENERATION_NUMBER_INFINITY;
 
        one->object.flags |= PARENT1;
        if (!n) {
@@ -823,6 +865,15 @@ static struct commit_list *paint_down_to_common(struct commit *one, int n, struc
                struct commit_list *parents;
                int flags;
 
+               if (commit->generation > last_gen)
+                       BUG("bad generation skip %8x > %8x at %s",
+                           commit->generation, last_gen,
+                           oid_to_hex(&commit->object.oid));
+               last_gen = commit->generation;
+
+               if (commit->generation < min_generation)
+                       break;
+
                flags = commit->object.flags & (PARENT1 | PARENT2 | STALE);
                if (flags == (PARENT1 | PARENT2)) {
                        if (!(commit->object.flags & RESULT)) {
@@ -871,7 +922,7 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co
                        return NULL;
        }
 
-       list = paint_down_to_common(one, n, twos);
+       list = paint_down_to_common(one, n, twos, 0);
 
        while (list) {
                struct commit *commit = pop_commit(&list);
@@ -929,6 +980,7 @@ static int remove_redundant(struct commit **array, int cnt)
                parse_commit(array[i]);
        for (i = 0; i < cnt; i++) {
                struct commit_list *common;
+               uint32_t min_generation = array[i]->generation;
 
                if (redundant[i])
                        continue;
@@ -937,8 +989,12 @@ static int remove_redundant(struct commit **array, int cnt)
                                continue;
                        filled_index[filled] = j;
                        work[filled++] = array[j];
+
+                       if (array[j]->generation < min_generation)
+                               min_generation = array[j]->generation;
                }
-               common = paint_down_to_common(array[i], filled, work);
+               common = paint_down_to_common(array[i], filled, work,
+                                             min_generation);
                if (array[i]->object.flags & PARENT2)
                        redundant[i] = 1;
                for (j = 0; j < filled; j++)
@@ -1048,14 +1104,21 @@ int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit *
 {
        struct commit_list *bases;
        int ret = 0, i;
+       uint32_t min_generation = GENERATION_NUMBER_INFINITY;
 
        if (parse_commit(commit))
                return ret;
-       for (i = 0; i < nr_reference; i++)
+       for (i = 0; i < nr_reference; i++) {
                if (parse_commit(reference[i]))
                        return ret;
+               if (reference[i]->generation < min_generation)
+                       min_generation = reference[i]->generation;
+       }
+
+       if (commit->generation > min_generation)
+               return ret;
 
-       bases = paint_down_to_common(commit, nr_reference, reference);
+       bases = paint_down_to_common(commit, nr_reference, reference, commit->generation);
        if (commit->object.flags & PARENT2)
                ret = 1;
        clear_commit_marks(commit, all_flags);
@@ -1605,13 +1668,21 @@ out:
        return result;
 }
 
+define_commit_slab(merge_desc_slab, struct merge_remote_desc *);
+static struct merge_desc_slab merge_desc_slab = COMMIT_SLAB_INIT(1, merge_desc_slab);
+
+struct merge_remote_desc *merge_remote_util(struct commit *commit)
+{
+       return *merge_desc_slab_at(&merge_desc_slab, commit);
+}
+
 void set_merge_remote_desc(struct commit *commit,
                           const char *name, struct object *obj)
 {
        struct merge_remote_desc *desc;
        FLEX_ALLOC_STR(desc, name, name);
        desc->obj = obj;
-