Merge branch 'jk/branch-l-0-deprecation'
authorJunio C Hamano <gitster@pobox.com>
Wed, 18 Jul 2018 19:20:31 +0000 (12:20 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 18 Jul 2018 19:20:31 +0000 (12:20 -0700)
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.

* jk/branch-l-0-deprecation:
  branch: deprecate "-l" option
  t: switch "branch -l" to "branch --create-reflog"
  t3200: unset core.logallrefupdates when testing reflog creation

212 files changed:
.gitignore
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-grep.txt
Documentation/git-help.txt
Documentation/git-imap-send.txt
Documentation/git-notes.txt
Documentation/git-show-index.txt
Documentation/git-status.txt
Documentation/git-submodule.txt
Documentation/git-svn.txt
Documentation/giteveryday.txt
Documentation/gitsubmodules.txt
Documentation/glossary-content.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/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/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
config.c
config.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
fetch-pack.c
fsck.c
generate-cmdlist.sh
git-add--interactive.perl
git-p4.py
git-rebase--interactive.sh
git-rebase--preserve-merges.sh [new file with mode: 0644]
git-rebase.sh
git-submodule.sh
git.c
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/packed-backend.c
refspec.c
refspec.h
remote-testsvn.c
remote.c
repository.c
repository.h
rerere.c
revision.c
revision.h
send-pack.c
sequencer.c
sha1-file.c
shallow.c
submodule-config.c
submodule.c
submodule.h
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/t2203-add-intent.sh
t/t3404-rebase-interactive.sh
t/t3423-rebase-reword.sh [new file with mode: 0755]
t/t3701-add-interactive.sh
t/t4011-diff-symlink.sh
t/t4014-format-patch.sh
t/t4254-am-corrupt.sh
t/t5318-commit-graph.sh
t/t5500-fetch-pack.sh
t/t5526-fetch-submodules.sh
t/t5537-fetch-shallow.sh
t/t5573-pull-verify-signatures.sh
t/t6036-recursive-corner-cases.sh
t/t6042-merge-rename-corner-cases.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/t9104-git-svn-follow-parent.sh
t/t9902-completion.sh
tag.c
tag.h
tree-walk.c
tree.c
unpack-trees.c
upload-pack.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
diff --git a/Documentation/RelNotes/2.19.0.txt b/Documentation/RelNotes/2.19.0.txt
new file mode 100644 (file)
index 0000000..2b45b6f
--- /dev/null
@@ -0,0 +1,101 @@
+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.
+
+
+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.
+
+
+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.
+
+ * Code cleanup.
+   (merge aee9be2ebe sg/update-ref-stdin-cleanup later to maint).
+   (merge 037714252f jc/clean-after-sanity-tests 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..8f7527b 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
@@ -1162,7 +1162,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 +1182,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 +1800,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 +3333,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
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 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 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 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 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..2c965d5 100644 (file)
@@ -18,7 +18,7 @@ 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
+corresponding to the array position within 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.
 
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
index 49bda76..f58f24b 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:
 
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..0cb6590 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
@@ -2397,6 +2398,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..23a0f25 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;
 
@@ -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..921d127 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);
index ed4c093..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]"),
@@ -56,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)
 {
@@ -87,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)
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..1d939af 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);
 
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 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..83f36d7 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"
@@ -777,7 +778,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);
 
@@ -1029,7 +1030,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)
@@ -1449,7 +1450,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..44c7c9e 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[] = {
@@ -905,7 +906,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..216e3da 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);
        }
 
@@ -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;
-       commit->util = desc;
+       *merge_desc_slab_at(&merge_desc_slab, commit) = desc;
 }
 
 struct commit *get_merge_parent(const char *name)
@@ -1623,7 +1694,7 @@ struct commit *get_merge_parent(const char *name)
                return NULL;
        obj = parse_object(&oid);
        commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
-       if (commit && !commit->util)
+       if (commit && !merge_remote_util(commit))
                set_merge_remote_desc(commit, name, obj);
        return commit;
 }
index c3af512..01b8b1d 100644 (file)
--- a/commit.h
+++ b/commit.h
 #include "pretty.h"
 
 #define COMMIT_NOT_FROM_GRAPH 0xFFFFFFFF
+#define GENERATION_NUMBER_INFINITY 0xFFFFFFFF
+#define GENERATION_NUMBER_MAX 0x3FFFFFFF
+#define GENERATION_NUMBER_ZERO 0
 
 struct commit_list {
        struct commit *item;
        struct commit_list *next;
 };
 
+/*
+ * The size of this struct matters in full repo walk operations like
+ * 'git clone' or 'git gc'. Consider using commit-slab to attach data
+ * to a commit instead of adding new fields here.
+ */
 struct commit {
        struct object object;
-       void *util;
        timestamp_t date;
        struct commit_list *parents;
 
@@ -29,6 +36,7 @@ struct commit {
         */
        struct tree *maybe_tree;
        uint32_t graph_pos;
+       uint32_t generation;
        unsigned int index;
 };
 
@@ -68,7 +76,7 @@ struct commit *lookup_commit_reference_by_name(const char *name);
  */
 struct commit *lookup_commit_or_die(const struct object_id *oid, const char *ref_name);
 
-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);
 int parse_commit_gently(struct commit *item, int quiet_on_missing);
 static inline int parse_commit(struct commit *item)
 {
@@ -111,6 +119,12 @@ void free_commit_buffer(struct commit *);
 struct tree *get_commit_tree(const struct commit *);
 struct object_id *get_commit_tree_oid(const struct commit *);
 
+/*
+ * Release memory related to a commit, including the parent list and
+ * any cached object buffer.
+ */
+void release_commit_memory(struct commit *c);
+
 /*
  * Disassociate any cached object buffer from the commit, but do not free it.
  * The buffer (or NULL, if none) is returned.
@@ -180,8 +194,8 @@ struct commit_graft {
 typedef int (*each_commit_graft_fn)(const struct commit_graft *, void *);
 
 struct commit_graft *read_graft_line(struct strbuf *line);
-int register_commit_graft(struct commit_graft *, int);
-struct commit_graft *lookup_commit_graft(const struct object_id *oid);
+int register_commit_graft(struct repository *r, struct commit_graft *, int);
+struct commit_graft *lookup_commit_graft(struct repository *r, const struct object_id *oid);
 
 extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2);
 extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos);
@@ -195,15 +209,15 @@ extern struct commit_list *get_merge_bases_many_dirty(struct commit *one, int n,
 
 struct oid_array;
 struct ref;
-extern int register_shallow(const struct object_id *oid);
+extern int register_shallow(struct repository *r, const struct object_id *oid);
 extern int unregister_shallow(const struct object_id *oid);
 extern int for_each_commit_graft(each_commit_graft_fn, void *);
-extern int is_repository_shallow(void);
+extern int is_repository_shallow(struct repository *r);
 extern struct commit_list *get_shallow_commits(struct object_array *heads,
                int depth, int shallow_flag, int not_shallow_flag);
 extern struct commit_list *get_shallow_commits_by_rev_list(
                int ac, const char **av, int shallow_flag, int not_shallow_flag);
-extern void set_alternate_shallow_file(const char *path, int override);
+extern void set_alternate_shallow_file(struct repository *r, const char *path, int override);
 extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
                                 const struct oid_array *extra);
 extern void setup_alternate_shallow(struct lock_file *shallow_lock,
@@ -312,7 +326,7 @@ struct merge_remote_desc {
        struct object *obj; /* the named object, could be a tag */
        char name[FLEX_ARRAY];
 };
-#define merge_remote_util(commit) ((struct merge_remote_desc *)((commit)->util))
+extern struct merge_remote_desc *merge_remote_util(struct commit *);
 extern void set_merge_remote_desc(struct commit *commit,
                                  const char *name, struct object *obj);
 
@@ -337,6 +351,7 @@ extern int remove_signature(struct strbuf *buf);
 extern int check_commit_signature(const struct commit *commit, struct signature_check *sigc);
 
 int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused);
+int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_, void *unused);
 
 LAST_ARG_MUST_BE_NULL
 extern int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...);
index fbbf0f8..139c903 100644 (file)
--- a/config.c
+++ b/config.c
@@ -14,6 +14,7 @@
 #include "quote.h"
 #include "hashmap.h"
 #include "string-list.h"
+#include "object-store.h"
 #include "utf8.h"
 #include "dir.h"
 #include "color.h"
@@ -1233,7 +1234,7 @@ static int git_default_core_config(const char *var, const char *value)
                }
                eol_rndtrp_die = git_config_bool(var, value);
                global_conv_flags_eol = eol_rndtrp_die ?
-                       CONV_EOL_RNDTRP_DIE : CONV_EOL_RNDTRP_WARN;
+                       CONV_EOL_RNDTRP_DIE : 0;
                return 0;
        }
 
@@ -3245,3 +3246,16 @@ enum config_scope current_config_scope(void)
        else
                return current_parsing_scope;
 }
+
+int lookup_config(const char **mapping, int nr_mapping, const char *var)
+{
+       int i;
+
+       for (i = 0; i < nr_mapping; i++) {
+               const char *name = mapping[i];
+
+               if (name && !strcasecmp(var, name))
+                       return i;
+       }
+       return -1;
+}
index cdac2fc..626d465 100644 (file)
--- a/config.h
+++ b/config.h
@@ -257,4 +257,8 @@ struct key_value_info {
 extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
 extern NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr);
 
+#define LOOKUP_CONFIG(mapping, var) \
+       lookup_config(mapping, ARRAY_SIZE(mapping), var)
+int lookup_config(const char **mapping, int nr_mapping, const char *var);
+
 #endif /* CONFIG_H */
index dd3e925..94c9551 100644 (file)
@@ -330,9 +330,32 @@ __gitcomp ()
        case "$cur_" in
        --*=)
                ;;
+       --no-*)
+               local c i=0 IFS=$' \t\n'
+               for c in $1; do
+                       if [[ $c == "--" ]]; then
+                               continue
+                       fi
+                       c="$c${4-}"
+                       if [[ $c == "$cur_"* ]]; then
+                               case $c in
+                               --*=*|*.) ;;
+                               *) c="$c " ;;
+                               esac
+                               COMPREPLY[i++]="${2-}$c"
+                       fi
+               done
+               ;;
        *)
                local c i=0 IFS=$' \t\n'
                for c in $1; do
+                       if [[ $c == "--" ]]; then
+                               c="--no-...${4-}"
+                               if [[ $c == "$cur_"* ]]; then
+                                       COMPREPLY[i++]="${2-}$c "
+                               fi
+                               break
+                       fi
                        c="$c${4-}"
                        if [[ $c == "$cur_"* ]]; then
                                case $c in
@@ -1161,7 +1184,7 @@ _git_am ()
                return
                ;;
        --*)
-               __gitcomp_builtin am "--no-utf8" \
+               __gitcomp_builtin am "" \
                        "$__git_am_inprogress_options"
                return
        esac
@@ -1261,9 +1284,7 @@ _git_branch ()
                __git_complete_refs --cur="${cur##--set-upstream-to=}"
                ;;
        --*)
-               __gitcomp_builtin branch "--no-color --no-abbrev
-                       --no-track --no-column
-                       "
+               __gitcomp_builtin branch
                ;;
        *)
                if [ $only_local_ref = "y" -a $has_r = "n" ]; then
@@ -1304,7 +1325,7 @@ _git_checkout ()
                __gitcomp "diff3 merge" "" "${cur##--conflict=}"
                ;;
        --*)
-               __gitcomp_builtin checkout "--no-track --no-recurse-submodules"
+               __gitcomp_builtin checkout
                ;;
        *)
                # check if --track, --no-track, or --no-guess was specified
@@ -1367,7 +1388,7 @@ _git_clone ()
 {
        case "$cur" in
        --*)
-               __gitcomp_builtin clone "--no-single-branch"
+               __gitcomp_builtin clone
                return
                ;;
        esac
@@ -1400,7 +1421,7 @@ _git_commit ()
                return
                ;;
        --*)
-               __gitcomp_builtin commit "--no-edit --verify"
+               __gitcomp_builtin commit
                return
        esac
 
@@ -1503,7 +1524,7 @@ _git_fetch ()
                return
                ;;
        --*)
-               __gitcomp_builtin fetch "--no-tags"
+               __gitcomp_builtin fetch
                return
                ;;
        esac
@@ -1540,7 +1561,7 @@ _git_fsck ()
 {
        case "$cur" in
        --*)
-               __gitcomp_builtin fsck "--no-reflogs"
+               __gitcomp_builtin fsck
                return
                ;;
        esac
@@ -1646,7 +1667,7 @@ _git_ls_files ()
 {
        case "$cur" in
        --*)
-               __gitcomp_builtin ls-files "--no-empty-directory"
+               __gitcomp_builtin ls-files
                return
                ;;
        esac
@@ -1797,12 +1818,7 @@ _git_merge ()
 
        case "$cur" in
        --*)
-               __gitcomp_builtin merge "--no-rerere-autoupdate
-                               --no-commit --no-edit --no-ff
-                               --no-log --no-progress
-                               --no-squash --no-stat
-                               --no-verify-signatures
-                               "
+               __gitcomp_builtin merge
                return
        esac
        __git_complete_refs
@@ -1901,10 +1917,7 @@ _git_pull ()
                return
                ;;
        --*)
-               __gitcomp_builtin pull "--no-autostash --no-commit --no-edit
-                                       --no-ff --no-log --no-progress --no-rebase
-                                       --no-squash --no-stat --no-tags
-                                       --no-verify-signatures"
+               __gitcomp_builtin pull
 
                return
                ;;
@@ -2095,7 +2108,7 @@ _git_status ()
                return
                ;;
        --*)
-               __gitcomp_builtin status "--no-column"
+               __gitcomp_builtin status
                return
                ;;
        esac
@@ -2142,9 +2155,24 @@ __git_config_get_set_variables ()
        __git config $config_file --name-only --list
 }
 
+__git_config_vars=
+__git_compute_config_vars ()
+{
+       test -n "$__git_config_vars" ||
+       __git_config_vars="$(git help --config-for-completion | sort | uniq)"
+}
+
 _git_config ()
 {
-       case "$prev" in
+       local varname
+
+       if [ "${BASH_VERSINFO[0]:-0}" -ge 4 ]; then
+               varname="${prev,,}"
+       else
+               varname="$(echo "$prev" |tr A-Z a-z)"
+       fi
+
+       case "$varname" in
        branch.*.remote|branch.*.pushremote)
                __gitcomp_nl "$(__git_remotes)"
                return
@@ -2242,20 +2270,20 @@ _git_config ()
                ;;
        branch.*.*)
                local pfx="${cur%.*}." cur_="${cur##*.}"
-               __gitcomp "remote pushremote merge mergeoptions rebase" "$pfx" "$cur_"
+               __gitcomp "remote pushRemote merge mergeOptions rebase" "$pfx" "$cur_"
                return
                ;;
        branch.*)
                local pfx="${cur%.*}." cur_="${cur#*.}"
                __gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")"
-               __gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_"
+               __gitcomp_nl_append $'autoSetupMerge\nautoSetupRebase\n' "$pfx" "$cur_"
                return
                ;;
        guitool.*.*)
                local pfx="${cur%.*}." cur_="${cur##*.}"
                __gitcomp "
-                       argprompt cmd confirm needsfile noconsole norescan
-                       prompt revprompt revunmerged title
+                       argPrompt cmd confirm needsFile noConsole noRescan
+                       prompt revPrompt revUnmerged title
                        " "$pfx" "$cur_"
                return
                ;;
@@ -2284,14 +2312,14 @@ _git_config ()
                local pfx="${cur%.*}." cur_="${cur##*.}"
                __gitcomp "
                        url proxy fetch push mirror skipDefaultUpdate
-                       receivepack uploadpack tagopt pushurl
+                       receivepack uploadpack tagOpt pushurl
                        " "$pfx" "$cur_"
                return
                ;;
        remote.*)
                local pfx="${cur%.*}." cur_="${cur#*.}"
                __gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "."
-               __gitcomp_nl_append "pushdefault" "$pfx" "$cur_"
+               __gitcomp_nl_append "pushDefault" "$pfx" "$cur_"
                return
                ;;
        url.*.*)
@@ -2299,333 +2327,14 @@ _git_config ()
                __gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_"
                return
                ;;
+       *.*)
+               __git_compute_config_vars
+               __gitcomp "$__git_config_vars"
+               ;;
+       *)
+               __git_compute_config_vars
+               __gitcomp "$(echo "$__git_config_vars" | sed 's/\.[^ ]*/./g')"
        esac
-       __gitcomp "
-               add.ignoreErrors
-               advice.amWorkDir
-               advice.commitBeforeMerge
-               advice.detachedHead
-               advice.implicitIdentity
-               advice.pushAlreadyExists
-               advice.pushFetchFirst
-               advice.pushNeedsForce
-               advice.pushNonFFCurrent
-               advice.pushNonFFMatching
-               advice.pushUpdateRejected
-               advice.resolveConflict
-               advice.rmHints
-               advice.statusHints
-               advice.statusUoption
-               advice.ignoredHook
-               alias.
-               am.keepcr
-               am.threeWay
-               apply.ignorewhitespace
-               apply.whitespace
-               branch.autosetupmerge
-               branch.autosetuprebase
-               browser.
-               clean.requireForce
-               color.branch
-               color.branch.current
-               color.branch.local
-               color.branch.plain
-               color.branch.remote
-               color.decorate.HEAD
-               color.decorate.branch
-               color.decorate.remoteBranch
-               color.decorate.stash
-               color.decorate.tag
-               color.diff
-               color.diff.commit
-               color.diff.frag
-               color.diff.func
-               color.diff.meta
-               color.diff.new
-               color.diff.old
-               color.diff.plain
-               color.diff.whitespace
-               color.grep
-               color.grep.context
-               color.grep.filename
-               color.grep.function
-               color.grep.linenumber
-               color.grep.match
-               color.grep.selected
-               color.grep.separator
-               color.interactive
-               color.interactive.error
-               color.interactive.header
-               color.interactive.help
-               color.interactive.prompt
-               color.pager
-               color.showbranch
-               color.status
-               color.status.added
-               color.status.changed
-               color.status.header
-               color.status.localBranch
-               color.status.nobranch
-               color.status.remoteBranch
-               color.status.unmerged
-               color.status.untracked
-               color.status.updated
-               color.ui
-               commit.cleanup
-               commit.gpgSign
-               commit.status
-               commit.template
-               commit.verbose
-               core.abbrev
-               core.askpass
-               core.attributesfile
-               core.autocrlf
-               core.bare
-               core.bigFileThreshold
-               core.checkStat
-               core.commentChar
-               core.commitGraph
-               core.compression
-               core.createObject
-               core.deltaBaseCacheLimit
-               core.editor
-               core.eol
-               core.excludesfile
-               core.fileMode
-               core.fsyncobjectfiles
-               core.gitProxy
-               core.hideDotFiles
-               core.hooksPath
-               core.ignoreStat
-               core.ignorecase
-               core.logAllRefUpdates
-               core.loosecompression
-               core.notesRef
-               core.packedGitLimit
-               core.packedGitWindowSize
-               core.packedRefsTimeout
-               core.pager
-               core.precomposeUnicode
-               core.preferSymlinkRefs
-               core.preloadindex
-               core.protectHFS
-               core.protectNTFS
-               core.quotepath
-               core.repositoryFormatVersion
-               core.safecrlf
-               core.sharedRepository
-               core.sparseCheckout
-               core.splitIndex
-               core.sshCommand
-               core.symlinks
-               core.trustctime
-               core.untrackedCache
-               core.warnAmbiguousRefs
-               core.whitespace
-               core.worktree
-               credential.helper
-               credential.useHttpPath
-               credential.username
-               credentialCache.ignoreSIGHUP
-               diff.autorefreshindex
-               diff.external
-               diff.ignoreSubmodules
-               diff.mnemonicprefix
-               diff.noprefix
-               diff.renameLimit
-               diff.renames
-               diff.statGraphWidth
-               diff.submodule
-               diff.suppressBlankEmpty
-               diff.tool
-               diff.wordRegex
-               diff.algorithm
-               difftool.
-               difftool.prompt
-               fetch.recurseSubmodules
-               fetch.unpackLimit
-               format.attach
-               format.cc
-               format.coverLetter
-               format.from
-               format.headers
-               format.numbered
-               format.pretty
-               format.signature
-               format.signoff
-               format.subjectprefix
-               format.suffix
-               format.thread
-               format.to
-               gc.
-               gc.aggressiveDepth
-               gc.aggressiveWindow
-               gc.auto
-               gc.autoDetach
-               gc.autopacklimit
-               gc.logExpiry
-               gc.packrefs
-               gc.pruneexpire
-               gc.reflogexpire
-               gc.reflogexpireunreachable
-               gc.rerereresolved
-               gc.rerereunresolved
-               gc.worktreePruneExpire
-               gitcvs.allbinary
-               gitcvs.commitmsgannotation
-               gitcvs.dbTableNamePrefix
-               gitcvs.dbdriver
-               gitcvs.dbname
-               gitcvs.dbpass
-               gitcvs.dbuser
-               gitcvs.enabled
-               gitcvs.logfile
-               gitcvs.usecrlfattr
-               guitool.
-               gui.blamehistoryctx
-               gui.commitmsgwidth
-               gui.copyblamethreshold
-               gui.diffcontext
-               gui.encoding
-               gui.fastcopyblame
-               gui.matchtrackingbranch
-               gui.newbranchtemplate
-               gui.pruneduringfetch
-               gui.spellingdictionary
-               gui.trustmtime
-               help.autocorrect
-               help.browser
-               help.format
-               http.lowSpeedLimit
-               http.lowSpeedTime
-               http.maxRequests
-               http.minSessions
-               http.noEPSV
-               http.postBuffer
-               http.proxy
-               http.sslCipherList
-               http.sslVersion
-               http.sslCAInfo
-               http.sslCAPath
-               http.sslCert
-               http.sslCertPasswordProtected
-               http.sslKey
-               http.sslVerify
-               http.useragent
-               i18n.commitEncoding
-               i18n.logOutputEncoding
-               imap.authMethod
-               imap.folder
-               imap.host
-               imap.pass
-               imap.port
-               imap.preformattedHTML
-               imap.sslverify
-               imap.tunnel
-               imap.user
-               init.templatedir
-               instaweb.browser
-               instaweb.httpd
-               instaweb.local
-               instaweb.modulepath
-               instaweb.port
-               interactive.singlekey
-               log.date
-               log.decorate
-               log.showroot
-               mailmap.file
-               man.
-               man.viewer
-               merge.
-               merge.conflictstyle
-               merge.log
-               merge.renameLimit
-               merge.renormalize
-               merge.stat
-               merge.tool
-               merge.verbosity
-               mergetool.
-               mergetool.keepBackup
-               mergetool.keepTemporaries
-               mergetool.prompt
-               notes.displayRef
-               notes.rewrite.
-               notes.rewrite.amend
-               notes.rewrite.rebase
-               notes.rewriteMode
-               notes.rewriteRef
-               pack.compression
-               pack.deltaCacheLimit
-               pack.deltaCacheSize
-               pack.depth
-               pack.indexVersion
-               pack.packSizeLimit
-               pack.threads
-               pack.window
-               pack.windowMemory
-               pager.
-               pretty.
-               pull.octopus
-               pull.twohead
-               push.default
-               push.followTags
-               rebase.autosquash
-               rebase.stat
-               receive.autogc
-               receive.denyCurrentBranch
-               receive.denyDeleteCurrent
-               receive.denyDeletes
-               receive.denyNonFastForwards
-               receive.fsckObjects
-               receive.unpackLimit
-               receive.updateserverinfo
-               remote.pushdefault
-               remotes.
-               repack.usedeltabaseoffset
-               rerere.autoupdate
-               rerere.enabled
-               sendemail.
-               sendemail.aliasesfile
-               sendemail.aliasfiletype
-               sendemail.bcc
-               sendemail.cc
-               sendemail.cccmd
-               sendemail.chainreplyto
-               sendemail.confirm
-               sendemail.envelopesender
-               sendemail.from
-               sendemail.identity
-               sendemail.multiedit
-               sendemail.signedoffbycc
-               sendemail.smtpdomain
-               sendemail.smtpencryption
-               sendemail.smtppass
-               sendemail.smtpserver
-               sendemail.smtpserveroption
-               sendemail.smtpserverport
-               sendemail.smtpuser
-               sendemail.suppresscc
-               sendemail.suppressfrom
-               sendemail.thread
-               sendemail.to
-               sendemail.tocmd
-               sendemail.validate
-               sendemail.smtpbatchsize
-               sendemail.smtprelogindelay
-               showbranch.default
-               status.relativePaths
-               status.showUntrackedFiles
-               status.submodulesummary
-               submodule.
-               tar.umask
-               transfer.unpackLimit
-               url.
-               user.email
-               user.name
-               user.signingkey
-               web.browser
-               branch. remote.
-       "
 }
 
 _git_remote ()
@@ -2649,7 +2358,7 @@ _git_remote ()
 
        case "$subcommand,$cur" in
        add,--*)
-               __gitcomp_builtin remote_add "--no-tags"
+               __gitcomp_builtin remote_add
                ;;
        add,*)
                ;;
@@ -2666,7 +2375,7 @@ _git_remote ()
                __gitcomp_builtin remote_update
                ;;
        update,*)
-               __gitcomp "$(__git_get_config_variables "remotes")"
+               __gitcomp "$(__git_remotes) $(__git_get_config_variables "remotes")"
                ;;
        set-url,--*)
                __gitcomp_builtin remote_set-url
@@ -2729,7 +2438,7 @@ _git_revert ()
        fi
        case "$cur" in
        --*)
-               __gitcomp_builtin revert "--no-edit" \
+               __gitcomp_builtin revert "" \
                        "$__git_revert_inprogress_options"
                return
                ;;
@@ -2799,7 +2508,7 @@ _git_show_branch ()
 {
        case "$cur" in
        --*)
-               __gitcomp_builtin show-branch "--no-color"
+               __gitcomp_builtin show-branch
                return
                ;;
        esac
index 0ffa407..6174e3b 100644 (file)
@@ -1,3 +1,6 @@
+# The default target of this Makefile is...
+all::
+
 test:
        ./t-git-credential-netrc.sh
 
index 58191a6..07227d0 100755 (executable)
        # set up test repository
 
        test_expect_success \
-    'set up test repository' \
-    'git config --add gpg.program test.git-config-gpg'
+               'set up test repository' \
+               'git config --add gpg.program test.git-config-gpg'
 
        # The external test will outputs its own plan
        test_external_has_tap=1
 
+       export PERL5LIB="$GITPERLLIB"
        test_external \
-    'git-credential-netrc' \
-    perl "$TEST_DIRECTORY"/../contrib/credential/netrc/test.pl
+               'git-credential-netrc' \
+               perl "$GIT_BUILD_DIR"/contrib/credential/netrc/test.pl
 
        test_done
 )
index 1e10010..c0fb371 100755 (executable)
@@ -1,5 +1,4 @@
 #!/usr/bin/perl
-use lib (split(/:/, $ENV{GITPERLLIB}));
 
 use warnings;
 use strict;
@@ -12,7 +11,6 @@ BEGIN {
        # t-git-credential-netrc.sh kicks off our testing, so we have to go
        # from there.
        Test::More->builder->current_test(1);
-       Test::More->builder->no_ending(1);
 }
 
 my @global_credential_args = @ARGV;
@@ -104,6 +102,9 @@ $cred = run_credential( ['-f', $netrcGpg, '-g', 'test.command-option-gpg', 'get'
 
 ok(scalar keys %$cred == 2, 'Got keys decrypted by command option');
 
+my $is_passing = eval { Test::More->is_passing };
+exit($is_passing ? 0 : 1) unless $@ =~ /Can't locate object method/;
+
 sub run_credential
 {
        my $args = shift @_;
index 4484bda..2f618a7 100644 (file)
@@ -25,6 +25,13 @@ git-jump will feed this to the editor:
 foo.c:2: printf("hello word!\n");
 -----------------------------------
 
+Or, when running 'git jump grep', column numbers will also be emitted,
+e.g. `git jump grep "hello"` would return:
+
+-----------------------------------
+foo.c:2:9: printf("hello word!\n");
+-----------------------------------
+
 Obviously this trivial case isn't that interesting; you could just open
 `foo.c` yourself. But when you have many changes scattered across a
 project, you can use the editor's support to "jump" from point to point.
@@ -35,7 +42,8 @@ Git-jump can generate four types of interesting lists:
 
   2. The beginning of any merge conflict markers.
 
-  3. Any grep matches.
+  3. Any grep matches, including the column of the first match on a
+     line.
 
   4. Any whitespace errors detected by `git diff --check`.
 
@@ -82,7 +90,7 @@ which does something similar to `git jump grep`. However, it is limited
 to positioning the cursor to the correct line in only the first file,
 leaving you to locate subsequent hits in that file or other files using
 the editor or pager. By contrast, git-jump provides the editor with a
-complete list of files and line numbers for each match.
+complete list of files, lines, and a column number for each match.
 
 
 Limitations
index 80ab059..931b0fe 100755 (executable)
@@ -52,7 +52,7 @@ mode_merge() {
 # editor shows them to us in the status bar.
 mode_grep() {
        cmd=$(git config jump.grepCmd)
-       test -n "$cmd" || cmd="git grep -n"
+       test -n "$cmd" || cmd="git grep -n --column"
        $cmd "$@" |
        perl -pe '
        s/[ \t]+/ /g;
index 64d0d30..56cfe31 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -1,6 +1,7 @@
 #define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
 #include "config.h"
+#include "object-store.h"
 #include "attr.h"
 #include "run-command.h"
 #include "quote.h"
index 104f954..a9f38eb 100644 (file)
@@ -389,8 +389,12 @@ static void do_oneway_diff(struct unpack_trees_options *o,
        struct rev_info *revs = o->unpack_data;
        int match_missing, cached;
 
-       /* i-t-a entries do not actually exist in the index */
-       if (revs->diffopt.ita_invisible_in_index &&
+       /*
+        * i-t-a entries do not actually exist in the index (if we're
+        * looking at its content)
+        */
+       if (o->index_only &&
+           revs->diffopt.ita_invisible_in_index &&
            idx && ce_intent_to_add(idx)) {
                idx = NULL;
                if (!tree)
diff --git a/diff.c b/diff.c
index 136d44b..dc53a19 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -13,6 +13,7 @@
 #include "attr.h"
 #include "run-command.h"
 #include "utf8.h"
+#include "object-store.h"
 #include "userdiff.h"
 #include "submodule-config.h"
 #include "submodule.h"
@@ -22,6 +23,7 @@
 #include "argv-array.h"
 #include "graph.h"
 #include "packfile.h"
+#include "help.h"
 
 #ifdef NO_FAST_WORKING_DIRECTORY
 #define FAST_WORKING_DIRECTORY 0
@@ -69,46 +71,37 @@ static char diff_colors[][COLOR_MAXLEN] = {
        GIT_COLOR_FAINT_ITALIC, /* NEW_MOVED_ALTERNATIVE_DIM */
 };
 
+static const char *color_diff_slots[] = {
+       [DIFF_CONTEXT]                = "context",
+       [DIFF_METAINFO]               = "meta",
+       [DIFF_FRAGINFO]               = "frag",
+       [DIFF_FILE_OLD]               = "old",
+       [DIFF_FILE_NEW]               = "new",
+       [DIFF_COMMIT]                 = "commit",
+       [DIFF_WHITESPACE]             = "whitespace",
+       [DIFF_FUNCINFO]               = "func",
+       [DIFF_FILE_OLD_MOVED]         = "oldMoved",
+       [DIFF_FILE_OLD_MOVED_ALT]     = "oldMovedAlternative",
+       [DIFF_FILE_OLD_MOVED_DIM]     = "oldMovedDimmed",
+       [DIFF_FILE_OLD_MOVED_ALT_DIM] = "oldMovedAlternativeDimmed",
+       [DIFF_FILE_NEW_MOVED]         = "newMoved",
+       [DIFF_FILE_NEW_MOVED_ALT]     = "newMovedAlternative",
+       [DIFF_FILE_NEW_MOVED_DIM]     = "newMovedDimmed",
+       [DIFF_FILE_NEW_MOVED_ALT_DIM] = "newMovedAlternativeDimmed",
+};
+
 static NORETURN void die_want_option(const char *option_name)
 {
        die(_("option '%s' requires a value"), option_name);
 }
 
+define_list_config_array_extra(color_diff_slots, {"plain"});
+
 static int parse_diff_color_slot(const char *var)
 {
-       if (!strcasecmp(var, "context") || !strcasecmp(var, "plain"))
+       if (!strcasecmp(var, "plain"))
                return DIFF_CONTEXT;
-       if (!strcasecmp(var, "meta"))
-               return DIFF_METAINFO;
-       if (!strcasecmp(var, "frag"))
-               return DIFF_FRAGINFO;
-       if (!strcasecmp(var, "old"))
-               return DIFF_FILE_OLD;
-       if (!strcasecmp(var, "new"))
-               return DIFF_FILE_NEW;
-       if (!strcasecmp(var, "commit"))
-               return DIFF_COMMIT;
-       if (!strcasecmp(var, "whitespace"))
-               return DIFF_WHITESPACE;
-       if (!strcasecmp(var, "func"))
-               return DIFF_FUNCINFO;
-       if (!strcasecmp(var, "oldmoved"))
-               return DIFF_FILE_OLD_MOVED;
-       if (!strcasecmp(var, "oldmovedalternative"))
-               return DIFF_FILE_OLD_MOVED_ALT;
-       if (!strcasecmp(var, "oldmoveddimmed"))
-               return DIFF_FILE_OLD_MOVED_DIM;
-       if (!strcasecmp(var, "oldmovedalternativedimmed"))
-               return DIFF_FILE_OLD_MOVED_ALT_DIM;
-       if (!strcasecmp(var, "newmoved"))
-               return DIFF_FILE_NEW_MOVED;
-       if (!strcasecmp(var, "newmovedalternative"))
-               return DIFF_FILE_NEW_MOVED_ALT;
-       if (!strcasecmp(var, "newmoveddimmed"))
-               return DIFF_FILE_NEW_MOVED_DIM;
-       if (!strcasecmp(var, "newmovedalternativedimmed"))
-               return DIFF_FILE_NEW_MOVED_ALT_DIM;
-       return -1;
+       return LOOKUP_CONFIG(color_diff_slots, var);
 }
 
 static int parse_dirstat_params(struct diff_options *options, const char *params_string,
index 0b7e498..d775183 100644 (file)
@@ -4,6 +4,7 @@
 #include "cache.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "object-store.h"
 #include "hashmap.h"
 #include "progress.h"
 
diff --git a/dir.c b/dir.c
index fe9bf58..a1fe57e 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -11,6 +11,7 @@
 #include "cache.h"
 #include "config.h"
 #include "dir.h"
+#include "object-store.h"
 #include "attr.h"
 #include "refs.h"
 #include "wildmatch.h"
diff --git a/entry.c b/entry.c
index 2101201..b5d1d3c 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "blob.h"
+#include "object-store.h"
 #include "dir.h"
 #include "streaming.h"
 #include "submodule.h"
index 2a6de23..013e845 100644 (file)
@@ -192,7 +192,7 @@ void setup_git_env(const char *git_dir)
        git_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
        shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
        if (shallow_file)
-               set_alternate_shallow_file(shallow_file, 0);
+               set_alternate_shallow_file(the_repository, shallow_file, 0);
 }
 
 int is_bare_repository(void)
@@ -319,11 +319,11 @@ char *get_index_file(void)
        return the_repository->index_file;
 }
 
-char *get_graft_file(void)
+char *get_graft_file(struct repository *r)
 {
-       if (!the_repository->graft_file)
+       if (!r->graft_file)
                BUG("git environment hasn't been setup");
-       return the_repository->graft_file;
+       return r->graft_file;
 }
 
 static void set_git_dir_1(const char *path)
index 756bdd0..52f1178 100644 (file)
@@ -45,14 +45,6 @@ void bitmap_set(struct bitmap *self, size_t pos)
        self->words[block] |= EWAH_MASK(pos);
 }
 
-void bitmap_clear(struct bitmap *self, size_t pos)
-{
-       size_t block = EWAH_BLOCK(pos);
-
-       if (block < self->word_alloc)
-               self->words[block] &= ~EWAH_MASK(pos);
-}
-
 int bitmap_get(struct bitmap *self, size_t pos)
 {
        size_t block = EWAH_BLOCK(pos);
@@ -137,30 +129,6 @@ void bitmap_or_ewah(struct bitmap *self, struct ewah_bitmap *other)
                self->words[i++] |= word;
 }
 
-void bitmap_each_bit(struct bitmap *self, ewah_callback callback, void *data)
-{
-       size_t pos = 0, i;
-
-       for (i = 0; i < self->word_alloc; ++i) {
-               eword_t word = self->words[i];
-               uint32_t offset;
-
-               if (word == (eword_t)~0) {
-                       for (offset = 0; offset < BITS_IN_EWORD; ++offset)
-                               callback(pos++, data);
-               } else {
-                       for (offset = 0; offset < BITS_IN_EWORD; ++offset) {
-                               if ((word >> offset) == 0)
-                                       break;
-
-                               offset += ewah_bit_ctz64(word >> offset);
-                               callback(pos + offset, data);
-                       }
-                       pos += BITS_IN_EWORD;
-               }
-       }
-}
-
 size_t bitmap_popcount(struct bitmap *self)
 {
        size_t i, count = 0;
index b9fdda1..d59b1af 100644 (file)
@@ -276,6 +276,18 @@ void ewah_each_bit(struct ewah_bitmap *self, void (*callback)(size_t, void*), vo
        }
 }
 
+/**
+ * Clear all the bits in the bitmap. Does not free or resize
+ * memory.
+ */
+static void ewah_clear(struct ewah_bitmap *self)
+{
+       self->buffer_size = 1;
+       self->buffer[0] = 0;
+       self->bit_size = 0;
+       self->rlw = self->buffer;
+}
+
 struct ewah_bitmap *ewah_new(void)
 {
        struct ewah_bitmap *self;
@@ -288,14 +300,6 @@ struct ewah_bitmap *ewah_new(void)
        return self;
 }
 
-void ewah_clear(struct ewah_bitmap *self)
-{
-       self->buffer_size = 1;
-       self->buffer[0] = 0;
-       self->bit_size = 0;
-       self->rlw = self->buffer;
-}
-
 void ewah_free(struct ewah_bitmap *self)
 {
        if (!self)
@@ -376,25 +380,6 @@ void ewah_iterator_init(struct ewah_iterator *it, struct ewah_bitmap *parent)
                read_new_rlw(it);
 }
 
-void ewah_not(struct ewah_bitmap *self)
-{
-       size_t pointer = 0;
-
-       while (pointer < self->buffer_size) {
-               eword_t *word = &self->buffer[pointer];
-               size_t literals, k;
-
-               rlw_xor_run_bit(word);
-               ++pointer;
-
-               literals = rlw_get_literal_words(word);
-               for (k = 0; k < literals; ++k) {
-                       self->buffer[pointer] = ~self->buffer[pointer];
-                       ++pointer;
-               }
-       }
-}
-
 void ewah_xor(
        struct ewah_bitmap *ewah_i,
        struct ewah_bitmap *ewah_j,
@@ -459,216 +444,6 @@ void ewah_xor(
        out->bit_size = max_size(ewah_i->bit_size, ewah_j->bit_size);
 }
 
-void ewah_and(
-       struct ewah_bitmap *ewah_i,
-       struct ewah_bitmap *ewah_j,
-       struct ewah_bitmap *out)
-{
-       struct rlw_iterator rlw_i;
-       struct rlw_iterator rlw_j;
-       size_t literals;
-
-       rlwit_init(&rlw_i, ewah_i);
-       rlwit_init(&rlw_j, ewah_j);
-
-       while (rlwit_word_size(&rlw_i) > 0 && rlwit_word_size(&rlw_j) > 0) {
-               while (rlw_i.rlw.running_len > 0 || rlw_j.rlw.running_len > 0) {
-                       struct rlw_iterator *prey, *predator;
-
-                       if (rlw_i.rlw.running_len < rlw_j.rlw.running_len) {
-                               prey = &rlw_i;
-                               predator = &rlw_j;
-                       } else {
-                               prey = &rlw_j;
-                               predator = &rlw_i;
-                       }
-
-                       if (predator->rlw.running_bit == 0) {
-                               ewah_add_empty_words(out, 0,
-                                       predator->rlw.running_len);
-                               rlwit_discard_first_words(prey,
-                                       predator->rlw.running_len);
-                               rlwit_discard_first_words(predator,
-                                       predator->rlw.running_len);
-                       } else {
-                               size_t index = rlwit_discharge(prey, out,
-                                       predator->rlw.running_len, 0);
-                               ewah_add_empty_words(out, 0,
-                                       predator->rlw.running_len - index);
-                               rlwit_discard_first_words(predator,
-                                       predator->rlw.running_len);
-                       }
-               }
-
-               literals = min_size(
-                       rlw_i.rlw.literal_words,
-                       rlw_j.rlw.literal_words);
-
-               if (literals) {
-                       size_t k;
-
-                       for (k = 0; k < literals; ++k) {
-                               ewah_add(out,
-                                       rlw_i.buffer[rlw_i.literal_word_start + k] &
-                                       rlw_j.buffer[rlw_j.literal_word_start + k]
-                               );
-                       }
-
-                       rlwit_discard_first_words(&rlw_i, literals);
-                       rlwit_discard_first_words(&rlw_j, literals);
-               }
-       }
-
-       if (rlwit_word_size(&rlw_i) > 0)
-               rlwit_discharge_empty(&rlw_i, out);
-       else
-               rlwit_discharge_empty(&rlw_j, out);
-
-       out->bit_size = max_size(ewah_i->bit_size, ewah_j->bit_size);
-}
-
-void ewah_and_not(
-       struct ewah_bitmap *ewah_i,
-       struct ewah_bitmap *ewah_j,
-       struct ewah_bitmap *out)
-{
-       struct rlw_iterator rlw_i;
-       struct rlw_iterator rlw_j;
-       size_t literals;
-
-       rlwit_init(&rlw_i, ewah_i);
-       rlwit_init(&rlw_j, ewah_j);
-
-       while (rlwit_word_size(&rlw_i) > 0 && rlwit_word_size(&rlw_j) > 0) {
-               while (rlw_i.rlw.running_len > 0 || rlw_j.rlw.running_len > 0) {
-                       struct rlw_iterator *prey, *predator;
-
-                       if (rlw_i.rlw.running_len < rlw_j.rlw.running_len) {
-                               prey = &rlw_i;
-                               predator = &rlw_j;
-                       } else {
-                               prey = &rlw_j;
-                               predator = &rlw_i;
-                       }
-
-                       if ((predator->rlw.running_bit && prey == &rlw_i) ||
-                               (!predator->rlw.running_bit && prey != &rlw_i)) {
-                               ewah_add_empty_words(out, 0,
-                                       predator->rlw.running_len);
-                               rlwit_discard_first_words(prey,
-                                       predator->rlw.running_len);
-                               rlwit_discard_first_words(predator,
-                                       predator->rlw.running_len);
-                       } else {
-                               size_t index;
-                               int negate_words;
-
-                               negate_words = (&rlw_i != prey);
-                               index = rlwit_discharge(prey, out,
-                                       predator->rlw.running_len, negate_words);
-                               ewah_add_empty_words(out, negate_words,
-                                       predator->rlw.running_len - index);
-                               rlwit_discard_first_words(predator,
-                                       predator->rlw.running_len);
-                       }
-               }
-
-               literals = min_size(
-                       rlw_i.rlw.literal_words,
-                       rlw_j.rlw.literal_words);
-
-               if (literals) {
-                       size_t k;
-
-                       for (k = 0; k < literals; ++k) {
-                               ewah_add(out,
-                                       rlw_i.buffer[rlw_i.literal_word_start + k] &
-                                       ~(rlw_j.buffer[rlw_j.literal_word_start + k])
-                               );
-                       }
-
-                       rlwit_discard_first_words(&rlw_i, literals);
-                       rlwit_discard_first_words(&rlw_j, literals);
-               }
-       }
-
-       if (rlwit_word_size(&rlw_i) > 0)
-               rlwit_discharge(&rlw_i, out, ~0, 0);
-       else
-               rlwit_discharge_empty(&rlw_j, out);
-
-       out->bit_size = max_size(ewah_i->bit_size, ewah_j->bit_size);
-}
-
-void ewah_or(
-       struct ewah_bitmap *ewah_i,
-       struct ewah_bitmap *ewah_j,
-       struct ewah_bitmap *out)
-{
-       struct rlw_iterator rlw_i;
-       struct rlw_iterator rlw_j;
-       size_t literals;
-
-       rlwit_init(&rlw_i, ewah_i);
-       rlwit_init(&rlw_j, ewah_j);
-
-       while (rlwit_word_size(&rlw_i) > 0 && rlwit_word_size(&rlw_j) > 0) {
-               while (rlw_i.rlw.running_len > 0 || rlw_j.rlw.running_len > 0) {
-                       struct rlw_iterator *prey, *predator;
-
-                       if (rlw_i.rlw.running_len < rlw_j.rlw.running_len) {
-                               prey = &rlw_i;
-                               predator = &rlw_j;
-                       } else {
-                               prey = &rlw_j;
-                               predator = &rlw_i;
-                       }
-
-                       if (predator->rlw.running_bit) {
-                               ewah_add_empty_words(out, 0,
-                                       predator->rlw.running_len);
-                               rlwit_discard_first_words(prey,
-                                       predator->rlw.running_len);
-                               rlwit_discard_first_words(predator,
-                                       predator->rlw.running_len);
-                       } else {
-                               size_t index = rlwit_discharge(prey, out,
-                                       predator->rlw.running_len, 0);
-                               ewah_add_empty_words(out, 0,
-                                       predator->rlw.running_len - index);
-                               rlwit_discard_first_words(predator,
-                                       predator->rlw.running_len);
-                       }
-               }
-
-               literals = min_size(
-                       rlw_i.rlw.literal_words,
-                       rlw_j.rlw.literal_words);
-
-               if (literals) {
-                       size_t k;
-
-                       for (k = 0; k < literals; ++k) {
-                               ewah_add(out,
-                                       rlw_i.buffer[rlw_i.literal_word_start + k] |
-                                       rlw_j.buffer[rlw_j.literal_word_start + k]
-                               );
-                       }
-
-                       rlwit_discard_first_words(&rlw_i, literals);
-                       rlwit_discard_first_words(&rlw_j, literals);
-               }
-       }
-
-       if (rlwit_word_size(&rlw_i) > 0)
-               rlwit_discharge(&rlw_i, out, ~0, 0);
-       else
-               rlwit_discharge(&rlw_j, out, ~0, 0);
-
-       out->bit_size = max_size(ewah_i->bit_size, ewah_j->bit_size);
-}
-
-
 #define BITMAP_POOL_MAX 16
 static struct ewah_bitmap *bitmap_pool[BITMAP_POOL_MAX];
 static size_t bitmap_pool_size;
index 33c08c4..9035ee6 100644 (file)
 #include "ewok.h"
 #include "strbuf.h"
 
-int ewah_serialize_native(struct ewah_bitmap *self, int fd)
-{
-       uint32_t write32;
-       size_t to_write = self->buffer_size * 8;
-
-       /* 32 bit -- bit size for the map */
-       write32 = (uint32_t)self->bit_size;
-       if (write(fd, &write32, 4) != 4)
-               return -1;
-
-       /** 32 bit -- number of compressed 64-bit words */
-       write32 = (uint32_t)self->buffer_size;
-       if (write(fd, &write32, 4) != 4)
-               return -1;
-
-       if (write(fd, self->buffer, to_write) != to_write)
-               return -1;
-
-       /** 32 bit -- position for the RLW */
-       write32 = self->rlw - self->buffer;
-       if (write(fd, &write32, 4) != 4)
-               return -1;
-
-       return (3 * 4) + to_write;
-}
-
 int ewah_serialize_to(struct ewah_bitmap *self,
                      int (*write_fun)(void *, const void *, size_t),
                      void *data)
@@ -100,16 +74,6 @@ int ewah_serialize_to(struct ewah_bitmap *self,
        return (3 * 4) + (self->buffer_size * 8);
 }
 
-static int write_helper(void *fd, const void *buf, size_t len)
-{
-       return write((intptr_t)fd, buf, len);
-}
-
-int ewah_serialize(struct ewah_bitmap *self, int fd)
-{
-       return ewah_serialize_to(self, write_helper, (void *)(intptr_t)fd);
-}
-
 static int write_strbuf(void *user_data, const void *data, size_t len)
 {
        struct strbuf *sb = user_data;
@@ -168,58 +132,3 @@ ssize_t ewah_read_mmap(struct ewah_bitmap *self, const void *map, size_t len)
 
        return ptr - (const uint8_t *)map;
 }
-
-int ewah_deserialize(struct ewah_bitmap *self, int fd)
-{
-       size_t i;
-       eword_t dump[2048];
-       const size_t words_per_dump = sizeof(dump) / sizeof(eword_t);
-       uint32_t bitsize, word_count, rlw_pos;
-
-       eword_t *buffer = NULL;
-       size_t words_left;
-
-       ewah_clear(self);
-
-       /* 32 bit -- bit size for the map */
-       if (read(fd, &bitsize, 4) != 4)
-               return -1;
-
-       self->bit_size = (size_t)ntohl(bitsize);
-
-       /** 32 bit -- number of compressed 64-bit words */
-       if (read(fd, &word_count, 4) != 4)
-               return -1;
-
-       self->buffer_size = self->alloc_size = (size_t)ntohl(word_count);
-       REALLOC_ARRAY(self->buffer, self->alloc_size);
-
-       /** 64 bit x N -- compressed words */
-       buffer = self->buffer;
-       words_left = self->buffer_size;
-
-       while (words_left >= words_per_dump) {
-               if (read(fd, dump, sizeof(dump)) != sizeof(dump))
-                       return -1;
-
-               for (i = 0; i < words_per_dump; ++i, ++buffer)
-                       *buffer = ntohll(dump[i]);
-
-               words_left -= words_per_dump;
-       }
-
-       if (words_left) {
-               if (read(fd, dump, words_left * 8) != words_left * 8)
-                       return -1;
-
-               for (i = 0; i < words_left; ++i, ++buffer)
-                       *buffer = ntohll(dump[i]);
-       }
-
-       /** 32 bit -- position for the RLW */
-       if (read(fd, &rlw_pos, 4) != 4)
-               return -1;
-
-       self->rlw = self->buffer + ntohl(rlw_pos);
-       return 0;
-}
index b9643b7..5093d43 100644 (file)
@@ -104,11 +104,3 @@ size_t rlwit_discharge(
 
        return index;
 }
-
-void rlwit_discharge_empty(struct rlw_iterator *it, struct ewah_bitmap *out)
-{
-       while (rlwit_word_size(it) > 0) {
-               ewah_add_empty_words(out, 0, rlwit_word_size(it));
-               rlwit_discard_first_words(it, rlwit_word_size(it));
-       }
-}
index 357fd93..84b2a29 100644 (file)
@@ -72,12 +72,6 @@ void ewah_pool_free(struct ewah_bitmap *self);
  */
 struct ewah_bitmap *ewah_new(void);
 
-/**
- * Clear all the bits in the bitmap. Does not free or resize
- * memory.
- */
-void ewah_clear(struct ewah_bitmap *self);
-
 /**
  * Free all the memory of the bitmap
  */
@@ -86,22 +80,12 @@ void ewah_free(struct ewah_bitmap *self);
 int ewah_serialize_to(struct ewah_bitmap *self,
                      int (*write_fun)(void *out, const void *buf, size_t len),
                      void *out);
-int ewah_serialize(struct ewah_bitmap *self, int fd);
-int ewah_serialize_native(struct ewah_bitmap *self, int fd);
 int ewah_serialize_strbuf(struct ewah_bitmap *self, struct strbuf *);
 
-int ewah_deserialize(struct ewah_bitmap *self, int fd);
 ssize_t ewah_read_mmap(struct ewah_bitmap *self, const void *map, size_t len);
 
 uint32_t ewah_checksum(struct ewah_bitmap *self);
 
-/**
- * Logical not (bitwise negation) in-place on the bitmap
- *
- * This operation is linear time based on the size of the bitmap.
- */
-void ewah_not(struct ewah_bitmap *self);
-
 /**
  * Call the given callback with the position of every single bit
  * that has been set on the bitmap.
@@ -164,26 +148,11 @@ void ewah_iterator_init(struct ewah_iterator *it, struct ewah_bitmap *parent);
  */
 int ewah_iterator_next(eword_t *next, struct ewah_iterator *it);
 
-void ewah_or(
-       struct ewah_bitmap *ewah_i,
-       struct ewah_bitmap *ewah_j,
-       struct ewah_bitmap *out);
-
-void ewah_and_not(
-       struct ewah_bitmap *ewah_i,
-       struct ewah_bitmap *ewah_j,
-       struct ewah_bitmap *out);
-
 void ewah_xor(
        struct ewah_bitmap *ewah_i,
        struct ewah_bitmap *ewah_j,
        struct ewah_bitmap *out);
 
-void ewah_and(
-       struct ewah_bitmap *ewah_i,
-       struct ewah_bitmap *ewah_j,
-       struct ewah_bitmap *out);
-
 /**
  * Direct word access
  */
@@ -204,7 +173,6 @@ struct bitmap {
 
 struct bitmap *bitmap_new(void);
 void bitmap_set(struct bitmap *self, size_t pos);
-void bitmap_clear(struct bitmap *self, size_t pos);
 int bitmap_get(struct bitmap *self, size_t pos);
 void bitmap_reset(struct bitmap *self);
 void bitmap_free(struct bitmap *self);
@@ -218,7 +186,6 @@ void bitmap_and_not(struct bitmap *self, struct bitmap *other);
 void bitmap_or_ewah(struct bitmap *self, struct ewah_bitmap *other);
 void bitmap_or(struct bitmap *self, const struct bitmap *other);
 
-void bitmap_each_bit(struct bitmap *self, ewah_callback callback, void *data);
 size_t bitmap_popcount(struct bitmap *self);
 
 #endif
index bb3c6ff..7cdfdd0 100644 (file)
@@ -98,7 +98,6 @@ void rlwit_init(struct rlw_iterator *it, struct ewah_bitmap *bitmap);
 void rlwit_discard_first_words(struct rlw_iterator *it, size_t x);
 size_t rlwit_discharge(
        struct rlw_iterator *it, struct ewah_bitmap *out, size_t max, int negate);
-void rlwit_discharge_empty(struct rlw_iterator *it, struct ewah_bitmap *out);
 
 static inline size_t rlwit_word_size(struct rlw_iterator *it)
 {
index a320ce9..dbd879a 100644 (file)
@@ -19,6 +19,7 @@
 #include "sha1-array.h"
 #include "oidset.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static int transfer_unpack_limit = -1;
 static int fetch_unpack_limit = -1;
@@ -396,7 +397,7 @@ static int find_common(struct fetch_pack_args *args,
                return 1;
        }
 
-       if (is_repository_shallow())
+       if (is_repository_shallow(the_repository))
                write_shallow_commits(&req_buf, 1, NULL);
        if (args->depth > 0)
                packet_buf_write(&req_buf, "deepen %d", args->depth);
@@ -427,7 +428,7 @@ static int find_common(struct fetch_pack_args *args,
                        if (skip_prefix(line, "shallow ", &arg)) {
              &