Merge branch 'ab/wildmatch'
authorJunio C Hamano <gitster@pobox.com>
Mon, 10 Jul 2017 20:42:51 +0000 (13:42 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Jul 2017 20:42:51 +0000 (13:42 -0700)
Minor code cleanup.

* ab/wildmatch:
wildmatch: remove unused wildopts parameter

267 files changed:
.gitmodules [new file with mode: 0644]
Documentation/RelNotes/1.7.10.1.txt
Documentation/RelNotes/2.12.0.txt
Documentation/RelNotes/2.13.2.txt
Documentation/RelNotes/2.14.0.txt
Documentation/config.txt
Documentation/git-add.txt
Documentation/git-pull.txt
Documentation/git-rebase.txt
Documentation/git-reset.txt
Documentation/git-send-email.txt
Documentation/git-stash.txt
Documentation/git-status.txt
Documentation/git-submodule.txt
Documentation/gitattributes.txt
Documentation/gitcli.txt
Documentation/glossary-content.txt
Documentation/pretty-formats.txt
Makefile
abspath.c
advice.c
advice.h
alias.c
apply.c
archive-tar.c
archive-zip.c
archive.c
attr.c
bisect.c
blame.c
branch.c
builtin/add.c
builtin/am.c
builtin/blame.c
builtin/branch.c
builtin/cat-file.c
builtin/check-attr.c
builtin/check-ignore.c
builtin/check-mailmap.c
builtin/checkout-index.c
builtin/checkout.c
builtin/clean.c
builtin/clone.c
builtin/column.c
builtin/commit-tree.c
builtin/commit.c
builtin/config.c
builtin/count-objects.c
builtin/describe.c
builtin/diff-files.c
builtin/diff-index.c
builtin/diff-tree.c
builtin/diff.c
builtin/difftool.c
builtin/fast-export.c
builtin/fetch.c
builtin/fmt-merge-msg.c
builtin/for-each-ref.c
builtin/fsck.c
builtin/gc.c
builtin/grep.c
builtin/hash-object.c
builtin/help.c
builtin/index-pack.c
builtin/init-db.c
builtin/log.c
builtin/ls-files.c
builtin/ls-tree.c
builtin/merge-base.c
builtin/merge-file.c
builtin/merge.c
builtin/mv.c
builtin/name-rev.c
builtin/notes.c
builtin/pack-objects.c
builtin/patch-id.c
builtin/prune-packed.c
builtin/prune.c
builtin/pull.c
builtin/push.c
builtin/read-tree.c
builtin/rebase--helper.c
builtin/receive-pack.c
builtin/reflog.c
builtin/remote.c
builtin/repack.c
builtin/replace.c
builtin/rerere.c
builtin/reset.c
builtin/rev-list.c
builtin/rev-parse.c
builtin/revert.c
builtin/rm.c
builtin/send-pack.c
builtin/shortlog.c
builtin/show-branch.c
builtin/stripspace.c
builtin/submodule--helper.c
builtin/symbolic-ref.c
builtin/tag.c
builtin/unpack-file.c
builtin/unpack-objects.c
builtin/update-index.c
builtin/update-ref.c
builtin/update-server-info.c
builtin/var.c
builtin/verify-commit.c
builtin/verify-pack.c
builtin/verify-tag.c
builtin/worktree.c
builtin/write-tree.c
cache.h
color.c
column.c
combine-diff.c
commit-slab.h
commit.c
compat/precompose_utf8.c
compat/regex/regexec.c
config.c
config.h [new file with mode: 0644]
connect.c
contrib/coccinelle/free.cocci
contrib/completion/git-completion.bash
contrib/diff-highlight/.gitignore [new file with mode: 0644]
contrib/diff-highlight/DiffHighlight.pm [new file with mode: 0644]
contrib/diff-highlight/Makefile
contrib/diff-highlight/README
contrib/diff-highlight/diff-highlight [deleted file]
contrib/diff-highlight/diff-highlight.perl [new file with mode: 0644]
contrib/hooks/multimail/git_multimail.py
contrib/mw-to-git/git-remote-mediawiki.perl
contrib/mw-to-git/t/README
contrib/subtree/Makefile
convert.c
convert.h
credential-cache--daemon.c
credential.c
daemon.c
date.c
diff-lib.c
diff.c
diffcore-rename.c
dir.c
environment.c
fast-import.c
fetch-pack.c
git-add--interactive.perl
git-compat-util.h
git-rebase.sh
git-send-email.perl
git-stash.sh
git-submodule.sh
git.c
gitweb/gitweb.perl
gpg-interface.c
graph.c
grep.c
hash.h
help.c
http-backend.c
http-fetch.c
http-push.c
http.c
ident.c
imap-send.c
line-log.c
ll-merge.c
log-tree.c
mailinfo.c
merge-recursive.c
mergetools/meld
notes-utils.c
notes.c
object.c
pack-bitmap.c
pager.c
parse-options.c
path.c
path.h [new file with mode: 0644]
pathspec.c
perl/Git.pm
perl/Git/I18N.pm
pretty.c
prio-queue.c
prompt.c
read-cache.c
ref-filter.c
refs.c
refs.h
refs/files-backend.c
refs/ref-cache.c
remote-curl.c
remote-testsvn.c
remote.c
repository.c [new file with mode: 0644]
repository.h [new file with mode: 0644]
rerere.c
revision.c
send-pack.c
sequencer.c
setup.c
sha1-array.c
sha1_file.c
sha1_name.c
sha1collisiondetection [new submodule]
sha1dc/sha1.c
split-index.c
split-index.h
strbuf.c
strbuf.h
submodule-config.c
submodule-config.h
submodule.c
submodule.h
t/helper/test-config.c
t/helper/test-strcmp-offset.c
t/helper/test-submodule-config.c
t/perf/p4205-log-pretty-formats.sh [new file with mode: 0755]
t/t1300-repo-config.sh
t/t1301-shared-repo.sh
t/t1308-config-set.sh
t/t1450-fsck.sh
t/t1700-split-index.sh
t/t2203-add-intent.sh
t/t3007-ls-files-recurse-submodules.sh
t/t3070-wildmatch.sh
t/t3404-rebase-interactive.sh
t/t3420-rebase-autostash.sh
t/t3701-add-interactive.sh
t/t4041-diff-submodule-option.sh
t/t4060-diff-submodule-option-diff-format.sh
t/t4129-apply-samemode.sh
t/t4133-apply-filenames.sh
t/t4136-apply-check.sh
t/t4213-log-tabexpand.sh
t/t5534-push-signed.sh
t/t5614-clone-submodules-shallow.sh
t/t6002-rev-list-bisect.sh
t/t6120-describe.sh
t/t7006-pager.sh
t/t7401-submodule-summary.sh
t/t7412-submodule-absorbgitdirs.sh
t/t7413-submodule-is-active.sh
t/t7414-submodule-mistakes.sh [new file with mode: 0755]
t/t7500-commit.sh
t/t7501-commit.sh
t/t7508-status.sh
t/t9300-fast-import.sh
t/t9700/test.pl
t/test-lib-functions.sh
trailer.c
transport-helper.c
transport.c
tree-diff.c
tree.c
tree.h
unpack-trees.c
upload-pack.c
usage.c
userdiff.c
versioncmp.c
worktree.c
wrapper.c
wt-status.c
wt-status.h
xdiff-interface.c
diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..cbeebda
--- /dev/null
@@ -0,0 +1,4 @@
+[submodule "sha1collisiondetection"]
+       path = sha1collisiondetection
+       url = https://github.com/cr-marcstevens/sha1collisiondetection.git
+       branch = master
index be68524cff388af3540db1f3237c417da3b84a35..71a86cb7c6d87ff60bce1f91504cca03511e4e56 100644 (file)
@@ -69,7 +69,7 @@ Fixes since v1.7.10
  * The 'push to upstream' implementation was broken in some corner
    cases. "git push $there" without refspec, when the current branch
    is set to push to a remote different from $there, used to push to
-   $there using the upstream information to a remote unreleated to
+   $there using the upstream information to a remote unrelated to
    $there.
 
  * Giving "--continue" to a conflicted "rebase -i" session skipped a
index 29154805b4e56010955d961726cfda4c8325eca2..ef8b97da9b84342422cc2519a78e782f264c339d 100644 (file)
@@ -264,7 +264,7 @@ notes for details).
    needed it so far.
 
  * Git 2.11 had a minor regression in "merge --ff-only" that competed
-   with another process that simultanously attempted to update the
+   with another process that simultaneously attempted to update the
    index. We used to explain what went wrong with an error message,
    but the new code silently failed.  The error message has been
    resurrected.
index c8ba0fa16f4904c421c878b53163c8095abf7f17..8c2b20071ed2bb04789f0957a548db9c2bfad7d7 100644 (file)
@@ -34,4 +34,21 @@ Fixes since v2.13.1
  * "git pull --rebase --autostash" didn't auto-stash when the local history
    fast-forwards to the upstream.
 
+ * "git describe --contains" penalized light-weight tags so much that
+   they were almost never considered.  Instead, give them about the
+   same chance to be considered as an annotated tag that is the same
+   age as the underlying commit would.
+
+ * The result from "git diff" that compares two blobs, e.g. "git diff
+   $commit1:$path $commit2:$path", used to be shown with the full
+   object name as given on the command line, but it is more natural to
+   use the $path in the output and use it to look up .gitattributes.
+
+ * A flaky test has been corrected.
+
+ * Help contributors that visit us at GitHub.
+
+ * "git stash push <pathspec>" did not work from a subdirectory at all.
+   Bugfix for a topic in v2.13
+
 Also contains various documentation updates and code clean-ups.
index 9c252cdc4ff835b58412c259aabf513c8ed6b516..2228035ad3328de40b5c8e99c59dcf4d23d46973 100644 (file)
@@ -38,26 +38,23 @@ UI, Workflows & Features
 
  * "git archive --format=zip" learned to use zip64 extension when
    necessary to go beyond the 4GB limit.
-   (merge 867e40ff3a rs/large-zip later to maint).
 
  * "git reset" learned "--recurse-submodules" option.
 
  * "git diff --submodule=diff" now recurses into nested submodules.
-   (merge 5a5221427c jk/diff-submodule-diff-inline later to maint).
 
  * "git repack" learned to accept the --threads=<n> option and pass it
    to pack-objects.
 
  * "git send-email" learned to run sendemail-validate hook to inspect
    and reject a message before sending it out.
-   (merge 177409e589 jt/send-email-validate-hook later to maint).
 
  * There is no good reason why "git fetch $there $sha1" should fail
    when the $sha1 names an object at the tip of an advertised ref,
    even when the other side hasn't enabled allowTipSHA1InWant.
 
  * The recently introduced "[includeIf "gitdir:$dir"] path=..."
-   mechansim has further been taught to take symlinks into account.
+   mechanism has further been taught to take symlinks into account.
    The directory "$dir" specified in "gitdir:$dir" may be a symlink to
    a real location, not something that $(getcwd) may return.  In such
    a case, a realpath of "$dir" is compared with the real path of the
@@ -81,15 +78,33 @@ UI, Workflows & Features
    required disambiguation more often.  The command line parser
    learned to say "it's a pathspec" a bit more often when the syntax
    looks like so.
-   (merge 2cb47ab695 jk/pathspec-magic-disambiguation later to maint).
 
  * Update "perl-compatible regular expression" support to enable JIT
    and also allow linking with the newer PCRE v2 library.
 
  * "filter-branch" learned a pseudo filter "--setup" that can be used
-   to define a common function/variable that can be used by other
+   to define common functions/variables that can be used by other
    filters.
 
+ * Using "git add d/i/r" when d/i/r is the top of the working tree of
+   a separate repository would create a gitlink in the index, which
+   would appear as a not-quite-initialized submodule to others.  We
+   learned to give warnings when this happens.
+
+ * "git status" learned to optionally give how many stash entries the
+   user has in its output.
+
+ * "git status" has long shown essentially the same message as "git
+   commit"; the message it gives while preparing for the root commit,
+   i.e. "Initial commit", was hard to understand for some new users.
+   Now it says "No commits yet" to stress more on the current status
+   (rather than the commit the user is preparing for, which is more in
+   line with the focus of "git commit").
+
+ * "git send-email" learned to overcome some SMTP server limitation
+   that does not allow many pieces of e-mails to be sent over a single
+   session.
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -99,7 +114,6 @@ Performance, Internal Implementation, Development Support etc.
 
  * Code to update the cache-tree has been tightened so that we won't
    accidentally write out any 0{40} entry in the tree object.
-   (merge a96d3cc3f6 jk/no-null-sha1-in-cache-tree later to maint).
 
  * Attempt to allow us notice "fishy" situation where we fail to
    remove the temporary directory used during the test.
@@ -122,14 +136,11 @@ Performance, Internal Implementation, Development Support etc.
 
  * Simplify parse_pathspec() codepath and stop it from looking at the
    default in-core index.
-   (merge 08de9151a8 bw/pathspec-sans-the-index later to maint).
 
  * Add perf-test for wildmatch.
-   (merge 62ca75a6b9 ab/perf-wildmatch later to maint).
 
  * Code from "conversion using external process" codepath has been
    extracted to a separate sub-process.[ch] module.
-   (merge 4f2a2e9f0e bp/sub-process-convert-filter later to maint).
 
  * When "git checkout", "git merge", etc. manipulates the in-core
    index, various pieces of information in the index extensions are
@@ -140,7 +151,6 @@ Performance, Internal Implementation, Development Support etc.
    cache is properly invalidated).
 
  * The internal implementation of "git grep" has seen some clean-up.
-   (merge 8df4c2953f ab/grep-preparatory-cleanup later to maint).
 
  * Update the C style recommendation for notes for translators, as
    recent versions of gettext tools can work with our style of
@@ -174,11 +184,37 @@ Performance, Internal Implementation, Development Support etc.
 
  * Three instances of the same helper function have been consolidated
    to one.
-   (merge e0556a928f pc/dir-count-slashes later to maint).
 
  * "fast-import" uses a default pack chain depth that is consistent
    with other parts of the system.
 
+ * A new test to show the interaction between the pattern [^a-z]
+   (which matches '/') and a slash in a path has been added.  The
+   pattern should not match the slash with "pathmatch", but should
+   with "wildmatch".
+
+ * The 'diff-highlight' program (in contrib/) has been restructured
+   for easier reuse by an external project 'diff-so-fancy'.
+   (merge 0c977dbc81 jk/diff-highlight-module later to maint).
+
+ * A common pattern to free a piece of memory and assign NULL to the
+   pointer that used to point at it has been replaced with a new
+   FREE_AND_NULL() macro.
+
+ * Traditionally, the default die() routine had a code to prevent it
+   from getting called multiple times, which interacted badly when a
+   threaded program used it (one downside is that the real error may
+   be hidden and instead the only error message given to the user may
+   end up being "die recursion detected", which is not very useful).
+
+ * Introduce a "repository" object to eventually make it easier to
+   work in multiple repositories (the primary focus is to work with
+   the superproject and its submodules) in a single process.
+
+ * Optimize "what are the object names already taken in an alternate
+   object database?" query that is used to derive the length of prefix
+   an object name is uniquely abbreviated to.
+
 
 Also contains various documentation updates and code clean-ups.
 
@@ -227,11 +263,6 @@ notes for details).
  * "git checkout --recurse-submodules" did not quite work with a
    submodule that itself has submodules.
 
- * Plug some leaks and updates internal API used to implement the
-   split index feature to make it easier to avoid such a leak in the
-   future.
-   (merge de950c5773 nd/split-index-unshare later to maint).
-
  * "pack-objects" can stream a slice of an existing packfile out when
    the pack bitmap can tell that the reachable objects are all needed
    in the output, without inspecting individual objects.  This
@@ -293,7 +324,6 @@ notes for details).
    they were almost never considered.  Instead, give them about the
    same chance to be considered as an annotated tag that is the same
    age as the underlying commit would.
-   (merge ef1e74065c jc/name-rev-lw-tag later to maint).
 
  * The "run-command" API implementation has been made more robust
    against dead-locking in a threaded environment.
@@ -319,7 +349,6 @@ notes for details).
    $commit1:$path $commit2:$path", used to be shown with the full
    object name as given on the command line, but it is more natural to
    use the $path in the output and use it to look up .gitattributes.
-   (merge 30d005c020 jk/diff-blob later to maint).
 
  * The "collision detecting" SHA-1 implementation shipped with 2.13
    was quite broken on some big-endian platforms and/or platforms that
@@ -340,7 +369,6 @@ notes for details).
    fast-forwards to the upstream.
 
  * A flaky test has been corrected.
-   (merge 7c2115aa07 jk/pack-idx-corruption-safety later to maint).
 
  * "git $cmd -h" for builtin commands calls the implementation of the
    command (i.e. cmd_$cmd() function) without doing any repository
@@ -349,11 +377,9 @@ notes for details).
    (merge d691551192 jk/consistent-h later to maint).
 
  * Help contributors that visit us at GitHub.
-   (merge 0b1bb0c032 ls/github later to maint).
 
  * "git stash push <pathspec>" did not work from a subdirectory at all.
    Bugfix for a topic in v2.13
-   (merge 22fc703ec9 ps/stash-push-pathspec-fix later to maint).
 
  * As there is no portable way to pass timezone information to
    strftime, some output format from "git log" and friends are
@@ -361,10 +387,72 @@ notes for details).
    and %Z with caller-supplied values to help working around this.
    (merge 6eced3ec5e rs/strbuf-addftime-zZ later to maint).
 
+ * "git mergetool" learned to work around a wrapper MacOS X adds
+   around underlying meld.
+   (merge 0af85f84bd da/mergetools-meld-output-opt-on-macos later to maint).
+
+ * An example in documentation that does not work in multi worktree
+   configuration has been corrected.
+   (merge 773a88914f ah/doc-gitattributes-empty-index later to maint).
+
+ * The pretty-format specifiers like '%h', '%t', etc. had an
+   optimization that no longer works correctly.  In preparation/hope
+   of getting it correctly implemented, first discard the optimization
+   that is broken.
+   (merge fe9e2aefd4 rs/pretty-add-again later to maint).
+
+ * The code to pick up and execute command alias definition from the
+   configuration used to switch to the top of the working tree and
+   then come back when the expanded alias was executed, which was
+   unnecessarilyl complex.  Attempt to simplify the logic by using the
+   early-config mechanism that does not chdir around.
+   (merge a9bcf6586d js/alias-early-config later to maint).
+
+ * Fix configuration codepath to pay proper attention to commondir
+   that is used in multi-worktree situation, and isolate config API
+   into its own header file.
+   (merge dc8441fdb4 bw/config-h later to maint).
+
+ * "git add -p" were updated in 2.12 timeframe to cope with custom
+   core.commentchar but the implementation was buggy and a
+   metacharacter like $ and * did not work.
+   (merge d85d7ecb80 jk/add-p-commentchar-fix later to maint).
+
+ * A recent regression in "git rebase -i" has been fixed and tests
+   that would have caught it and others have been added.
+   (merge adf16c08cb pw/rebase-i-regression-fix-tests later to maint).
+
+ * An unaligned 32-bit access in pack-bitmap code ahs been corrected.
+   (merge da41c942b3 jc/pack-bitmap-unaligned later to maint).
+
+ * Tighten error checks for invalid "git apply" input.
+   (merge d70e9c5c8c rs/apply-validate-input later to maint).
+
+ * The split index code did not honor core.sharedrepository setting
+   correctly.
+   (merge 3ee83f48e5 cc/shared-index-permfix later to maint).
+
+ * The Makefile rule in contrib/subtree for building documentation
+   learned to honour USE_ASCIIDOCTOR just like the main documentation
+   set does.
+   (merge fdc1ad97c1 aw/contrib-subtree-doc-asciidoctor later to maint).
+
+ * Update the sha1dc again to fix portability glitches.
+   (merge 9936c1b52a ab/sha1dc-maint later to maint).
+
+ * Code clean-up to fix possible buffer over-reading.
+   (merge 8bc172e5f2 rs/apply-avoid-over-reading later to maint).
+
+ * A few tests that tried to verify the contents of push certificates
+   did not use 'git rev-parse' to formulate the line to look for in
+   the certificate correctly.
+   (merge 8722947e5c js/t5534-rev-parse-gives-multi-line-output-fix later to maint).
+
  * Other minor doc, test and build updates and code cleanups.
-   (merge 8ba74bfd7c jc/diff-tree-stale-comment later to maint).
-   (merge 68602c01fd sb/submodule-rm-absorb later to maint).
    (merge 68241cb9dd sb/t4005-modernize later to maint).
-   (merge ae52d57f0b km/test-mailinfo-b-failure later to maint).
-   (merge 8b1d9136e1 sg/revision-parser-skip-prefix later to maint).
-   (merge bb8efa1772 sd/t3200-branch-m-test later to maint).
+   (merge 4fced24712 ks/t7508-indent-fix later to maint).
+   (merge 968b1fe263 mb/reword-autocomplete-message later to maint).
+   (merge 8592c95cdf ah/doc-pretty-color-auto-prefix later to maint).
+   (merge 73fc2aadc7 js/fsck-name-object later to maint).
+   (merge dc4b4a61ba jc/utf8-fprintf later to maint).
+   (merge c2d4b4cd06 sb/merge-recursive-code-cleanup later to maint).
index f6278a5ae6a1f554ddb8b9861d9067181b928bb5..d5c9c4cab60531d178d5c11d623a5c3f1036a0d0 100644 (file)
@@ -348,6 +348,9 @@ advice.*::
        rmHints::
                In case of failure in the output of linkgit:git-rm[1],
                show directions on how to proceed from the current state.
+       addEmbeddedRepo::
+               Advice on what to do when you've accidentally added one
+               git repo inside of another.
 --
 
 core.fileMode::
@@ -683,7 +686,8 @@ core.packedGitLimit::
        bytes at once to complete an operation it will unmap existing
        regions to reclaim virtual address space within the process.
 +
-Default is 256 MiB on 32 bit platforms and 8 GiB on 64 bit platforms.
+Default is 256 MiB on 32 bit platforms and 32 TiB (effectively
+unlimited) on 64 bit platforms.
 This should be reasonable for all users/operating systems, except on
 the largest projects.  You probably do not need to adjust this value.
 +
@@ -2620,7 +2624,7 @@ rebase.autoSquash::
        If set to true enable `--autosquash` option by default.
 
 rebase.autoStash::
-       When set to true, automatically create a temporary stash
+       When set to true, automatically create a temporary stash entry
        before the operation begins, and apply it after the operation
        ends.  This means that you can run rebase on a dirty worktree.
        However, use with care: the final stash application after a
@@ -2942,6 +2946,16 @@ sendemail.xmailer::
 sendemail.signedoffcc (deprecated)::
        Deprecated alias for `sendemail.signedoffbycc`.
 
+sendemail.smtpBatchSize::
+       Number of messages to be sent per connection, after that a relogin
+       will happen.  If the value is 0 or undefined, send all messages in
+       one connection.
+       See also the `--batch-size` option of linkgit:git-send-email[1].
+
+sendemail.smtpReloginDelay::
+       Seconds wait before reconnecting to smtp server.
+       See also the `--relogin-delay` option of linkgit:git-send-email[1].
+
 showbranch.default::
        The default set of branches for linkgit:git-show-branch[1].
        See linkgit:git-show-branch[1].
@@ -2992,6 +3006,11 @@ status.displayCommentPrefix::
        behavior of linkgit:git-status[1] in Git 1.8.4 and previous.
        Defaults to false.
 
+status.showStash::
+       If set to true, linkgit:git-status[1] will display the number of
+       entries currently stashed away.
+       Defaults to false.
+
 status.showUntrackedFiles::
        By default, linkgit:git-status[1] and linkgit:git-commit[1] show
        files which are not currently tracked by Git. Directories which
@@ -3029,12 +3048,12 @@ status.submoduleSummary::
 
 stash.showPatch::
        If this is set to true, the `git stash show` command without an
-       option will show the stash in patch form.  Defaults to false.
+       option will show the stash entry in patch form.  Defaults to false.
        See description of 'show' command in linkgit:git-stash[1].
 
 stash.showStat::
        If this is set to true, the `git stash show` command without an
-       option will show diffstat of the stash.  Defaults to true.
+       option will show diffstat of the stash entry.  Defaults to true.
        See description of 'show' command in linkgit:git-stash[1].
 
 submodule.<name>.url::
index 7ed63dce0b1f55325497b4fd6879422fe119eaf5..f4169fb1ec4c61068cc70756c31a5abcc31496f6 100644 (file)
@@ -165,6 +165,13 @@ for "git add --no-all <pathspec>...", i.e. ignored removed files.
        be ignored, no matter if they are already present in the work
        tree or not.
 
+--no-warn-embedded-repo::
+       By default, `git add` will warn when adding an embedded
+       repository to the index without using `git submodule add` to
+       create an entry in `.gitmodules`. This option will suppress the
+       warning (e.g., if you are manually performing operations on
+       submodules).
+
 --chmod=(+|-)x::
        Override the executable bit of the added files.  The executable
        bit is only changed in the index, the files on disk are left
index e414185f5a6a302afa359926c7f8c2c6bf5ac3e7..9db5e08f4a63ae6b15b37ecf7ce96ee728716195 100644 (file)
@@ -131,7 +131,7 @@ unless you have read linkgit:git-rebase[1] carefully.
 --autostash::
 --no-autostash::
        Before starting rebase, stash local modifications away (see
-       linkgit:git-stash[1]) if needed, and apply the stash when
+       linkgit:git-stash[1]) if needed, and apply the stash entry when
        done. `--no-autostash` is useful to override the `rebase.autoStash`
        configuration variable (see linkgit:git-config[1]).
 +
index 53f4e144444ae7b30ce2634c0f364400927b27d2..a5afd602d8eb6cf6fdfbb20863e913a5318c354d 100644 (file)
@@ -446,7 +446,7 @@ used to override and disable this setting.
 
 --autostash::
 --no-autostash::
-       Automatically create a temporary stash before the operation
+       Automatically create a temporary stash entry before the operation
        begins, and apply it after the operation ends.  This means
        that you can run rebase on a dirty worktree.  However, use
        with care: the final stash application after a successful
index 8a21198d65c77c4a23f95d089ed1ce7f003dc0c6..1d697d996220b23d5ac660e809563296ecd1c574 100644 (file)
@@ -115,7 +115,7 @@ $ git pull git://info.example.com/ nitfol  <4>
 in these files are in good order.  You do not want to see them
 when you run "git diff", because you plan to work on other files
 and changes with these files are distracting.
-<2> Somebody asks you to pull, and the changes sounds worthy of merging.
+<2> Somebody asks you to pull, and the changes sound worthy of merging.
 <3> However, you already dirtied the index (i.e. your index does
 not match the HEAD commit).  But you know the pull you are going
 to make does not affect frotz.c or filfre.c, so you revert the
@@ -294,7 +294,7 @@ $ git reset --keep start                    <3>
 
 Split a commit apart into a sequence of commits::
 +
-Suppose that you have created lots of logically separate changes and commited
+Suppose that you have created lots of logically separate changes and committed
 them together. Then, later you decide that it might be better to have each
 logical chunk associated with its own commit. You can use git reset to rewind
 history without changing the contents of your local files, and then successively
index bb23b02caf3ee50a32c86d97e0451cd4be6ab232..bac9014ac71775e5116ad7686af697eb22286ee2 100644 (file)
@@ -248,6 +248,21 @@ must be used for each option.
        commands and replies will be printed. Useful to debug TLS
        connection and authentication problems.
 
+--batch-size=<num>::
+       Some email servers (e.g. smtp.163.com) limit the number emails to be
+       sent per session (connection) and this will lead to a faliure when
+       sending many messages.  With this option, send-email will disconnect after
+       sending $<num> messages and wait for a few seconds (see --relogin-delay)
+       and reconnect, to work around such a limit.  You may want to
+       use some form of credential helper to avoid having to retype
+       your password every time this happens.  Defaults to the
+       `sendemail.smtpBatchSize` configuration variable.
+
+--relogin-delay=<int>::
+       Waiting $<int> seconds before reconnecting to SMTP server. Used together
+       with --batch-size option.  Defaults to the `sendemail.smtpReloginDelay`
+       configuration variable.
+
 Automating
 ~~~~~~~~~~
 
index 70191d06b69ed307c6ce1d8f46c158b61eb6545f..00f95fee1faf52138ce014104148c444be89dabe 100644 (file)
@@ -51,18 +51,18 @@ OPTIONS
 save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
 push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>...]::
 
-       Save your local modifications to a new 'stash' and roll them
+       Save your local modifications to a new 'stash entry' and roll them
        back to HEAD (in the working tree and in the index).
        The <message> part is optional and gives
        the description along with the stashed state.
 +
 For quickly making a snapshot, you can omit "push".  In this mode,
 non-option arguments are not allowed to prevent a misspelled
-subcommand from making an unwanted stash.  The two exceptions to this
+subcommand from making an unwanted stash entry.  The two exceptions to this
 are `stash -p` which acts as alias for `stash push -p` and pathspecs,
 which are allowed after a double hyphen `--` for disambiguation.
 +
-When pathspec is given to 'git stash push', the new stash records the
+When pathspec is given to 'git stash push', the new stash entry records the
 modified states only for the files that match the pathspec.  The index
 entries and working tree files are then rolled back to the state in
 HEAD only for these files, too, leaving files that do not match the
@@ -89,10 +89,10 @@ The `--patch` option implies `--keep-index`.  You can use
 
 list [<options>]::
 
-       List the stashes that you currently have.  Each 'stash' is listed
-       with its name (e.g. `stash@{0}` is the latest stash, `stash@{1}` is
+       List the stash entries that you currently have.  Each 'stash entry' is
+       listed with its name (e.g. `stash@{0}` is the latest entry, `stash@{1}` is
        the one before, etc.), the name of the branch that was current when the
-       stash was made, and a short description of the commit the stash was
+       entry was made, and a short description of the commit the entry was
        based on.
 +
 ----------------------------------------------------------------
@@ -105,11 +105,12 @@ command to control what is shown and how. See linkgit:git-log[1].
 
 show [<stash>]::
 
-       Show the changes recorded in the stash as a diff between the
-       stashed state and its original parent. When no `<stash>` is given,
-       shows the latest one. By default, the command shows the diffstat, but
-       it will accept any format known to 'git diff' (e.g., `git stash show
-       -p stash@{1}` to view the second most recent stash in patch form).
+       Show the changes recorded in the stash entry as a diff between the
+       stashed contents and the commit back when the stash entry was first
+       created. When no `<stash>` is given, it shows the latest one.
+       By default, the command shows the diffstat, but it will accept any
+       format known to 'git diff' (e.g., `git stash show -p stash@{1}`
+       to view the second most recent entry in patch form).
        You can use stash.showStat and/or stash.showPatch config variables
        to change the default behavior.
 
@@ -149,26 +150,27 @@ branch <branchname> [<stash>]::
 +
 This is useful if the branch on which you ran `git stash save` has
 changed enough that `git stash apply` fails due to conflicts. Since
-the stash is applied on top of the commit that was HEAD at the time
-`git stash` was run, it restores the originally stashed state with
-no conflicts.
+the stash entry is applied on top of the commit that was HEAD at the
+time `git stash` was run, it restores the originally stashed state
+with no conflicts.
 
 clear::
-       Remove all the stashed states. Note that those states will then
+       Remove all the stash entries. Note that those entries will then
        be subject to pruning, and may be impossible to recover (see
        'Examples' below for a possible strategy).
 
 drop [-q|--quiet] [<stash>]::
 
-       Remove a single stashed state from the stash list. When no `<stash>`
-       is given, it removes the latest one. i.e. `stash@{0}`, otherwise
-       `<stash>` must be a valid stash log reference of the form
-       `stash@{<revision>}`.
+       Remove a single stash entry from the list of stash entries.
+       When no `<stash>` is given, it removes the latest one.
+       i.e. `stash@{0}`, otherwise `<stash>` must be a valid stash
+       log reference of the form `stash@{<revision>}`.
 
 create::
 
-       Create a stash (which is a regular commit object) and return its
-       object name, without storing it anywhere in the ref namespace.
+       Create a stash entry (which is a regular commit object) and
+       return its object name, without storing it anywhere in the ref
+       namespace.
        This is intended to be useful for scripts.  It is probably not
        the command you want to use; see "save" above.
 
@@ -182,10 +184,10 @@ store::
 DISCUSSION
 ----------
 
-A stash is represented as a commit whose tree records the state of the
-working directory, and its first parent is the commit at `HEAD` when
-the stash was created.  The tree of the second parent records the
-state of the index when the stash is made, and it is made a child of
+A stash entry is represented as a commit whose tree records the state
+of the working directory, and its first parent is the commit at `HEAD`
+when the entry was created.  The tree of the second parent records the
+state of the index when the entry is made, and it is made a child of
 the `HEAD` commit.  The ancestry graph looks like this:
 
             .----W
@@ -269,12 +271,12 @@ $ edit/build/test remaining parts
 $ git commit foo -m 'Remaining parts'
 ----------------------------------------------------------------
 
-Recovering stashes that were cleared/dropped erroneously::
+Recovering stash entries that were cleared/dropped erroneously::
 
-If you mistakenly drop or clear stashes, they cannot be recovered
+If you mistakenly drop or clear stash entries, they cannot be recovered
 through the normal safety mechanisms.  However, you can try the
-following incantation to get a list of stashes that are still in your
-repository, but not reachable any more:
+following incantation to get a list of stash entries that are still in
+your repository, but not reachable any more:
 +
 ----------------------------------------------------------------
 git fsck --unreachable |
index d70abc6afe3aa40aaaab2e055ee75d8ee22cdb69..d47f198f15cd4c767b03c14580b816bf750e9ee1 100644 (file)
@@ -32,6 +32,9 @@ OPTIONS
 --branch::
        Show the branch and tracking info even in short-format.
 
+--show-stash::
+       Show the number of entries currently stashed away.
+
 --porcelain[=<version>]::
        Give the output in an easy-to-parse format for scripts.
        This is similar to the short output, but will remain stable
index 74bc6200d564c6aa72183e393f7c7d2e0c00bf7d..b9a56d4c6e2249f64e40b9133f2224c8bc2363ef 100644 (file)
@@ -63,14 +63,6 @@ add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--dep
        to the changeset to be committed next to the current
        project: the current project is termed the "superproject".
 +
-This requires at least one argument: <repository>. The optional
-argument <path> is the relative location for the cloned submodule
-to exist in the superproject. If <path> is not given, the
-"humanish" part of the source repository is used ("repo" for
-"/path/to/repo.git" and "foo" for "host.xz:foo/.git").
-The <path> is also used as the submodule's logical name in its
-configuration entries unless `--name` is used to specify a logical name.
-+
 <repository> is the URL of the new submodule's origin repository.
 This may be either an absolute URL, or (if it begins with ./
 or ../), the location relative to the superproject's default remote
@@ -87,21 +79,22 @@ If the superproject doesn't have a default remote configured
 the superproject is its own authoritative upstream and the current
 working directory is used instead.
 +
-<path> is the relative location for the cloned submodule to
-exist in the superproject. If <path> does not exist, then the
-submodule is created by cloning from the named URL. If <path> does
-exist and is already a valid Git repository, then this is added
-to the changeset without cloning. This second form is provided
-to ease creating a new submodule from scratch, and presumes
-the user will later push the submodule to the given URL.
+The optional argument <path> is the relative location for the cloned
+submodule to exist in the superproject. If <path> is not given, the
+canonical part of the source repository is used ("repo" for
+"/path/to/repo.git" and "foo" for "host.xz:foo/.git"). If <path>
+exists and is already a valid Git repository, then it is staged
+for commit without cloning. The <path> is also used as the submodule's
+logical name in its configuration entries unless `--name` is used
+to specify a logical name.
 +
-In either case, the given URL is recorded into .gitmodules for
-use by subsequent users cloning the superproject. If the URL is
-given relative to the superproject's repository, the presumption
-is the superproject and submodule repositories will be kept
-together in the same relative location, and only the
-superproject's URL needs to be provided: git-submodule will correctly
-locate the submodule using the relative URL in .gitmodules.
+The given URL is recorded into `.gitmodules` for use by subsequent users
+cloning the superproject. If the URL is given relative to the
+superproject's repository, the presumption is the superproject and
+submodule repositories will be kept together in the same relative
+location, and only the superproject's URL needs to be provided.
+git-submodule will correctly locate the submodule using the relative
+URL in `.gitmodules`.
 
 status [--cached] [--recursive] [--] [<path>...]::
        Show the status of the submodules. This will print the SHA-1 of the
@@ -123,7 +116,7 @@ too (and can also report changes to a submodule's work tree).
 init [--] [<path>...]::
        Initialize the submodules recorded in the index (which were
        added and committed elsewhere) by setting `submodule.$name.url`
-       in .git/config. It uses the same setting from .gitmodules as
+       in .git/config. It uses the same setting from `.gitmodules` as
        a template. If the URL is relative, it will be resolved using
        the default remote. If there is no default remote, the current
        repository will be assumed to be upstream.
@@ -141,7 +134,7 @@ you can also just use `git submodule update --init` without
 the explicit 'init' step if you do not intend to customize
 any submodule locations.
 +
-See the add subcommand for the defintion of default remote.
+See the add subcommand for the definition of default remote.
 
 deinit [-f|--force] (--all|[--] <path>...)::
        Unregister the given submodules, i.e. remove the whole
@@ -197,7 +190,7 @@ configuration variable:
        none;; the submodule is not updated.
 
 If the submodule is not yet initialized, and you just want to use the
-setting as stored in .gitmodules, you can automatically initialize the
+setting as stored in `.gitmodules`, you can automatically initialize the
 submodule with the `--init` option.
 
 If `--recursive` is specified, this command will recurse into the
@@ -220,7 +213,7 @@ 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:
-       $name is the name of the relevant submodule section in .gitmodules,
+       $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.
@@ -242,7 +235,7 @@ git submodule foreach 'echo $path `git rev-parse HEAD`'
 
 sync [--recursive] [--] [<path>...]::
        Synchronizes submodules' remote URL configuration setting
-       to the value specified in .gitmodules. It will only affect those
+       to the value specified in `.gitmodules`. It will only affect those
        submodules which already have a URL entry in .git/config (that is the
        case when they are initialized or freshly added). This is useful when
        submodule URLs change upstream and you need to update your local
@@ -413,7 +406,7 @@ for linkgit:git-clone[1]'s `--reference` and `--shared` options carefully.
 --[no-]recommend-shallow::
        This option is only valid for the update command.
        The initial clone of a submodule will use the recommended
-       `submodule.<name>.shallow` as provided by the .gitmodules file
+       `submodule.<name>.shallow` as provided by the `.gitmodules` file
        by default. To ignore the suggestions use `--no-recommend-shallow`.
 
 -j <n>::
@@ -429,7 +422,7 @@ for linkgit:git-clone[1]'s `--reference` and `--shared` options carefully.
 
 FILES
 -----
-When initializing submodules, a .gitmodules file in the top-level directory
+When initializing submodules, a `.gitmodules` file in the top-level directory
 of the containing repository is used to find the url of each submodule.
 This file should be formatted in the same way as `$GIT_DIR/config`. The key
 to each submodule url is "submodule.$name.url".  See linkgit:gitmodules[5]
index 4736483865ee56c3cf23f41985e2064fbef0cfea..2a2d7e2a4d2a9cab2af8bd881dd880ca2a52235a 100644 (file)
@@ -229,7 +229,7 @@ From a clean working directory:
 
 -------------------------------------------------
 $ echo "* text=auto" >.gitattributes
-$ rm .git/index     # Remove the index to re-scan the working directory
+$ git read-tree --empty   # Clean index, force re-scan of working directory
 $ git add .
 $ git status        # Show files that will be normalized
 $ git commit -m "Introduce end-of-line normalization"
index dfe7d8372723c7a4970b8a7100764d1becc7f830..9f13266a685176bf142d9e381d7a9d10ea12aa7b 100644 (file)
@@ -194,7 +194,7 @@ different things.
  * The `--index` option is used to ask a command that
    usually works on files in the working tree to *also*
    affect the index.  For example, `git stash apply` usually
-   merges changes recorded in a stash to the working tree,
+   merges changes recorded in a stash entry to the working tree,
    but with the `--index` option, it also merges changes to
    the index as well.
 
index 6e991c246915143deba887632def104fc709c9bf..b71b943b12eda2eab1792dfc910e405ad2ad540c 100644 (file)
@@ -570,6 +570,10 @@ The most notable example is `HEAD`.
        is created by giving the `--depth` option to linkgit:git-clone[1], and
        its history can be later deepened with linkgit:git-fetch[1].
 
+[[def_stash]]stash entry::
+       An <<def_object,object>> used to temporarily store the contents of a
+       <<def_dirty,dirty>> working directory and the index for future reuse.
+
 [[def_submodule]]submodule::
        A <<def_repository,repository>> that holds the history of a
        separate project inside another repository (the latter of
index 38040e95b5cdb137fd3575076e5f69d393c19280..4d6dac5770bed76cada2f53334e239c70d15a073 100644 (file)
@@ -174,11 +174,12 @@ endif::git-rev-list[]
 - '%Creset': reset color
 - '%C(...)': color specification, as described under Values in the
   "CONFIGURATION FILE" section of linkgit:git-config[1];
-  adding `auto,` at the beginning will emit color only when colors are
-  enabled for log output (by `color.diff`, `color.ui`, or `--color`, and
-  respecting the `auto` settings of the former if we are going to a
-  terminal). `auto` alone (i.e. `%C(auto)`) will turn on auto coloring
-  on the next placeholders until the color is switched again.
+  adding `auto,` at the beginning (e.g. `%C(auto,red)`) will emit
+  color only when colors are enabled for log output (by `color.diff`,
+  `color.ui`, or `--color`, and respecting the `auto` settings of the
+  former if we are going to a terminal). `auto` alone (i.e.
+  `%C(auto)`) will turn on auto coloring on the next placeholders
+  until the color is switched again.
 - '%m': left (`<`), right (`>`) or boundary (`-`) mark
 - '%n': newline
 - '%%': a raw '%'
@@ -213,8 +214,8 @@ If you add a `+` (plus sign) after '%' of a placeholder, a line-feed
 is inserted immediately before the expansion if and only if the
 placeholder expands to a non-empty string.
 
-If you add a `-` (minus sign) after '%' of a placeholder, line-feeds that
-immediately precede the expansion are deleted if and only if the
+If you add a `-` (minus sign) after '%' of a placeholder, all consecutive
+line-feeds immediately preceding the expansion are deleted if and only if the
 placeholder expands to an empty string.
 
 If you add a ` ` (space) after '%' of a placeholder, a space
index b94cd5633c8ebda7e09874a1012fb75cbccc64e0..bfa5b3a4ca7885787241eb99dffcf2216e05cdaf 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -162,6 +162,12 @@ all::
 # algorithm. This is slower, but may detect attempted collision attacks.
 # Takes priority over other *_SHA1 knobs.
 #
+# Define DC_SHA1_SUBMODULE in addition to DC_SHA1 to use the
+# sha1collisiondetection shipped as a submodule instead of the
+# non-submodule copy in sha1dc/. This is an experimental option used
+# by the git project to migrate to using sha1collisiondetection as a
+# submodule.
+#
 # Define OPENSSL_SHA1 environment variable when running make to link
 # with the SHA1 routine from openssl library.
 #
@@ -840,6 +846,7 @@ LIB_OBJS += refs/ref-cache.o
 LIB_OBJS += ref-filter.o
 LIB_OBJS += remote.o
 LIB_OBJS += replace_object.o
+LIB_OBJS += repository.o
 LIB_OBJS += rerere.o
 LIB_OBJS += resolve-undo.o
 LIB_OBJS += revision.o
@@ -1003,6 +1010,10 @@ EXTLIBS =
 
 GIT_USER_AGENT = git/$(GIT_VERSION)
 
+ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)
+DC_SHA1_SUBMODULE = auto
+endif
+
 include config.mak.uname
 -include config.mak.autogen
 -include config.mak
@@ -1448,8 +1459,14 @@ ifdef APPLE_COMMON_CRYPTO
        BASIC_CFLAGS += -DSHA1_APPLE
 else
        DC_SHA1 := YesPlease
+ifdef DC_SHA1_SUBMODULE
+       LIB_OBJS += sha1collisiondetection/lib/sha1.o
+       LIB_OBJS += sha1collisiondetection/lib/ubc_check.o
+       BASIC_CFLAGS += -DDC_SHA1_SUBMODULE
+else
        LIB_OBJS += sha1dc/sha1.o
        LIB_OBJS += sha1dc/ubc_check.o
+endif
        BASIC_CFLAGS += \
                -DSHA1_DC \
                -DSHA1DC_NO_STANDARD_INCLUDES \
index 7f1cfe97929ea33efb81adfcc97b82f334dccb3d..708aff8d42c562112fe4076635af903c7f41fbaa 100644 (file)
--- a/abspath.c
+++ b/abspath.c
@@ -183,7 +183,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
 
                        /*
                         * use the symlink as the remaining components that
-                        * need to be resloved
+                        * need to be resolved
                         */
                        strbuf_swap(&symlink, &remaining);
                }
index b84ae4960f11af10d01667d01eb0bb27f52ecb14..d81e1cb7425b0f2d75461865b5c965a21ada5587 100644 (file)
--- a/advice.c
+++ b/advice.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 
 int advice_push_update_rejected = 1;
 int advice_push_non_ff_current = 1;
@@ -15,6 +16,7 @@ int advice_detached_head = 1;
 int advice_set_upstream_failure = 1;
 int advice_object_name_warning = 1;
 int advice_rm_hints = 1;
+int advice_add_embedded_repo = 1;
 
 static struct {
        const char *name;
@@ -35,6 +37,7 @@ static struct {
        { "setupstreamfailure", &advice_set_upstream_failure },
        { "objectnamewarning", &advice_object_name_warning },
        { "rmhints", &advice_rm_hints },
+       { "addembeddedrepo", &advice_add_embedded_repo },
 
        /* make this an alias for backward compatibility */
        { "pushnonfastforward", &advice_push_update_rejected }
index b341a55ce7c250cc34b49dc06a2843b5a5df1aac..c84a44531c7d8fcc9867b2df4ba9dc11d0766508 100644 (file)
--- a/advice.h
+++ b/advice.h
@@ -18,6 +18,7 @@ extern int advice_detached_head;
 extern int advice_set_upstream_failure;
 extern int advice_object_name_warning;
 extern int advice_rm_hints;
+extern int advice_add_embedded_repo;
 
 int git_default_advice_config(const char *var, const char *value);
 __attribute__((format (printf, 1, 2)))
diff --git a/alias.c b/alias.c
index 3b90397a99d9f7ed4a0c1c5a83f5e69c879e752f..39f622e4141576b1170131f6c4b14316becb1a71 100644 (file)
--- a/alias.c
+++ b/alias.c
@@ -1,14 +1,29 @@
 #include "cache.h"
+#include "config.h"
+
+struct config_alias_data {
+       const char *alias;
+       char *v;
+};
+
+static int config_alias_cb(const char *key, const char *value, void *d)
+{
+       struct config_alias_data *data = d;
+       const char *p;
+
+       if (skip_prefix(key, "alias.", &p) && !strcmp(p, data->alias))
+               return git_config_string((const char **)&data->v, key, value);
+
+       return 0;
+}
 
 char *alias_lookup(const char *alias)
 {
-       char *v = NULL;
-       struct strbuf key = STRBUF_INIT;
-       strbuf_addf(&key, "alias.%s", alias);
-       if (git_config_key_is_valid(key.buf))
-               git_config_get_string(key.buf, &v);
-       strbuf_release(&key);
-       return v;
+       struct config_alias_data data = { alias, NULL };
+
+       read_early_config(config_alias_cb, &data);
+
+       return data.v;
 }
 
 #define SPLIT_CMDLINE_BAD_ENDING 1
@@ -47,8 +62,7 @@ int split_cmdline(char *cmdline, const char ***argv)
                                src++;
                                c = cmdline[src];
                                if (!c) {
-                                       free(*argv);
-                                       *argv = NULL;
+                                       FREE_AND_NULL(*argv);
                                        return -SPLIT_CMDLINE_BAD_ENDING;
                                }
                        }
@@ -60,8 +74,7 @@ int split_cmdline(char *cmdline, const char ***argv)
        cmdline[dst] = 0;
 
        if (quoted) {
-               free(*argv);
-               *argv = NULL;
+               FREE_AND_NULL(*argv);
                return -SPLIT_CMDLINE_UNCLOSED_QUOTE;
        }
 
diff --git a/apply.c b/apply.c
index bb411b5810d9550c16689bf77101e0f40c49ac6e..4050cebcfacc233f6d449221ec5c44b3551a4678 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -8,6 +8,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "blob.h"
 #include "delta.h"
 #include "diff.h"
@@ -210,6 +211,7 @@ struct patch {
        unsigned ws_rule;
        int lines_added, lines_deleted;
        int score;
+       int extension_linenr; /* first line specifying delete/new/rename/copy */
        unsigned int is_toplevel_relative:1;
        unsigned int inaccurate_eof:1;
        unsigned int is_binary:1;
@@ -974,8 +976,7 @@ static int gitdiff_verify_name(struct apply_state *state,
                }
                free(another);
        } else {
-               /* expect "/dev/null" */
-               if (memcmp("/dev/null", line, 9) || line[9] != '\n')
+               if (!starts_with(line, "/dev/null\n"))
                        return error(_("git apply: bad git-diff - expected /dev/null on line %d"), state->linenr);
        }
 
@@ -1000,20 +1001,27 @@ static int gitdiff_newname(struct apply_state *state,
                                   DIFF_NEW_NAME);
 }
 
+static int parse_mode_line(const char *line, int linenr, unsigned int *mode)
+{
+       char *end;
+       *mode = strtoul(line, &end, 8);
+       if (end == line || !isspace(*end))
+               return error(_("invalid mode on line %d: %s"), linenr, line);
+       return 0;
+}
+
 static int gitdiff_oldmode(struct apply_state *state,
                           const char *line,
                           struct patch *patch)
 {
-       patch->old_mode = strtoul(line, NULL, 8);
-       return 0;
+       return parse_mode_line(line, state->linenr, &patch->old_mode);
 }
 
 static int gitdiff_newmode(struct apply_state *state,
                           const char *line,
                           struct patch *patch)
 {
-       patch->new_mode = strtoul(line, NULL, 8);
-       return 0;
+       return parse_mode_line(line, state->linenr, &patch->new_mode);
 }
 
 static int gitdiff_delete(struct apply_state *state,
@@ -1127,7 +1135,7 @@ static int gitdiff_index(struct apply_state *state,
        memcpy(patch->new_sha1_prefix, line, len);
        patch->new_sha1_prefix[len] = 0;
        if (*ptr == ' ')
-               patch->old_mode = strtoul(ptr+1, NULL, 8);
+               return gitdiff_oldmode(state, ptr + 1, patch);
        return 0;
 }
 
@@ -1311,6 +1319,18 @@ static char *git_header_name(struct apply_state *state,
        }
 }
 
+static int check_header_line(struct apply_state *state, struct patch *patch)
+{
+       int extensions = (patch->is_delete == 1) + (patch->is_new == 1) +
+                        (patch->is_rename == 1) + (patch->is_copy == 1);
+       if (extensions > 1)
+               return error(_("inconsistent header lines %d and %d"),
+                            patch->extension_linenr, state->linenr);
+       if (extensions && !patch->extension_linenr)
+               patch->extension_linenr = state->linenr;
+       return 0;
+}
+
 /* Verify that we recognize the lines following a git header */
 static int parse_git_header(struct apply_state *state,
                            const char *line,
@@ -1377,6 +1397,8 @@ static int parse_git_header(struct apply_state *state,
                        res = p->fn(state, line + oplen, patch);
                        if (res < 0)
                                return -1;
+                       if (check_header_line(state, patch))
+                               return -1;
                        if (res > 0)
                                return offset;
                        break;
@@ -1574,7 +1596,8 @@ static int find_header(struct apply_state *state,
                                patch->old_name = xstrdup(patch->def_name);
                                patch->new_name = xstrdup(patch->def_name);
                        }
-                       if (!patch->is_delete && !patch->new_name) {
+                       if ((!patch->new_name && !patch->is_delete) ||
+                           (!patch->old_name && !patch->is_new)) {
                                error(_("git diff header lacks filename information "
                                             "(line %d)"), state->linenr);
                                return -128;
@@ -2256,7 +2279,7 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
        case S_IFREG:
                if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
                        return error(_("unable to open or read %s"), path);
-               convert_to_git(path, buf->buf, buf->len, buf, 0);
+               convert_to_git(&the_index, path, buf->buf, buf->len, buf, 0);
                return 0;
        default:
                return -1;
@@ -3694,8 +3717,7 @@ static int check_preimage(struct apply_state *state,
  is_new:
        patch->is_new = 1;
        patch->is_delete = 0;
-       free(patch->old_name);
-       patch->old_name = NULL;
+       FREE_AND_NULL(patch->old_name);
        return 0;
 }
 
index 073e60ebd3c366b42298ae443eee230407d4e3a7..c6ed96ee74ec10f5c9ffb6f520193326d4704b6b 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (c) 2005, 2006 Rene Scharfe
  */
 #include "cache.h"
+#include "config.h"
 #include "tar.h"
 #include "archive.h"
 #include "streaming.h"
index 27563e9e2602108997033e6fa79c660bc08aa863..e8913e5a26c6e97216c4b79ad96b5e3ddf906c45 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (c) 2006 Rene Scharfe
  */
 #include "cache.h"
+#include "config.h"
 #include "archive.h"
 #include "streaming.h"
 #include "utf8.h"
index b15a922dab56a525ca3ce7f1143d215fe39f3132..60b3035a7a6a9e7c2e69b4ba7de00ebdf8bfdbb8 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "commit.h"
 #include "tree-walk.h"
diff --git a/attr.c b/attr.c
index 821203e2a980c329fc065a0dfabe37ef67a4bbbe..37454999d21e9dcea73e6717da608d80720235e8 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -9,6 +9,7 @@
 
 #define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
+#include "config.h"
 #include "exec_cmd.h"
 #include "attr.h"
 #include "dir.h"
@@ -638,13 +639,11 @@ void attr_check_reset(struct attr_check *check)
 
 void attr_check_clear(struct attr_check *check)
 {
-       free(check->items);
-       check->items = NULL;
+       FREE_AND_NULL(check->items);
        check->alloc = 0;
        check->nr = 0;
 
-       free(check->all_attrs);
-       check->all_attrs = NULL;
+       FREE_AND_NULL(check->all_attrs);
        check->all_attrs_nr = 0;
 
        drop_attr_stack(&check->stack);
index 2a2b9b7267acbb8752015d64ec477f64c6047875..a9fd9fbc61a661ab19e18713b115f868daab2f98 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "diff.h"
 #include "revision.h"
diff --git a/blame.c b/blame.c
index 194b58e96066f9620005f64a57ca9ecc618c86f4..91e26e93e8a23d0af63e1bc8a74e9f7690276ab4 100644 (file)
--- a/blame.c
+++ b/blame.c
@@ -229,7 +229,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
                if (strbuf_read(&buf, 0, 0) < 0)
                        die_errno("failed to read from stdin");
        }
-       convert_to_git(path, buf.buf, buf.len, &buf, 0);
+       convert_to_git(&the_index, path, buf.buf, buf.len, &buf, 0);
        origin->file.ptr = buf.buf;
        origin->file.size = buf.len;
        pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_oid.hash);
@@ -314,8 +314,7 @@ static void fill_origin_blob(struct diff_options *opt,
 static void drop_origin_blob(struct blame_origin *o)
 {
        if (o->file.ptr) {
-               free(o->file.ptr);
-               o->file.ptr = NULL;
+               FREE_AND_NULL(o->file.ptr);
        }
 }
 
index 985316eb76505a60bca0aa303322bef35e7defaa..36541d05cd7b934bceba1af4fd4c121e51cd862b 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "cache.h"
+#include "config.h"
 #include "branch.h"
 #include "refs.h"
 #include "remote.h"
@@ -24,8 +25,7 @@ static int find_tracked_branch(struct remote *remote, void *priv)
                } else {
                        free(tracking->spec.src);
                        if (tracking->src) {
-                               free(tracking->src);
-                               tracking->src = NULL;
+                               FREE_AND_NULL(tracking->src);
                        }
                }
                tracking->spec.src = NULL;
index d9a2491e48f16d9ef7de5c05008f8c7e6a5e64b2..e888fb8c5f2a1fa2be33e834724460dec8072726 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2006 Linus Torvalds
  */
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "lockfile.h"
 #include "dir.h"
@@ -249,6 +250,7 @@ N_("The following paths are ignored by one of your .gitignore files:\n");
 
 static int verbose, show_only, ignored_too, refresh_only;
 static int ignore_add_errors, intent_to_add, ignore_missing;
+static int warn_on_embedded_repo = 1;
 
 #define ADDREMOVE_DEFAULT 1
 static int addremove = ADDREMOVE_DEFAULT;
@@ -282,6 +284,8 @@ static struct option builtin_add_options[] = {
        OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
        OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
        OPT_STRING( 0 , "chmod", &chmod_arg, N_("(+/-)x"), N_("override the executable bit of the listed files")),
+       OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
+                       N_("warn when adding an embedded repository")),
        OPT_END(),
 };
 
@@ -295,6 +299,45 @@ static int add_config(const char *var, const char *value, void *cb)
        return git_default_config(var, value, cb);
 }
 
+static const char embedded_advice[] = N_(
+"You've added another git repository inside your current repository.\n"
+"Clones of the outer repository will not contain the contents of\n"
+"the embedded repository and will not know how to obtain it.\n"
+"If you meant to add a submodule, use:\n"
+"\n"
+"      git submodule add <url> %s\n"
+"\n"
+"If you added this path by mistake, you can remove it from the\n"
+"index with:\n"
+"\n"
+"      git rm --cached %s\n"
+"\n"
+"See \"git help submodule\" for more information."
+);
+
+static void check_embedded_repo(const char *path)
+{
+       struct strbuf name = STRBUF_INIT;
+
+       if (!warn_on_embedded_repo)
+               return;
+       if (!ends_with(path, "/"))
+               return;
+
+       /* Drop trailing slash for aesthetics */
+       strbuf_addstr(&name, path);
+       strbuf_strip_suffix(&name, "/");
+
+       warning(_("adding embedded git repository: %s"), name.buf);
+       if (advice_add_embedded_repo) {
+               advise(embedded_advice, name.buf, name.buf);
+               /* there may be multiple entries; advise only once */
+               advice_add_embedded_repo = 0;
+       }
+
+       strbuf_release(&name);
+}
+
 static int add_files(struct dir_struct *dir, int flags)
 {
        int i, exit_status = 0;
@@ -307,12 +350,14 @@ static int add_files(struct dir_struct *dir, int flags)
                exit_status = 1;
        }
 
-       for (i = 0; i < dir->nr; i++)
+       for (i = 0; i < dir->nr; i++) {
+               check_embedded_repo(dir->entries[i]->name);
                if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
                        if (!ignore_add_errors)
                                die(_("adding files failed"));
                        exit_status = 1;
                }
+       }
        return exit_status;
 }
 
index 3985f9a89f985baa139ea69f5fde8ce1384871f6..c973bd96dcb5d630d56e935733bfa4530ccd2872 100644 (file)
@@ -4,6 +4,7 @@
  * Based on git-am.sh by Junio C Hamano.
  */
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "exec_cmd.h"
 #include "parse-options.h"
@@ -483,8 +484,7 @@ static int run_applypatch_msg_hook(struct am_state *state)
        ret = run_hook_le(NULL, "applypatch-msg", am_path(state, "final-commit"), NULL);
 
        if (!ret) {
-               free(state->msg);
-               state->msg = NULL;
+               FREE_AND_NULL(state->msg);
                if (read_commit_msg(state) < 0)
                        die(_("'%s' was deleted by the applypatch-msg hook"),
                                am_path(state, "final-commit"));
@@ -1073,17 +1073,10 @@ static void am_next(struct am_state *state)
 {
        struct object_id head;
 
-       free(state->author_name);
-       state->author_name = NULL;
-
-       free(state->author_email);
-       state->author_email = NULL;
-
-       free(state->author_date);
-       state->author_date = NULL;
-
-       free(state->msg);
-       state->msg = NULL;
+       FREE_AND_NULL(state->author_name);
+       FREE_AND_NULL(state->author_email);
+       FREE_AND_NULL(state->author_date);
+       FREE_AND_NULL(state->msg);
        state->msg_len = 0;
 
        unlink(am_path(state, "author-script"));
index 749ad7f05b657ba34534a4ae6601dd5d85649b36..bda1a787265e6d44d2ec0bec1e4dee5bf8de9c3b 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "commit.h"
 #include "diff.h"
index 83fcda43dceec0255c6164eb42a35d3d89011efb..c958e93257910816bd8d40673805e8553f921f3f 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "color.h"
 #include "refs.h"
 #include "commit.h"
index 4bffd7a2d8eee2ea251afef70f63f646f184a339..96b786e4892aec0ed7e5d07ac8d3261c7b765f33 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "diff.h"
 #include "parse-options.h"
@@ -56,11 +57,11 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
        struct object_context obj_context;
        struct object_info oi = OBJECT_INFO_INIT;
        struct strbuf sb = STRBUF_INIT;
-       unsigned flags = LOOKUP_REPLACE_OBJECT;
+       unsigned flags = OBJECT_INFO_LOOKUP_REPLACE;
        const char *path = force_path;
 
        if (unknown_type)
-               flags |= LOOKUP_UNKNOWN_OBJECT;
+               flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
 
        if (get_sha1_with_context(obj_name, GET_SHA1_RECORD_PATH,
                                  oid.hash, &obj_context))
@@ -337,7 +338,8 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,
        struct strbuf buf = STRBUF_INIT;
 
        if (!data->skip_object_info &&
-           sha1_object_info_extended(data->oid.hash, &data->info, LOOKUP_REPLACE_OBJECT) < 0) {
+           sha1_object_info_extended(data->oid.hash, &data->info,
+                                     OBJECT_INFO_LOOKUP_REPLACE) < 0) {
                printf("%s missing\n",
                       obj_name ? obj_name : oid_to_hex(&data->oid));
                fflush(stdout);
index 4d01ca0c8ba0ba2a1d2c209b766e19d9ca9c8ac0..91444dc0448b32e854f1923fe1e57e28c87f5b35 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "attr.h"
 #include "quote.h"
 #include "parse-options.h"
index c7b8c08897193e225d8da32f4d402def3f16fe50..3e280b9c7aa9c93c8e7572a4fe3f7ef3ac92b3af 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "dir.h"
 #include "quote.h"
 #include "pathspec.h"
index cf0f54f6b92ec8db45158c43ad164413ec4a1333..cdce144f3b7f160f508721ed4f4afc69d683262a 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "mailmap.h"
 #include "parse-options.h"
 #include "string-list.h"
index 07631d0c9c59f6ba03f288294797e08cdfe22b7c..39c8be05dc4beda2f0cd179e5c5f495ce079f8d9 100644 (file)
@@ -5,6 +5,7 @@
  *
  */
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "quote.h"
 #include "cache-tree.h"
index 1624eed7e7625c18da7ffb58f1b9ae456c3dbd77..9661e1bcba31ffa4f7b8a2fb1a9d2060cb8efda7 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "parse-options.h"
 #include "refs.h"
index 142bf668cffe814006fae791f1bdc6b20fe6f366..057fc97fe4494338e6a85ac9f695563f1fcb9596 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "dir.h"
 #include "parse-options.h"
 #include "string-list.h"
@@ -837,8 +838,7 @@ static void interactive_main_loop(void)
                        int ret;
                        ret = menus[*chosen].fn();
                        if (ret != MENU_RETURN_NO_LOOP) {
-                               free(chosen);
-                               chosen = NULL;
+                               FREE_AND_NULL(chosen);
                                if (!del_list.nr) {
                                        clean_print_color(CLEAN_COLOR_ERROR);
                                        printf_ln(_("No more files to clean, exiting."));
@@ -851,8 +851,7 @@ static void interactive_main_loop(void)
                        quit_cmd();
                }
 
-               free(chosen);
-               chosen = NULL;
+               FREE_AND_NULL(chosen);
                break;
        }
 }
index a2ea019c590190a00d1a7cf51a917c7ebdc7886c..08b5cc433c6fcad5eea2dfc3321aea28a599d51f 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "parse-options.h"
 #include "fetch-pack.h"
index 33314b4d7127cb6e4116c350e113058e07f58474..0c3223d64b159580935bf24f8583a35a1ae903ff 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "strbuf.h"
 #include "parse-options.h"
 #include "string-list.h"
index f39c2b27375fcd70f050e56174b0966053652eef..a4a923d7c0b688e162c8e4d0411ff9b72748fb5c 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "tree.h"
 #include "builtin.h"
index e3c9e190b06a63250a9c7eff3e256efcb10660f7..b0a740b25e6ba8c4c3e6165b3ec67b20e0536e5f 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "cache-tree.h"
 #include "color.h"
@@ -139,7 +140,6 @@ static enum commit_whence whence;
 static int sequencer_in_use;
 static int use_editor = 1, include_status = 1;
 static int show_ignored_in_status, have_option_m;
-static const char *only_include_assumed;
 static struct strbuf message = STRBUF_INIT;
 
 static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;
@@ -253,7 +253,8 @@ static int list_paths(struct string_list *list, const char *with_tree,
 
        if (with_tree) {
                char *max_prefix = common_prefix(pattern);
-               overlay_tree_on_cache(with_tree, max_prefix ? max_prefix : prefix);
+               overlay_tree_on_index(&the_index, with_tree,
+                                     max_prefix ? max_prefix : prefix);
                free(max_prefix);
        }
 
@@ -841,9 +842,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                                  "with '%c' will be kept; you may remove them"
                                  " yourself if you want to.\n"
                                  "An empty message aborts the commit.\n"), comment_line_char);
-               if (only_include_assumed)
-                       status_printf_ln(s, GIT_COLOR_NORMAL,
-                                       "%s", only_include_assumed);
 
                /*
                 * These should never fail because they come from our own
@@ -877,8 +875,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                                (int)(ci.name_end - ci.name_begin), ci.name_begin,
                                (int)(ci.mail_end - ci.mail_begin), ci.mail_begin);
 
-               if (ident_shown)
-                       status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
+               status_printf_ln(s, GIT_COLOR_NORMAL, "%s", ""); /* Add new line for clarity */
 
                saved_color_setting = s->use_color;
                s->use_color = 0;
@@ -1208,8 +1205,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
                die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
        if (argc == 0 && (also || (only && !amend && !allow_empty)))
                die(_("No paths with --include/--only does not make sense."));
-       if (argc > 0 && !also && !only)
-               only_include_assumed = _("Explicit paths specified without -i or -o; assuming --only paths...");
        if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
                cleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;
        else if (!strcmp(cleanup_arg, "verbatim"))
@@ -1295,6 +1290,10 @@ static int git_status_config(const char *k, const char *v, void *cb)
                status_deferred_config.show_branch = git_config_bool(k, v);
                return 0;
        }
+       if (!strcmp(k, "status.showstash")) {
+               s->show_stash = git_config_bool(k, v);
+               return 0;
+       }
        if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
                s->use_color = git_config_colorbool(k, v);
                return 0;
@@ -1343,6 +1342,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
                            N_("show status concisely"), STATUS_FORMAT_SHORT),
                OPT_BOOL('b', "branch", &s.show_branch,
                         N_("show branch information")),
+               OPT_BOOL(0, "show-stash", &s.show_stash,
+                        N_("show stash information")),
                { OPTION_CALLBACK, 0, "porcelain", &status_format,
                  N_("version"), N_("machine-readable output"),
                  PARSE_OPT_OPTARG, opt_parse_porcelain },
@@ -1652,6 +1653,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                usage_with_options(builtin_commit_usage, builtin_commit_options);
 
        status_init_config(&s, git_commit_config);
+       s.commit_template = 1;
        status_format = STATUS_FORMAT_NONE; /* Ignore status.short */
        s.colopts = 0;
 
index 7f6c25d4d95b37f7785e0b6872d059095548c87f..70ff231e9c5bce550e7af20ddfe91b8b68ee32ae 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "color.h"
 #include "parse-options.h"
 #include "urlmatch.h"
@@ -214,8 +215,7 @@ static int get_value(const char *key_, const char *regex_)
                key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
                if (regcomp(key_regexp, key, REG_EXTENDED)) {
                        error("invalid key pattern: %s", key_);
-                       free(key_regexp);
-                       key_regexp = NULL;
+                       FREE_AND_NULL(key_regexp);
                        ret = CONFIG_INVALID_PATTERN;
                        goto free_strings;
                }
@@ -235,15 +235,14 @@ static int get_value(const char *key_, const char *regex_)
                regexp = (regex_t*)xmalloc(sizeof(regex_t));
                if (regcomp(regexp, regex_, REG_EXTENDED)) {
                        error("invalid pattern: %s", regex_);
-                       free(regexp);
-                       regexp = NULL;
+                       FREE_AND_NULL(regexp);
                        ret = CONFIG_INVALID_PATTERN;
                        goto free_strings;
                }
        }
 
-       git_config_with_options(collect_config, &values,
-                               &given_config_source, &config_options);
+       config_with_options(collect_config, &values,
+                           &given_config_source, &config_options);
 
        ret = !values.nr;
 
@@ -320,8 +319,8 @@ static void get_color(const char *var, const char *def_color)
        get_color_slot = var;
        get_color_found = 0;
        parsed_color[0] = '\0';
-       git_config_with_options(git_get_color_config, NULL,
-                               &given_config_source, &config_options);
+       config_with_options(git_get_color_config, NULL,
+                           &given_config_source, &config_options);
 
        if (!get_color_found && def_color) {
                if (color_parse(def_color, parsed_color) < 0)
@@ -352,8 +351,8 @@ static int get_colorbool(const char *var, int print)
        get_colorbool_found = -1;
        get_diff_color_found = -1;
        get_color_ui_found = -1;
-       git_config_with_options(git_get_colorbool_config, NULL,
-                               &given_config_source, &config_options);
+       config_with_options(git_get_colorbool_config, NULL,
+                           &given_config_source, &config_options);
 
        if (get_colorbool_found < 0) {
                if (!strcmp(get_colorbool_slot, "color.diff"))
@@ -441,8 +440,8 @@ static int get_urlmatch(const char *var, const char *url)
                show_keys = 1;
        }
 
-       git_config_with_options(urlmatch_config_entry, &config,
-                               &given_config_source, &config_options);
+       config_with_options(urlmatch_config_entry, &config,
+                           &given_config_source, &config_options);
 
        ret = !values.nr;
 
@@ -538,6 +537,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                config_options.respect_includes = !given_config_source.file;
        else
                config_options.respect_includes = respect_includes_opt;
+       if (!nongit) {
+               config_options.commondir = get_git_common_dir();
+               config_options.git_dir = get_git_dir();
+       }
 
        if (end_null) {
                term = '\0';
@@ -582,9 +585,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 
        if (actions == ACTION_LIST) {
                check_argc(argc, 0, 0);
-               if (git_config_with_options(show_all_config, NULL,
-                                           &given_config_source,
-                                           &config_options) < 0) {
+               if (config_with_options(show_all_config, NULL,
+                                       &given_config_source,
+                                       &config_options) < 0) {
                        if (given_config_source.file)
                                die_errno("unable to read config file '%s'",
                                          given_config_source.file);
index acb05940fc3cd902d4c9bfa480f2c473dcc4d9d5..1d82e61f2a6391bd93a6c3dd91a2515189ff79cc 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "dir.h"
 #include "builtin.h"
 #include "parse-options.h"
index 2fe05f5324ee5b25b59e911874569599f804fd0d..19eacdd170d98ea583cc2eb373247df600be24d7 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "commit.h"
 #include "tag.h"
index c97069a714e42a1737b5dfa223fe39c26ad9aa67..17bf84d18f802d3f223e7408fee644b94878b35f 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "config.h"
 #include "diff.h"
 #include "commit.h"
 #include "revision.h"
index d59bf6cf5f8da394251532765f27a044c14a572d..185e6f9b582fdcf15072038b570463a0cfb1bbf2 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "diff.h"
 #include "commit.h"
 #include "revision.h"
index 7e15d01f36396fdc6b630eb43a5f36d462fb78e6..31d2cb410738d335d9f6431d6901ea1c0f8b67ff 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "diff.h"
 #include "commit.h"
 #include "log-tree.h"
index d9152c21bf5a8aa41778f838b4d804ac698bdc2b..7cde6abbcf7651af8313bd3d70eb1944e72c9cb3 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2006 Junio C Hamano
  */
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "color.h"
 #include "commit.h"
index b9a892f2693efe01a08c958f7064f13ba6ec43aa..9199227f6e9dc0b6d0c3e350f701aeaf9caaddd3 100644 (file)
@@ -12,6 +12,7 @@
  * Copyright (C) 2016 Johannes Schindelin
  */
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "run-command.h"
 #include "exec_cmd.h"
index a932be04f4d5f733eebe1ebeba82c1bc64de3088..12d501bfde3aac09c411169f99ff28ad35593a3b 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "commit.h"
 #include "object.h"
index 100248c5afe3e1c16fa7fe79696200aeb5d1bde2..1838a9abfba61b76a52e96520b9dc559cf4747a2 100644 (file)
@@ -2,6 +2,7 @@
  * "git fetch"
  */
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "commit.h"
 #include "builtin.h"
@@ -249,9 +250,11 @@ static void find_non_local_tags(struct transport *transport,
                 */
                if (ends_with(ref->name, "^{}")) {
                        if (item &&
-                           !has_object_file_with_flags(&ref->old_oid, HAS_SHA1_QUICK) &&
+                           !has_object_file_with_flags(&ref->old_oid,
+                                                       OBJECT_INFO_QUICK) &&
                            !will_fetch(head, ref->old_oid.hash) &&
-                           !has_sha1_file_with_flags(item->util, HAS_SHA1_QUICK) &&
+                           !has_sha1_file_with_flags(item->util,
+                                                     OBJECT_INFO_QUICK) &&
                            !will_fetch(head, item->util))
                                item->util = NULL;
                        item = NULL;
@@ -265,7 +268,7 @@ static void find_non_local_tags(struct transport *transport,
                 * fetch.
                 */
                if (item &&
-                   !has_sha1_file_with_flags(item->util, HAS_SHA1_QUICK) &&
+                   !has_sha1_file_with_flags(item->util, OBJECT_INFO_QUICK) &&
                    !will_fetch(head, item->util))
                        item->util = NULL;
 
@@ -286,7 +289,7 @@ static void find_non_local_tags(struct transport *transport,
         * checked to see if it needs fetching.
         */
        if (item &&
-           !has_sha1_file_with_flags(item->util, HAS_SHA1_QUICK) &&
+           !has_sha1_file_with_flags(item->util, OBJECT_INFO_QUICK) &&
            !will_fetch(head, item->util))
                item->util = NULL;
 
index 70137b0b7e56e6319872fddc3527fe1094009dee..10cbb434163f2f6e60e0cc9cb55bab220004a549 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "commit.h"
 #include "diff.h"
index eca365bf89bb64a71d02d21da29fc1e84204c1a1..52be99cbacdd84f60e5b9f2efd1f1d50f602cdb8 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "object.h"
 #include "parse-options.h"
index 3a2c27f2413e5e377926e0e7df339549c37a76b3..99dea7adf60a61906500b4aebc6cb7d566339b38 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "tree.h"
 #include "blob.h"
@@ -536,7 +537,7 @@ static int fsck_cruft(const char *basename, const char *path, void *data)
        return 0;
 }
 
-static int fsck_subdir(int nr, const char *path, void *progress)
+static int fsck_subdir(unsigned int nr, const char *path, void *progress)
 {
        display_progress(progress, nr + 1);
        return 0;
index f484eda43ca06046924931d2055b50c2f89ea8d7..bd91f136fed125ab06502c22b74b4f193f60773a 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include "builtin.h"
+#include "config.h"
 #include "tempfile.h"
 #include "lockfile.h"
 #include "parse-options.h"
index 3e4b9600e86b661c99f4b936dfa574029ac4fbba..fa351c49f4fd74b3cde1703ef98dba5f0c2c4e8f 100644 (file)
@@ -4,6 +4,8 @@
  * Copyright (c) 2006 Junio C Hamano
  */
 #include "cache.h"
+#include "repository.h"
+#include "config.h"
 #include "blob.h"
 #include "tree.h"
 #include "commit.h"
@@ -642,11 +644,11 @@ static int grep_submodule_launch(struct grep_opt *opt,
 static int grep_submodule(struct grep_opt *opt, const struct object_id *oid,
                          const char *filename, const char *path)
 {
-       if (!is_submodule_initialized(path))
+       if (!is_submodule_active(the_repository, path))
                return 0;
        if (!is_submodule_populated_gently(path, NULL)) {
                /*
-                * If searching history, check for the presense of the
+                * If searching history, check for the presence of the
                 * submodule's gitdir before skipping the submodule.
                 */
                if (oid) {
index bbeaf20bcca1ae1e9bfa55b5a8e4adbed83c00e8..d04baf999a94cfa6a07e74861876d6a9f1c88a6d 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) Junio C Hamano, 2005
  */
 #include "builtin.h"
+#include "config.h"
 #include "blob.h"
 #include "quote.h"
 #include "parse-options.h"
index 49f7a07f85db1e36d959749adf2eb1962940fb19..334a8494abcc4ac52babf468d8a1ef415aa7f297 100644 (file)
@@ -2,6 +2,7 @@
  * Builtin help command
  */
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "exec_cmd.h"
 #include "parse-options.h"
index 04b9dcaf0f4ca90712cbb85cace521e226194f3b..26828c1d82bc9a997041cb464d4a3fde38e2d19d 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "delta.h"
 #include "pack.h"
 #include "csum-file.h"
@@ -388,8 +389,7 @@ static struct base_data *alloc_base_data(void)
 static void free_base_data(struct base_data *c)
 {
        if (c->data) {
-               free(c->data);
-               c->data = NULL;
+               FREE_AND_NULL(c->data);
                get_thread_data()->base_cache_used -= c->size;
        }
 }
@@ -605,8 +605,7 @@ static void *unpack_data(struct object_entry *obj,
        git_inflate_end(&stream);
        free(inbuf);
        if (consume) {
-               free(data);
-               data = NULL;
+               FREE_AND_NULL(data);
        }
        return data;
 }
@@ -794,7 +793,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
 
        if (startup_info->have_repository) {
                read_lock();
-               collision_test_needed = has_sha1_file_with_flags(oid->hash, HAS_SHA1_QUICK);
+               collision_test_needed =
+                       has_sha1_file_with_flags(oid->hash, OBJECT_INFO_QUICK);
                read_unlock();
        }
 
index 8a6acb0ec69330f7aae20d34fb5c5733f0058c67..47823f9aa4452edfa684b042dd5fbaa935df1d39 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "builtin.h"
 #include "exec_cmd.h"
index 998437b23dcb32a45e4d722d695c86d3cc82b4bc..8ca1de98943bdc62248ddd31708a6632557c61de 100644 (file)
@@ -5,6 +5,7 @@
  *              2006 Junio Hamano
  */
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "color.h"
 #include "commit.h"
index b376afc3124c3240f4f249ccc206efa0b064675e..b8514a0029a1437687a5cf6b6f8bad9792340bc3 100644 (file)
@@ -5,7 +5,10 @@
  *
  * Copyright (C) Linus Torvalds, 2005
  */
+#define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
+#include "repository.h"
+#include "config.h"
 #include "quote.h"
 #include "dir.h"
 #include "builtin.h"
@@ -31,10 +34,8 @@ static int line_terminator = '\n';
 static int debug_mode;
 static int show_eol;
 static int recurse_submodules;
-static struct argv_array submodule_options = ARGV_ARRAY_INIT;
 
 static const char *prefix;
-static const char *super_prefix;
 static int max_prefix_len;
 static int prefix_len;
 static struct pathspec pathspec;
@@ -53,17 +54,17 @@ static const char *tag_modified = "";
 static const char *tag_skip_worktree = "";
 static const char *tag_resolve_undo = "";
 
-static void write_eolinfo(const struct cache_entry *ce, const char *path)
+static void write_eolinfo(const struct index_state *istate,
+                         const struct cache_entry *ce, const char *path)
 {
-       if (!show_eol)
-               return;
-       else {
+       if (show_eol) {
                struct stat st;
                const char *i_txt = "";
                const char *w_txt = "";
                const char *a_txt = get_convert_attr_ascii(path);
                if (ce && S_ISREG(ce->ce_mode))
-                       i_txt = get_cached_convert_stats_ascii(ce->name);
+                       i_txt = get_cached_convert_stats_ascii(istate,
+                                                              ce->name);
                if (!lstat(path, &st) && S_ISREG(st.st_mode))
                        w_txt = get_wt_convert_stats_ascii(path);
                printf("i/%-5s w/%-5s attr/%-17s\t", i_txt, w_txt, a_txt);
@@ -72,25 +73,49 @@ static void write_eolinfo(const struct cache_entry *ce, const char *path)
 
 static void write_name(const char *name)
 {
-       /*
-        * Prepend the super_prefix to name to construct the full_name to be
-        * written.
-        */
-       struct strbuf full_name = STRBUF_INIT;
-       if (super_prefix) {
-               strbuf_addstr(&full_name, super_prefix);
-               strbuf_addstr(&full_name, name);
-               name = full_name.buf;
-       }
-
        /*
         * With "--full-name", prefix_len=0; this caller needs to pass
         * an empty string in that case (a NULL is good for "").
         */
        write_name_quoted_relative(name, prefix_len ? prefix : NULL,
                                   stdout, line_terminator);
+}
+
+static const char *get_tag(const struct cache_entry *ce, const char *tag)
+{
+       static char alttag[4];
+
+       if (tag && *tag && show_valid_bit && (ce->ce_flags & CE_VALID)) {
+               memcpy(alttag, tag, 3);
+
+               if (isalpha(tag[0])) {
+                       alttag[0] = tolower(tag[0]);
+               } else if (tag[0] == '?') {
+                       alttag[0] = '!';
+               } else {
+                       alttag[0] = 'v';
+                       alttag[1] = tag[0];
+                       alttag[2] = ' ';
+                       alttag[3] = 0;
+               }
 
-       strbuf_release(&full_name);
+               tag = alttag;
+       }
+
+       return tag;
+}
+
+static void print_debug(const struct cache_entry *ce)
+{
+       if (debug_mode) {
+               const struct stat_data *sd = &ce->ce_stat_data;
+
+               printf("  ctime: %d:%d\n", sd->sd_ctime.sec, sd->sd_ctime.nsec);
+               printf("  mtime: %d:%d\n", sd->sd_mtime.sec, sd->sd_mtime.nsec);
+               printf("  dev: %d\tino: %d\n", sd->sd_dev, sd->sd_ino);
+               printf("  uid: %d\tgid: %d\n", sd->sd_uid, sd->sd_gid);
+               printf("  size: %d\tflags: %x\n", sd->sd_size, ce->ce_flags);
+       }
 }
 
 static void show_dir_entry(const char *tag, struct dir_entry *ent)
@@ -104,23 +129,25 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
                return;
 
        fputs(tag, stdout);
-       write_eolinfo(NULL, ent->name);
+       write_eolinfo(NULL, NULL, ent->name);
        write_name(ent->name);
 }
 
-static void show_other_files(struct dir_struct *dir)
+static void show_other_files(const struct index_state *istate,
+                            const struct dir_struct *dir)
 {
        int i;
 
        for (i = 0; i < dir->nr; i++) {
                struct dir_entry *ent = dir->entries[i];
-               if (!cache_name_is_other(ent->name, ent->len))
+               if (!index_name_is_other(istate, ent->name, ent->len))
                        continue;
                show_dir_entry(tag_other, ent);
        }
 }
 
-static void show_killed_files(struct dir_struct *dir)
+static void show_killed_files(const struct index_state *istate,
+                             const struct dir_struct *dir)
 {
        int i;
        for (i = 0; i < dir->nr; i++) {
@@ -134,29 +161,29 @@ static void show_killed_files(struct dir_struct *dir)
                                /* If ent->name is prefix of an entry in the
                                 * cache, it will be killed.
                                 */
-                               pos = cache_name_pos(ent->name, ent->len);
+                               pos = index_name_pos(istate, ent->name, ent->len);
                                if (0 <= pos)
                                        die("BUG: killed-file %.*s not found",
                                                ent->len, ent->name);
                                pos = -pos - 1;
-                               while (pos < active_nr &&
-                                      ce_stage(active_cache[pos]))
+                               while (pos < istate->cache_nr &&
+                                      ce_stage(istate->cache[pos]))
                                        pos++; /* skip unmerged */
-                               if (active_nr <= pos)
+                               if (istate->cache_nr <= pos)
                                        break;
                                /* pos points at a name immediately after
                                 * ent->name in the cache.  Does it expect
                                 * ent->name to be a directory?
                                 */
-                               len = ce_namelen(active_cache[pos]);
+                               len = ce_namelen(istate->cache[pos]);
                                if ((ent->len < len) &&
-                                   !strncmp(active_cache[pos]->name,
+                                   !strncmp(istate->cache[pos]->name,
                                             ent->name, ent->len) &&
-                                   active_cache[pos]->name[ent->len] == '/')
+                                   istate->cache[pos]->name[ent->len] == '/')
                                        killed = 1;
                                break;
                        }
-                       if (0 <= cache_name_pos(ent->name, sp - ent->name)) {
+                       if (0 <= index_name_pos(istate, ent->name, sp - ent->name)) {
                                /* If any of the leading directories in
                                 * ent->name is registered in the cache,
                                 * ent->name will be killed.
@@ -170,100 +197,41 @@ static void show_killed_files(struct dir_struct *dir)
        }
 }
 
-/*
- * Compile an argv_array with all of the options supported by --recurse_submodules
- */
-static void compile_submodule_options(const char **argv,
-                                     const struct dir_struct *dir,
-                                     int show_tag)
-{
-       if (line_terminator == '\0')
-               argv_array_push(&submodule_options, "-z");
-       if (show_tag)
-               argv_array_push(&submodule_options, "-t");
-       if (show_valid_bit)
-               argv_array_push(&submodule_options, "-v");
-       if (show_cached)
-               argv_array_push(&submodule_options, "--cached");
-       if (show_eol)
-               argv_array_push(&submodule_options, "--eol");
-       if (debug_mode)
-               argv_array_push(&submodule_options, "--debug");
-
-       /* Add Pathspecs */
-       argv_array_push(&submodule_options, "--");
-       for (; *argv; argv++)
-               argv_array_push(&submodule_options, *argv);
-}
+static void show_files(struct repository *repo, struct dir_struct *dir);
 
-/**
- * Recursively call ls-files on a submodule
- */
-static void show_gitlink(const struct cache_entry *ce)
+static void show_submodule(struct repository *superproject,
+                          struct dir_struct *dir, const char *path)
 {
-       struct child_process cp = CHILD_PROCESS_INIT;
-       int status;
-       char *dir;
-
-       prepare_submodule_repo_env(&cp.env_array);
-       argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT);
-
-       if (prefix_len)
-               argv_array_pushf(&cp.env_array, "%s=%s",
-                                GIT_TOPLEVEL_PREFIX_ENVIRONMENT,
-                                prefix);
-       argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
-                        super_prefix ? super_prefix : "",
-                        ce->name);
-       argv_array_push(&cp.args, "ls-files");
-       argv_array_push(&cp.args, "--recurse-submodules");
-
-       /* add supported options */
-       argv_array_pushv(&cp.args, submodule_options.argv);
-
-       cp.git_cmd = 1;
-       dir = mkpathdup("%s/%s", get_git_work_tree(), ce->name);
-       cp.dir = dir;
-       status = run_command(&cp);
-       free(dir);
-       if (status)
-               exit(status);
+       struct repository submodule;
+
+       if (repo_submodule_init(&submodule, superproject, path))
+               return;
+
+       if (repo_read_index(&submodule) < 0)
+               die("index file corrupt");
+
+       repo_read_gitmodules(&submodule);
+
+       show_files(&submodule, dir);
+
+       repo_clear(&submodule);
 }
 
-static void show_ce_entry(const char *tag, const struct cache_entry *ce)
+static void show_ce(struct repository *repo, struct dir_struct *dir,
+                   const struct cache_entry *ce, const char *fullname,
+                   const char *tag)
 {
-       struct strbuf name = STRBUF_INIT;
-       int len = max_prefix_len;
-       if (super_prefix)
-               strbuf_addstr(&name, super_prefix);
-       strbuf_addstr(&name, ce->name);
-
-       if (len > ce_namelen(ce))
+       if (max_prefix_len > strlen(fullname))
                die("git ls-files: internal error - cache entry not superset of prefix");
 
        if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
-           submodule_path_match(&pathspec, name.buf, ps_matched)) {
-               show_gitlink(ce);
-       } else if (match_pathspec(&pathspec, name.buf, name.len,
-                                 len, ps_matched,
+           is_submodule_active(repo, ce->name)) {
+               show_submodule(repo, dir, ce->name);
+       } else if (match_pathspec(&pathspec, fullname, strlen(fullname),
+                                 max_prefix_len, ps_matched,
                                  S_ISDIR(ce->ce_mode) ||
                                  S_ISGITLINK(ce->ce_mode))) {
-               if (tag && *tag && show_valid_bit &&
-                   (ce->ce_flags & CE_VALID)) {
-                       static char alttag[4];
-                       memcpy(alttag, tag, 3);
-                       if (isalpha(tag[0]))
-                               alttag[0] = tolower(tag[0]);
-                       else if (tag[0] == '?')
-                               alttag[0] = '!';
-                       else {
-                               alttag[0] = 'v';
-                               alttag[1] = tag[0];
-                               alttag[2] = ' ';
-                               alttag[3] = 0;
-                       }
-                       tag = alttag;
-               }
+               tag = get_tag(ce, tag);
 
                if (!show_stage) {
                        fputs(tag, stdout);
@@ -274,30 +242,20 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
                               find_unique_abbrev(ce->oid.hash, abbrev),
                               ce_stage(ce));
                }
-               write_eolinfo(ce, ce->name);
-               write_name(ce->name);
-               if (debug_mode) {
-                       const struct stat_data *sd = &ce->ce_stat_data;
-
-                       printf("  ctime: %d:%d\n", sd->sd_ctime.sec, sd->sd_ctime.nsec);
-                       printf("  mtime: %d:%d\n", sd->sd_mtime.sec, sd->sd_mtime.nsec);
-                       printf("  dev: %d\tino: %d\n", sd->sd_dev, sd->sd_ino);
-                       printf("  uid: %d\tgid: %d\n", sd->sd_uid, sd->sd_gid);
-                       printf("  size: %d\tflags: %x\n", sd->sd_size, ce->ce_flags);
-               }
+               write_eolinfo(repo->index, ce, fullname);
+               write_name(fullname);
+               print_debug(ce);
        }
-
-       strbuf_release(&name);
 }
 
-static void show_ru_info(void)
+static void show_ru_info(const struct index_state *istate)
 {
        struct string_list_item *item;
 
-       if (!the_index.resolve_undo)
+       if (!istate->resolve_undo)
                return;
 
-       for_each_string_list_item(item, the_index.resolve_undo) {
+       for_each_string_list_item(item, istate->resolve_undo) {
                const char *path = item->string;
                struct resolve_undo_info *ui = item->util;
                int i, len;
@@ -319,88 +277,110 @@ static void show_ru_info(void)
        }
 }
 
-static int ce_excluded(struct dir_struct *dir, const struct cache_entry *ce)
+static int ce_excluded(struct dir_struct *dir, struct index_state *istate,
+                      const char *fullname, const struct cache_entry *ce)
 {
        int dtype = ce_to_dtype(ce);
-       return is_excluded(dir, &the_index, ce->name, &dtype);
+       return is_excluded(dir, istate, fullname, &dtype);
+}
+
+static void construct_fullname(struct strbuf *out, const struct repository *repo,
+                              const struct cache_entry *ce)
+{
+       strbuf_reset(out);
+       if (repo->submodule_prefix)
+               strbuf_addstr(out, repo->submodule_prefix);
+       strbuf_addstr(out, ce->name);
 }
 
-static void show_files(struct dir_struct *dir)
+static void show_files(struct repository *repo, struct dir_struct *dir)
 {
        int i;
+       struct strbuf fullname = STRBUF_INIT;
 
        /* For cached/deleted files we don't need to even do the readdir */
        if (show_others || show_killed) {
                if (!show_others)
                        dir->flags |= DIR_COLLECT_KILLED_ONLY;
-               fill_directory(dir, &the_index, &pathspec);
+               fill_directory(dir, repo->index, &pathspec);
                if (show_others)
-                       show_other_files(dir);
+                       show_other_files(repo->index, dir);
                if (show_killed)
-                       show_killed_files(dir);
+                       show_killed_files(repo->index, dir);
        }
        if (show_cached || show_stage) {
-               for (i = 0; i < active_nr; i++) {
-                       const struct cache_entry *ce = active_cache[i];
+               for (i = 0; i < repo->index->cache_nr; i++) {
+                       const struct cache_entry *ce = repo->index->cache[i];
+
+                       construct_fullname(&fullname, repo, ce);
+
                        if ((dir->flags & DIR_SHOW_IGNORED) &&
-                           !ce_excluded(dir, ce))
+                           !ce_excluded(dir, repo->index, fullname.buf, ce))
                                continue;
                        if (show_unmerged && !ce_stage(ce))
                                continue;
                        if (ce->ce_flags & CE_UPDATE)
                                continue;
-                       show_ce_entry(ce_stage(ce) ? tag_unmerged :
-                               (ce_skip_worktree(ce) ? tag_skip_worktree : tag_cached), ce);
+                       show_ce(repo, dir, ce, fullname.buf,
+                               ce_stage(ce) ? tag_unmerged :
+                               (ce_skip_worktree(ce) ? tag_skip_worktree :
+                                tag_cached));
                }
        }
        if (show_deleted || show_modified) {
-               for (i = 0; i < active_nr; i++) {
-                       const struct cache_entry *ce = active_cache[i];
+               for (i = 0; i < repo->index->cache_nr; i++) {
+                       const struct cache_entry *ce = repo->index->cache[i];
                        struct stat st;
                        int err;
+
+                       construct_fullname(&fullname, repo, ce);
+
                        if ((dir->flags & DIR_SHOW_IGNORED) &&
-                           !ce_excluded(dir, ce))
+                           !ce_excluded(dir, repo->index, fullname.buf, ce))
                                continue;
                        if (ce->ce_flags & CE_UPDATE)
                                continue;
                        if (ce_skip_worktree(ce))
                                continue;
-                       err = lstat(ce->name, &st);
+                       err = lstat(fullname.buf, &st);
                        if (show_deleted && err)
-                               show_ce_entry(tag_removed, ce);
-                       if (show_modified && ce_modified(ce, &st, 0))
-                               show_ce_entry(tag_modified, ce);
+                               show_ce(repo, dir, ce, fullname.buf, tag_removed);
+                       if (show_modified && ie_modified(repo->index, ce, &st, 0))
+                               show_ce(repo, dir, ce, fullname.buf, tag_modified);
                }
        }
+
+       strbuf_release(&fullname);
 }
 
 /*
  * Prune the index to only contain stuff starting with "prefix"
  */
-static void prune_cache(const char *prefix, size_t prefixlen)
+static void prune_index(struct index_state *istate,
+                       const char *prefix, size_t prefixlen)
 {
        int pos;
        unsigned int first, last;
 
        if (!prefix)
                return;
-       pos = cache_name_pos(prefix, prefixlen);
+       pos = index_name_pos(istate, prefix, prefixlen);
        if (pos < 0)
                pos = -pos-1;
        first = pos;
-       last = active_nr;
+       last = istate->cache_nr;
        while (last > first) {
                int next = (last + first) >> 1;
-               const struct cache_entry *ce = active_cache[next];
+               const struct cache_entry *ce = istate->cache[next];
                if (!strncmp(ce->name, prefix, prefixlen)) {
                        first = next+1;
                        continue;
                }
                last = next;
        }
-       memmove(active_cache, active_cache + pos,
+       memmove(istate->cache, istate->cache + pos,
                (last - pos) * sizeof(struct cache_entry *));
-       active_nr = last - pos;
+       istate->cache_nr = last - pos;
 }
 
 static int get_common_prefix_len(const char *common_prefix)
@@ -430,7 +410,8 @@ static int get_common_prefix_len(const char *common_prefix)
  * that were given from the command line.  We are not
  * going to write this index out.
  */
-void overlay_tree_on_cache(const char *tree_name, const char *prefix)
+void overlay_tree_on_index(struct index_state *istate,
+                          const char *tree_name, const char *prefix)
 {
        struct tree *tree;
        struct object_id oid;
@@ -445,8 +426,8 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
                die("bad tree-ish %s", tree_name);
 
        /* Hoist the unmerged entries up to stage #3 to make room */
-       for (i = 0; i < active_nr; i++) {
-               struct cache_entry *ce = active_cache[i];
+       for (i = 0; i < istate->cache_nr; i++) {
+               struct cache_entry *ce = istate->cache[i];
                if (!ce_stage(ce))
                        continue;
                ce->ce_flags |= CE_STAGEMASK;
@@ -459,11 +440,11 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
                               PATHSPEC_PREFER_CWD, prefix, matchbuf);
        } else
                memset(&pathspec, 0, sizeof(pathspec));
-       if (read_tree(tree, 1, &pathspec))
+       if (read_tree(tree, 1, &pathspec, istate))
                die("unable to read tree entries %s", tree_name);
 
-       for (i = 0; i < active_nr; i++) {
-               struct cache_entry *ce = active_cache[i];
+       for (i = 0; i < istate->cache_nr; i++) {
+               struct cache_entry *ce = istate->cache[i];
                switch (ce_stage(ce)) {
                case 0:
                        last_stage0 = ce;
@@ -594,10 +575,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
        prefix = cmd_prefix;
        if (prefix)
                prefix_len = strlen(prefix);
-       super_prefix = get_super_prefix();
        git_config(git_default_config, NULL);
 
-       if (read_cache() < 0)
+       if (repo_read_index(the_repository) < 0)
                die("index file corrupt");
 
        argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
@@ -631,7 +611,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                setup_work_tree();
 
        if (recurse_submodules)
-               compile_submodule_options(argv, &dir, show_tag);
+               repo_read_gitmodules(the_repository);
 
        if (recurse_submodules &&
            (show_stage || show_deleted || show_others || show_unmerged ||
@@ -649,7 +629,10 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
        /*
         * Find common prefix for all pathspec's
         * This is used as a performance optimization which unfortunately cannot
-        * be done when recursing into submodules
+        * be done when recursing into submodules because when a pathspec is
+        * given which spans repository boundaries you can't simply remove the
+        * submodule entry because the pathspec may match something inside the
+        * submodule.
         */
        if (recurse_submodules)
                max_prefix = NULL;
@@ -657,7 +640,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                max_prefix = common_prefix(&pathspec);
        max_prefix_len = get_common_prefix_len(max_prefix);
 
-       prune_cache(max_prefix, max_prefix_len);
+       prune_index(the_repository->index, max_prefix, max_prefix_len);
 
        /* Treat unmatching pathspec elements as errors */
        if (pathspec.nr && error_unmatch)
@@ -678,11 +661,13 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                 */
                if (show_stage || show_unmerged)
                        die("ls-files --with-tree is incompatible with -s or -u");
-               overlay_tree_on_cache(with_tree, max_prefix);
+               overlay_tree_on_index(the_repository->index, with_tree, max_prefix);
        }
-       show_files(&dir);
+
+       show_files(the_repository, &dir);
+
        if (show_resolve_undo)
-               show_ru_info();
+               show_ru_info(the_repository->index);
 
        if (ps_matched) {
                int bad;
index ee7b293b11eb5c73dd6fe1ea31c5d3bf52c79656..ef965408e8fc5d80fa9e9daf0264a91abccd978c 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "config.h"
 #include "blob.h"
 #include "tree.h"
 #include "commit.h"
index 0c36a70ad8f4dba1744ba6c4fa93389e2b796925..6dbd167d3b0874cd966b4590951a12d01f8f6aeb 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "refs.h"
 #include "diff.h"
index 47dde7c39c922c77bf388e87db27618d09f5bb74..b08803e61119a569e2ca5a33402666d8978d9ff0 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "xdiff/xdiff.h"
 #include "xdiff-interface.h"
 #include "parse-options.h"
index 84970cd85e8b0788928ff24b47c8c1b3dc3409e2..900bafdb45d0b28ab5497cfd251535266fc92be5 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "parse-options.h"
 #include "builtin.h"
 #include "lockfile.h"
index 61d20037add7cf56df721f8d69612b50412f94e9..dcf6736b5b4c53989ee1fb3c5240e04f5dbb337d 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2006 Johannes Schindelin
  */
 #include "builtin.h"
+#include "config.h"
 #include "pathspec.h"
 #include "lockfile.h"
 #include "dir.h"
index d21a5002a7ecbcb6e8921fdab1b1bfdd16dcbe7a..c41ea7c2a62ba868061884e511256c24f4d020d9 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "tag.h"
 #include "refs.h"
index c939a84b7629cd5d4dda09d427255410d723d95b..77573cf1ea8cb4d998597e265263487e22fde592 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "notes.h"
 #include "blob.h"
index f672225def033595602bc4ff91ee26edd9804944..f4a8441fe913850e7a1cadf3376837237519e761 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "attr.h"
 #include "object.h"
 #include "blob.h"
@@ -264,8 +265,7 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent
                 * make sure no cached delta data remains from a
                 * previous attempt before a pack split occurred.
                 */
-               free(entry->delta_data);
-               entry->delta_data = NULL;
+               FREE_AND_NULL(entry->delta_data);
                entry->z_delta_size = 0;
        } else if (entry->delta_data) {
                size = entry->delta_size;
@@ -1375,12 +1375,10 @@ static void cleanup_preferred_base(void)
                if (!pbase_tree_cache[i])
                        continue;
                free(pbase_tree_cache[i]->tree_data);
-               free(pbase_tree_cache[i]);
-               pbase_tree_cache[i] = NULL;
+               FREE_AND_NULL(pbase_tree_cache[i]);
        }
 
-       free(done_pbase_paths);
-       done_pbase_paths = NULL;
+       FREE_AND_NULL(done_pbase_paths);
        done_pbase_paths_num = done_pbase_paths_alloc = 0;
 }
 
@@ -1970,8 +1968,7 @@ static unsigned long free_unpacked(struct unpacked *n)
        n->index = NULL;
        if (n->data) {
                freed_mem += n->entry->size;
-               free(n->data);
-               n->data = NULL;
+               FREE_AND_NULL(n->data);
        }
        n->entry = NULL;
        n->depth = 0;
index 81552e02e412b53fcb50ffa6a4d5949acdaac79c..970d0d30b4f4107e667f3a75d172cc2d25b04b8f 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 
 static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result)
 {
index c026299e789abe19826264225fa2000b3149f875..ac978ad401c01c4f44d3134b95a2bcb8b29973f9 100644 (file)
@@ -10,7 +10,7 @@ static const char * const prune_packed_usage[] = {
 
 static struct progress *progress;
 
-static int prune_subdir(int nr, const char *path, void *data)
+static int prune_subdir(unsigned int nr, const char *path, void *data)
 {
        int *opts = data;
        display_progress(progress, nr + 1);
index f0e2bff04c797b630616bddaefa742e736a423a9..c378690545b27b7e4753e0f919f3ea6626b0eae9 100644 (file)
@@ -68,7 +68,7 @@ static int prune_cruft(const char *basename, const char *path, void *data)
        return 0;
 }
 
-static int prune_subdir(int nr, const char *path, void *data)
+static int prune_subdir(unsigned int nr, const char *path, void *data)
 {
        if (!show_only)
                rmdir(path);
index 69417e4f362f6d7baa11885bd1cb8c5cbb676b14..2ce311a52eb6111fd16951c860d194dc35300438 100644 (file)
@@ -6,6 +6,7 @@
  * Fetch one or more remote refs and merge it/them into the current HEAD.
  */
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "parse-options.h"
 #include "exec_cmd.h"
index 258648d5fd685f4284b3a2bbc0def0076a670b28..03846e83795c477c8e802d078c5a5ed77140d550 100644 (file)
@@ -2,6 +2,7 @@
  * "git push"
  */
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "run-command.h"
 #include "builtin.h"
index 5bfd4c9f76d84c177b72a8ed97d3418d111583e9..d5f618d086365520fcf36ed8db110ba701ba37d3 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "object.h"
 #include "tree.h"
index ca1ebb2fa18a221446e5f8458e1f30528c31ed98..c82b4dce6838fa039e9c2cfc769c7cd17a8ef562 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "parse-options.h"
 #include "sequencer.h"
 
index b1706a5731c0e527a8abc1d42ac4f0e6d346c47c..71c0c768db92378b824951acd6efb7179438017b 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "pack.h"
 #include "refs.h"
index 96c82b4f5ef419f14425f47b2be699e7c87c3540..e237d927a0881b56135a21a1b0041e7de6ff39ab 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "commit.h"
 #include "refs.h"
index f1a88fe2658986af2e33d3979af1764f6decc43b..6273c0c23c904d5f789ff794458cf0c3f2661d94 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "parse-options.h"
 #include "transport.h"
 #include "remote.h"
index 38ba4ef825ebf4791afb50e72e69bdb61db2aa14..f17a68a17da960813e6e925837638a5d9a26d5ee 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "dir.h"
 #include "parse-options.h"
 #include "run-command.h"
index 89262df5a19c3dcf9b39bb7f1be8c1df7e9305f0..fba336a68a375e20e9b40d332eb58a3f302249fa 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "refs.h"
 #include "parse-options.h"
index 1bf72423bf72d7b7d224c14808b0652d78305d63..ffb66e29073c07c43197ae34f2c31d3b9b610903 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "dir.h"
 #include "parse-options.h"
 #include "string-list.h"
index 45001e5200cb4c5aaf0ad316cf1622f9495d851d..7aeaea2737991f021eb788708c1710305abb4b08 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright (c) 2005, 2006 Linus Torvalds and Junio C Hamano
  */
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "tag.h"
 #include "object.h"
index b250c515b1aecab2b43aebe591ad7a22d5829271..95d84d5cda1bdb6a699bc74ad57f7f1910946440 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "diff.h"
 #include "revision.h"
index efdc14473be53ff79b13012d650ec5fded052fd9..c78b7b33d6604bb38a16e30d64cfabee0fd67f40 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "refs.h"
 #include "quote.h"
index 345d9586a709c08a1095f2635833d075c45fe7be..16028b9ea82edee9cf41044c69a47e8994d78fc6 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "parse-options.h"
 #include "diff.h"
index b39f10fcb64f047090967dbf8b31120d2beb1b67..52826d137935ca6698006258ebdb8b207f7161df 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) Linus Torvalds 2006
  */
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "dir.h"
 #include "cache-tree.h"
index b8e2e74fe0c5cdefa6ed4d6c309a8bba203cc6e8..633e0c3cdd3171e6e51944c5b68e4a4afa48862e 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "commit.h"
 #include "refs.h"
 #include "pkt-line.h"
index 7cff1839fc15f46d58c9f78361f362d1d790cbd9..43c4799ea9a9d963f9a44be5cd0ee5bc511e73df 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "diff.h"
 #include "string-list.h"
index 82f378e7f59f306499bf38f802f09187617dde00..7073a3eb9769cae1f00e714a93528b33ca651d9c 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "refs.h"
 #include "builtin.h"
index 1e62a008cbc57691c6a0055f0286a2c11d1e3122..bdf032886912bb768cf3528efbffab4fe3029a58 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "parse-options.h"
 #include "strbuf.h"
 
index 1b4d2b346762af8e6150d88fed87409e877ca676..6abdad3294ce84652a55522aff55f6e7673d192f 100644 (file)
@@ -1,10 +1,11 @@
 #include "builtin.h"
+#include "repository.h"
 #include "cache.h"
+#include "config.h"
 #include "parse-options.h"
 #include "quote.h"
 #include "pathspec.h"
 #include "dir.h"
-#include "utf8.h"
 #include "submodule.h"
 #include "submodule-config.h"
 #include "string-list.h"
@@ -279,7 +280,7 @@ static void module_list_active(struct module_list *list)
        for (i = 0; i < list->nr; i++) {
                const struct cache_entry *ce = list->entries[i];
 
-               if (!is_submodule_initialized(ce->name))
+               if (!is_submodule_active(the_repository, ce->name))
                        continue;
 
                ALLOC_GROW(active_modules.entries,
@@ -325,7 +326,7 @@ static int module_list(int argc, const char **argv, const char *prefix)
                        printf("%06o %s %d\t", ce->ce_mode,
                               oid_to_hex(&ce->oid), ce_stage(ce));
 
-               utf8_fprintf(stdout, "%s\n", ce->name);
+               fprintf(stdout, "%s\n", ce->name);
        }
        return 0;
 }
@@ -361,7 +362,7 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
         *
         * Set active flag for the submodule being initialized
         */
-       if (!is_submodule_initialized(path)) {
+       if (!is_submodule_active(the_repository, path)) {
                strbuf_reset(&sb);
                strbuf_addf(&sb, "submodule.%s.active", sub->name);
                git_config_set_gently(sb.buf, "true");
@@ -816,7 +817,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
        }
 
        /* Check if the submodule has been initialized. */
-       if (!is_submodule_initialized(ce->name)) {
+       if (!is_submodule_active(the_repository, ce->name)) {
                next_submodule_warn_missing(suc, out, displaypath);
                goto cleanup;
        }
@@ -1037,7 +1038,7 @@ static int update_clone(int argc, const char **argv, const char *prefix)
                return 1;
 
        for_each_string_list_item(item, &suc.projectlines)
-               utf8_fprintf(stdout, "%s", item->string);
+               fprintf(stdout, "%s", item->string);
 
        return 0;
 }
@@ -1192,7 +1193,7 @@ static int is_active(int argc, const char **argv, const char *prefix)
 
        gitmodules_config();
 
-       return !is_submodule_initialized(argv[1]);
+       return !is_submodule_active(the_repository, argv[1]);
 }
 
 #define SUPPORT_SUPER_PREFIX (1<<0)
index 70addef158b347488366f6c5787d326c3657adcd..df75cb9d4a21a76df3451f925d674b475dc26753 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "cache.h"
 #include "refs.h"
 #include "parse-options.h"
index 1f74a56db749a5e1ffa06715e347cdc1b041033b..01154ea8dcca869ed635eb433d5afe879b8e883c 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "refs.h"
 #include "tag.h"
index 6fc6bcdf7f014a52703fcd44677a705c824bc0b0..73f133419167840d150300faa696bc32027cd02f 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 
 static char *create_temp_file(unsigned char *sha1)
 {
index 8bc9997767adbb77cc8af81b2b289e22f2b61c5a..689a29fac1a50df6e5b8fc3cda617ef1c6d060b3 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "object.h"
 #include "delta.h"
 #include "pack.h"
@@ -112,8 +113,7 @@ static void *get_data(unsigned long size)
                        break;
                if (ret != Z_OK) {
                        error("inflate returned %d", ret);
-                       free(buf);
-                       buf = NULL;
+                       FREE_AND_NULL(buf);
                        if (!recover)
                                exit(1);
                        has_errors = 1;
index f99b1e5790b9b6aeafaa88f438a8a50f1538c2fe..56721cf03db23a2f5a1b8e9419422df916d7b00f 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "quote.h"
 #include "cache-tree.h"
index 0b2ecf41aeda427e75eb7fe36388e7d0d91d5413..40ccfc193bf785cfae0f83526c561eedf0d310bc 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "builtin.h"
 #include "parse-options.h"
index 6c8cc3edc1f5fec4e2aa173f2650a69db5e065f0..873070e517090cbb21bf53cbc03088da6f85ec1f 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "parse-options.h"
 
index aedbb53a2da5e02b2c8fc29a1a4dc22dc76fbefb..6c6f46b4aeaf658f4de9dc02895a2b19a5c7c5a8 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) Eric Biederman, 2005
  */
 #include "builtin.h"
+#include "config.h"
 
 static const char var_usage[] = "git var (-l | <variable>)";
 
index 05b734e6d1bd469b63aa7b51921622a590730b6d..ba38ac9b1518884693e2c89ec19cc9e00fce9fa3 100644 (file)
@@ -6,6 +6,7 @@
  * Based on git-verify-tag
  */
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "commit.h"
 #include "run-command.h"
index c94e156932c0c8e0ba0c2dc302043c0f3ec0336d..c2a1a5c5048412abaa545862dbd0f3dd93338dc5 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "run-command.h"
 #include "parse-options.h"
 
index 5199553d914f266315ffc3f170ef95a2a7f621ff..f9a5f7535aad9c24041e0677dfa4ed4af87cabf0 100644 (file)
@@ -6,6 +6,7 @@
  * Based on git-verify-tag.sh
  */
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "tag.h"
 #include "run-command.h"
index 793306ea5162f1c3e9663c0c99d693b88baaea3d..c98e2ce5f57c1f41ccaf90041a1a22233ae75551 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "dir.h"
 #include "parse-options.h"
@@ -299,10 +300,8 @@ static int add_worktree(const char *path, const char *refname,
        }
 
        is_junk = 0;
-       free(junk_work_tree);
-       free(junk_git_dir);
-       junk_work_tree = NULL;
-       junk_git_dir = NULL;
+       FREE_AND_NULL(junk_work_tree);
+       FREE_AND_NULL(junk_git_dir);
 
 done:
        if (ret || !opts->keep_locked) {
index 084c0df7833f29c7554a4ffe95dac4bda1c6ce66..bd0a78aa3c56b7e817c7ddf6fcaba703d6d5fecc 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "tree.h"
 #include "cache-tree.h"
 #include "parse-options.h"
diff --git a/cache.h b/cache.h
index d6ba8a2f11a63d4d9ec5257a75532414d22526c0..71fe092644c2c4032ed29c2801fefdf976736db0 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -11,6 +11,8 @@
 #include "string-list.h"
 #include "pack-revindex.h"
 #include "hash.h"
+#include "path.h"
+#include "sha1-array.h"
 
 #ifndef platform_SHA_CTX
 /*
@@ -462,6 +464,8 @@ static inline enum object_type object_type(unsigned int mode)
  */
 extern const char * const local_repo_env[];
 
+extern void setup_git_env(void);
+
 /*
  * Returns true iff we have a configured git repository (either via
  * setup_git_directory, or in the environment via $GIT_DIR).
@@ -525,12 +529,15 @@ extern void set_git_work_tree(const char *tree);
 
 extern void setup_work_tree(void);
 /*
- * Find GIT_DIR of the repository that contains the current working directory,
- * without changing the working directory or other global state. The result is
- * appended to gitdir. The return value is either NULL if no repository was
- * found, or pointing to the path inside gitdir's buffer.
+ * Find the commondir and gitdir of the repository that contains the current
+ * working directory, without changing the working directory or other global
+ * state. The result is appended to commondir and gitdir.  If the discovered
+ * gitdir does not correspond to a worktree, then 'commondir' and 'gitdir' will
+ * both have the same result appended to the buffer.  The return value is
+ * either 0 upon success and non-zero if no repository was found.
  */
-extern const char *discover_git_directory(struct strbuf *gitdir);
+extern int discover_git_directory(struct strbuf *commondir,
+                                 struct strbuf *gitdir);
 extern const char *setup_git_directory_gently(int *);
 extern const char *setup_git_directory(void);
 extern char *prefix_path(const char *prefix, int len, const char *path);
@@ -766,7 +773,6 @@ extern int core_apply_sparse_checkout;
 extern int precomposed_unicode;
 extern int protect_hfs;
 extern int protect_ntfs;
-extern int git_db_env, git_index_env, git_graft_env, git_common_dir_env;
 
 /*
  * Include broken refs in all ref iterations, which will
@@ -888,64 +894,6 @@ extern void check_repository_format(void);
 #define DATA_CHANGED    0x0020
 #define TYPE_CHANGED    0x0040
 
-/*
- * Return a statically allocated filename, either generically (mkpath), in
- * the repository directory (git_path), or in a submodule's repository
- * directory (git_path_submodule). In all cases, note that the result
- * may be overwritten by another call to _any_ of the functions. Consider
- * using the safer "dup" or "strbuf" formats below (in some cases, the
- * unsafe versions have already been removed).
- */
-extern const char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
-extern const char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
-extern const char *git_common_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
-
-extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
-       __attribute__((format (printf, 3, 4)));
-extern void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
-       __attribute__((format (printf, 2, 3)));
-extern void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...)
-       __attribute__((format (printf, 2, 3)));
-extern char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
-       __attribute__((format (printf, 2, 3)));
-extern int strbuf_git_path_submodule(struct strbuf *sb, const char *path,
-                                    const char *fmt, ...)
-       __attribute__((format (printf, 3, 4)));
-extern char *git_pathdup(const char *fmt, ...)
-       __attribute__((format (printf, 1, 2)));
-extern char *mkpathdup(const char *fmt, ...)
-       __attribute__((format (printf, 1, 2)));
-extern char *git_pathdup_submodule(const char *path, const char *fmt, ...)
-       __attribute__((format (printf, 2, 3)));
-
-extern void report_linked_checkout_garbage(void);
-
-/*
- * You can define a static memoized git path like:
- *
- *    static GIT_PATH_FUNC(git_path_foo, "FOO");
- *
- * or use one of the global ones below.
- */
-#define GIT_PATH_FUNC(func, filename) \
-       const char *func(void) \
-       { \
-               static char *ret; \
-               if (!ret) \
-                       ret = git_pathdup(filename); \
-               return ret; \
-       }
-
-const char *git_path_cherry_pick_head(void);
-const char *git_path_revert_head(void);
-const char *git_path_squash_msg(void);
-const char *git_path_merge_msg(void);
-const char *git_path_merge_rr(void);
-const char *git_path_merge_mode(void);
-const char *git_path_merge_head(void);
-const char *git_path_fetch_head(void);
-const char *git_path_shallow(void);
-
 /*
  * Return the name of the file in the local object database that would
  * be used to store a loose object with the specified sha1.  The
@@ -1212,13 +1160,12 @@ extern char *xdg_config_home(const char *filename);
  */
 extern char *xdg_cache_home(const char *filename);
 
-/* object replacement */
-#define LOOKUP_REPLACE_OBJECT 1
-#define LOOKUP_UNKNOWN_OBJECT 2
-extern void *read_sha1_file_extended(const unsigned char *sha1, enum object_type *type, unsigned long *size, unsigned flag);
+extern void *read_sha1_file_extended(const unsigned char *sha1,
+                                    enum object_type *type,
+                                    unsigned long *size, int lookup_replace);
 static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
 {
-       return read_sha1_file_extended(sha1, type, size, LOOKUP_REPLACE_OBJECT);
+       return read_sha1_file_extended(sha1, type, size, 1);
 }
 
 /*
@@ -1240,13 +1187,6 @@ static inline const unsigned char *lookup_replace_object(const unsigned char *sh
        return do_lookup_replace_object(sha1);
 }
 
-static inline const unsigned char *lookup_replace_object_extended(const unsigned char *sha1, unsigned flag)
-{
-       if (!(flag & LOOKUP_REPLACE_OBJECT))
-               return sha1;
-       return lookup_replace_object(sha1);
-}
-
 /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
 extern int sha1_object_info(const unsigned char *, unsigned long *);
 extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1);
@@ -1283,15 +1223,10 @@ int read_loose_object(const char *path,
                      void **contents);
 
 /*
- * Return true iff we have an object named sha1, whether local or in
- * an alternate object database, and whether packed or loose.  This
- * function does not respect replace references.
- *
- * If the QUICK flag is set, do not re-check the pack directory
- * when we cannot find the object (this means we may give a false
- * negative answer if another process is simultaneously repacking).
+ * 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.
  */
-#define HAS_SHA1_QUICK 0x1
 extern int has_sha1_file_with_flags(const unsigned char *sha1, int flags);
 static inline int has_sha1_file(const unsigned char *sha1)
 {
@@ -1593,6 +1528,16 @@ extern struct alternate_object_database {
        struct strbuf scratch;
        size_t base_len;
 
+       /*
+        * Used to store the results of readdir(3) calls when searching
+        * for unique abbreviated hashes.  This cache is never
+        * invalidated, thus it's racy and not necessarily accurate.
+        * That's fine for its purpose; don't use it for tasks requiring
+        * greater accuracy!
+        */
+       char loose_objects_subdir_seen[256];
+       struct oid_array loose_objects_cache;
+
        char path[FLEX_ARRAY];
 } *alt_odb_list;
 extern void prepare_alt_odb(void);
@@ -1808,9 +1753,15 @@ typedef int each_loose_object_fn(const struct object_id *oid,
 typedef int each_loose_cruft_fn(const char *basename,
                                const char *path,
                                void *data);
-typedef int each_loose_subdir_fn(int nr,
+typedef int each_loose_subdir_fn(unsigned int nr,
                                 const char *path,
                                 void *data);
+int for_each_file_in_obj_subdir(unsigned int subdir_nr,
+                               struct strbuf *path,
+                               each_loose_object_fn obj_cb,
+                               each_loose_cruft_fn cruft_cb,
+                               each_loose_subdir_fn subdir_cb,
+                               void *data);
 int for_each_loose_file_in_objdir(const char *path,
                                  each_loose_object_fn obj_cb,
                                  each_loose_cruft_fn cruft_cb,
@@ -1842,6 +1793,7 @@ struct object_info {
        off_t *disk_sizep;
        unsigned char *delta_base_sha1;
        struct strbuf *typename;
+       void **contentp;
 
        /* Response */
        enum {
@@ -1873,194 +1825,23 @@ struct object_info {
  */
 #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
 extern int sha1_object_info_extended(const unsigned char *, struct object_info *, unsigned flags);
 extern int packed_object_info(struct packed_git *pack, off_t offset, struct object_info *);
 
 /* Dumb servers support */
 extern int update_server_info(int);
 
-/* git_config_parse_key() returns these negated: */
-#define CONFIG_INVALID_KEY 1
-#define CONFIG_NO_SECTION_OR_NAME 2
-/* git_config_set_gently(), git_config_set_multivar_gently() return the above or these: */
-#define CONFIG_NO_LOCK -1
-#define CONFIG_INVALID_FILE 3
-#define CONFIG_NO_WRITE 4
-#define CONFIG_NOTHING_SET 5
-#define CONFIG_INVALID_PATTERN 6
-#define CONFIG_GENERIC_ERROR 7
-
-#define CONFIG_REGEX_NONE ((void *)1)
-
-struct git_config_source {
-       unsigned int use_stdin:1;
-       const char *file;
-       const char *blob;
-};
-
-enum config_origin_type {
-       CONFIG_ORIGIN_BLOB,
-       CONFIG_ORIGIN_FILE,
-       CONFIG_ORIGIN_STDIN,
-       CONFIG_ORIGIN_SUBMODULE_BLOB,
-       CONFIG_ORIGIN_CMDLINE
-};
-
-struct config_options {
-       unsigned int respect_includes : 1;
-       const char *git_dir;
-};
-
-typedef int (*config_fn_t)(const char *, const char *, void *);
-extern int git_default_config(const char *, const char *, void *);
-extern int git_config_from_file(config_fn_t fn, const char *, void *);
-extern int git_config_from_mem(config_fn_t fn, const enum config_origin_type,
-                                       const char *name, const char *buf, size_t len, void *data);
-extern int git_config_from_blob_sha1(config_fn_t fn, const char *name,
-                                    const unsigned char *sha1, void *data);
-extern void git_config_push_parameter(const char *text);
-extern int git_config_from_parameters(config_fn_t fn, void *data);
-extern void read_early_config(config_fn_t cb, void *data);
-extern void git_config(config_fn_t fn, void *);
-extern int git_config_with_options(config_fn_t fn, void *,
-                                  struct git_config_source *config_source,
-                                  const struct config_options *opts);
-extern int git_parse_ulong(const char *, unsigned long *);
-extern int git_parse_maybe_bool(const char *);
-extern int git_config_int(const char *, const char *);
-extern int64_t git_config_int64(const char *, const char *);
-extern unsigned long git_config_ulong(const char *, const char *);
-extern ssize_t git_config_ssize_t(const char *, const char *);
-extern int git_config_bool_or_int(const char *, const char *, int *);
-extern int git_config_bool(const char *, const char *);
-extern int git_config_maybe_bool(const char *, const char *);
-extern int git_config_string(const char **, const char *, const char *);
-extern int git_config_pathname(const char **, const char *, const char *);
-extern int git_config_set_in_file_gently(const char *, const char *, const char *);
-extern void git_config_set_in_file(const char *, const char *, const char *);
-extern int git_config_set_gently(const char *, const char *);
-extern void git_config_set(const char *, const char *);
-extern int git_config_parse_key(const char *, char **, int *);
-extern int git_config_key_is_valid(const char *key);
-extern int git_config_set_multivar_gently(const char *, const char *, const char *, int);
-extern void git_config_set_multivar(const char *, const char *, const char *, int);
-extern int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, int);
-extern void git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
-extern int git_config_rename_section(const char *, const char *);
-extern int git_config_rename_section_in_file(const char *, const char *, const char *);
-extern const char *git_etc_gitconfig(void);
-extern int git_env_bool(const char *, int);
-extern unsigned long git_env_ulong(const char *, unsigned long);
-extern int git_config_system(void);
-extern int config_error_nonbool(const char *);
-#if defined(__GNUC__)
-#define config_error_nonbool(s) (config_error_nonbool(s), const_error())
-#endif
 extern const char *get_log_output_encoding(void);
 extern const char *get_commit_output_encoding(void);
 
-extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
-
-enum config_scope {
-       CONFIG_SCOPE_UNKNOWN = 0,
-       CONFIG_SCOPE_SYSTEM,
-       CONFIG_SCOPE_GLOBAL,
-       CONFIG_SCOPE_REPO,
-       CONFIG_SCOPE_CMDLINE,
-};
-
-extern enum config_scope current_config_scope(void);
-extern const char *current_config_origin_type(void);
-extern const char *current_config_name(void);
-
-struct config_include_data {
-       int depth;
-       config_fn_t fn;
-       void *data;
-       const struct config_options *opts;
-};
-#define CONFIG_INCLUDE_INIT { 0 }
-extern int git_config_include(const char *name, const char *value, void *data);
-
-/*
- * Match and parse a config key of the form:
- *
- *   section.(subsection.)?key
- *
- * (i.e., what gets handed to a config_fn_t). The caller provides the section;
- * we return -1 if it does not match, 0 otherwise. The subsection and key
- * out-parameters are filled by the function (and *subsection is NULL if it is
- * missing).
- *
- * If the subsection pointer-to-pointer passed in is NULL, returns 0 only if
- * there is no subsection at all.
- */
-extern int parse_config_key(const char *var,
-                           const char *section,
-                           const char **subsection, int *subsection_len,
-                           const char **key);
-
-struct config_set_element {
-       struct hashmap_entry ent;
-       char *key;
-       struct string_list value_list;
-};
-
-struct configset_list_item {
-       struct config_set_element *e;
-       int value_index;
-};
-
-/*
- * the contents of the list are ordered according to their
- * position in the config files and order of parsing the files.
- * (i.e. key-value pair at the last position of .git/config will
- * be at the last item of the list)
- */
-struct configset_list {
-       struct configset_list_item *items;
-       unsigned int nr, alloc;
-};
-
-struct config_set {
-       struct hashmap config_hash;
-       int hash_initialized;
-       struct configset_list list;
-};
-
-extern void git_configset_init(struct config_set *cs);
-extern int git_configset_add_file(struct config_set *cs, const char *filename);
-extern int git_configset_get_value(struct config_set *cs, const char *key, const char **value);
-extern const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);
-extern void git_configset_clear(struct config_set *cs);
-extern int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest);
-extern int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
-extern int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
-extern int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest);
-extern int git_configset_get_bool(struct config_set *cs, const char *key, int *dest);
-extern int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *is_bool, int *dest);
-extern int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);
-extern int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest);
-
-extern int git_config_get_value(const char *key, const char **value);
-extern const struct string_list *git_config_get_value_multi(const char *key);
-extern void git_config_clear(void);
-extern void git_config_iter(config_fn_t fn, void *data);
-extern int git_config_get_string_const(const char *key, const char **dest);
-extern int git_config_get_string(const char *key, char **dest);
-extern int git_config_get_int(const char *key, int *dest);
-extern int git_config_get_ulong(const char *key, unsigned long *dest);
-extern int git_config_get_bool(const char *key, int *dest);
-extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
-extern int git_config_get_maybe_bool(const char *key, int *dest);
-extern int git_config_get_pathname(const char *key, const char **dest);
-extern int git_config_get_untracked_cache(void);
-extern int git_config_get_split_index(void);
-extern int git_config_get_max_percent_split_change(void);
-
-/* This dies if the configured or default date is in the future */
-extern int git_config_get_expiry(const char *key, const char **output);
-
 /*
  * This is a hack for test programs like test-dump-untracked-cache to
  * ensure that they do not modify the untracked cache when reading it.
@@ -2068,16 +1849,6 @@ extern int git_config_get_expiry(const char *key, const char **output);
  */
 extern int ignore_untracked_cache_config;
 
-struct key_value_info {
-       const char *filename;
-       int linenr;
-       enum config_origin_type origin_type;
-       enum config_scope scope;
-};
-
-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);
-
 extern int committer_ident_sufficiently_given(void);
 extern int author_ident_sufficiently_given(void);
 
@@ -2193,7 +1964,8 @@ extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
 #define ws_tab_width(rule)     ((rule) & WS_TAB_WIDTH_MASK)
 
 /* ls-files */
-void overlay_tree_on_cache(const char *tree_name, const char *prefix);
+void overlay_tree_on_index(struct index_state *istate,
+                          const char *tree_name, const char *prefix);
 
 char *alias_lookup(const char *alias);
 int split_cmdline(char *cmdline, const char ***argv);
diff --git a/color.c b/color.c
index dee61557e03f452f1e20ce6c8c467203aa8aed60..31b6207a00de42a386e98c5656209ea7a010abe4 100644 (file)
--- a/color.c
+++ b/color.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "color.h"
 
 static int git_use_color_default = GIT_COLOR_AUTO;
index d55ead18efeba9435bd2f2e76e2d7ac9ddc064c1..ff7bdab1a32478c8719ee3b973742456df7dc629 100644 (file)
--- a/column.c
+++ b/column.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "column.h"
 #include "string-list.h"
 #include "parse-options.h"
index ec9d930440993b265fe74aacd2a3fdb768dccf64..9e163d5adabd93fd48a6b563c5f31c32740e01c7 100644 (file)
@@ -1053,7 +1053,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
                        if (is_file) {
                                struct strbuf buf = STRBUF_INIT;
 
-                               if (convert_to_git(elem->path, result, len, &buf, safe_crlf)) {
+                               if (convert_to_git(&the_index, elem->path, result, len, &buf, safe_crlf)) {
                                        free(result);
                                        result = strbuf_detach(&buf, &len);
                                        result_size = len;
index 42d16dcded870bfa400421a88b6d0d8c9309a404..333d81e370b188aae2110860df9eaff7b9d9582f 100644 (file)
@@ -82,8 +82,7 @@ static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s)                \
        for (i = 0; i < s->slab_count; i++)                             \
                free(s->slab[i]);                                       \
        s->slab_count = 0;                                              \
-       free(s->slab);                                                  \
-       s->slab = NULL;                                                 \
+       FREE_AND_NULL(s->slab);                                         \
 }                                                                      \
                                                                        \
 static MAYBE_UNUSED elemtype *slabname## _at_peek(struct slabname *s,  \
index 99846d9bf467be8e737341795054588475c65855..cbfd6899392e8715b206c96b3b58cbdaf29c77cd 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -287,8 +287,7 @@ void free_commit_buffer(struct commit *commit)
 {
        struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
        if (v) {
-               free(v->buffer);
-               v->buffer = NULL;
+               FREE_AND_NULL(v->buffer);
                v->size = 0;
        }
 }
index 4293b53b171f5002127d7a354309d343706c0272..de61c15d3483fc4a9e8e163bd7cfa5280996c61a 100644 (file)
@@ -6,6 +6,7 @@
 #define PRECOMPOSE_UNICODE_C
 
 #include "cache.h"
+#include "config.h"
 #include "utf8.h"
 #include "precompose_utf8.h"
 
index eb5e1d44397cdad8f0db910e39037cf6b39f35a9..0a745d9c3b375fbfdefa3afcd021b952cef0e685 100644 (file)
@@ -4102,7 +4102,7 @@ extend_buffers (re_match_context_t *mctx)
   if (BE (INT_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0))
     return REG_ESPACE;
 
-  /* Double the lengthes of the buffers.  */
+  /* Double the lengths of the buffers.  */
   ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
   if (BE (ret != REG_NOERROR, 0))
     return ret;
index 260caf27b87809363aa5ee4d1ffe4fd95ddb8874..a9356c1383861ecf7f33ee0262c8a60bbe20864f 100644 (file)
--- a/config.c
+++ b/config.c
@@ -6,6 +6,8 @@
  *
  */
 #include "cache.h"
+#include "config.h"
+#include "repository.h"
 #include "lockfile.h"
 #include "exec_cmd.h"
 #include "strbuf.h"
@@ -71,13 +73,6 @@ static int core_compression_seen;
 static int pack_compression_seen;
 static int zlib_compression_seen;
 
-/*
- * Default config_set that contains key-value pairs from the usual set of config
- * config files (i.e repo specific .git/config, user wide ~/.gitconfig, XDG
- * config file and the global /etc/gitconfig)
- */
-static struct config_set the_config_set;
-
 static int config_file_fgetc(struct config_source *conf)
 {
        return getc_unlocked(conf->u.file);
@@ -218,8 +213,6 @@ static int include_by_gitdir(const struct config_options *opts,
 
        if (opts->git_dir)
                git_dir = opts->git_dir;
-       else if (have_git_dir())
-               git_dir = get_git_dir();
        else
                goto done;
 
@@ -395,8 +388,7 @@ static int git_config_parse_key_1(const char *key, char **store_key, int *basele
 
 out_free_ret_1:
        if (store_key) {
-               free(*store_key);
-               *store_key = NULL;
+               FREE_AND_NULL(*store_key);
        }
        return -CONFIG_INVALID_KEY;
 }
@@ -604,7 +596,8 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name)
         */
        cf->linenr--;
        ret = fn(name->buf, value, data);
-       cf->linenr++;
+       if (ret >= 0)
+               cf->linenr++;
        return ret;
 }
 
@@ -1545,10 +1538,8 @@ static int do_git_config_sequence(const struct config_options *opts,
        char *user_config = expand_user_path("~/.gitconfig", 0);
        char *repo_config;
 
-       if (opts->git_dir)
-               repo_config = mkpathdup("%s/config", opts->git_dir);
-       else if (have_git_dir())
-               repo_config = git_pathdup("config");
+       if (opts->commondir)
+               repo_config = mkpathdup("%s/config", opts->commondir);
        else
                repo_config = NULL;
 
@@ -1579,9 +1570,9 @@ static int do_git_config_sequence(const struct config_options *opts,
        return ret;
 }
 
-int git_config_with_options(config_fn_t fn, void *data,
-                           struct git_config_source *config_source,
-                           const struct config_options *opts)
+int config_with_options(config_fn_t fn, void *data,
+                       struct git_config_source *config_source,
+                       const struct config_options *opts)
 {
        struct config_include_data inc = CONFIG_INCLUDE_INIT;
 
@@ -1607,26 +1598,6 @@ int git_config_with_options(config_fn_t fn, void *data,
        return do_git_config_sequence(opts, fn, data);
 }
 
-static void git_config_raw(config_fn_t fn, void *data)
-{
-       struct config_options opts = {0};
-
-       opts.respect_includes = 1;
-       if (git_config_with_options(fn, data, NULL, &opts) < 0)
-               /*
-                * git_config_with_options() normally returns only
-                * zero, as most errors are fatal, and
-                * non-fatal potential errors are guarded by "if"
-                * statements that are entered only when no error is
-                * possible.
-                *
-                * If we ever encounter a non-fatal error, it means
-                * something went really wrong and we should stop
-                * immediately.
-                */
-               die(_("unknown error occurred while reading the configuration files"));
-}
-
 static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
 {
        int i, value_index;
@@ -1653,11 +1624,13 @@ static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
 void read_early_config(config_fn_t cb, void *data)
 {
        struct config_options opts = {0};
-       struct strbuf buf = STRBUF_INIT;
+       struct strbuf commondir = STRBUF_INIT;
+       struct strbuf gitdir = STRBUF_INIT;
 
        opts.respect_includes = 1;
 
-       if (have_git_dir())
+       if (have_git_dir()) {
+               opts.commondir = get_git_common_dir();
                opts.git_dir = get_git_dir();
        /*
         * When setup_git_directory() was not yet asked to discover the
@@ -1667,20 +1640,15 @@ void read_early_config(config_fn_t cb, void *data)
         * notably, the current working directory is still the same after the
         * call).
         */
-       else if (discover_git_directory(&buf))
-               opts.git_dir = buf.buf;
-
-       git_config_with_options(cb, data, NULL, &opts);
-
-       strbuf_release(&buf);
-}
+       } else if (!discover_git_directory(&commondir, &gitdir)) {
+               opts.commondir = commondir.buf;
+               opts.git_dir = gitdir.buf;
+       }
 
-static void git_config_check_init(void);
+       config_with_options(cb, data, NULL, &opts);
 
-void git_config(config_fn_t fn, void *data)
-{
-       git_config_check_init();
-       configset_iter(&the_config_set, fn, data);
+       strbuf_release(&commondir);
+       strbuf_release(&gitdir);
 }
 
 static struct config_set_element *configset_find_element(struct config_set *cs, const char *key)
@@ -1892,87 +1860,194 @@ int git_configset_get_pathname(struct config_set *cs, const char *key, const cha
                return 1;
 }
 
-static void git_config_check_init(void)
+/* Functions use to read configuration from a repository */
+static void repo_read_config(struct repository *repo)
+{
+       struct config_options opts;
+
+       opts.respect_includes = 1;
+       opts.commondir = repo->commondir;
+       opts.git_dir = repo->gitdir;
+
+       if (!repo->config)
+               repo->config = xcalloc(1, sizeof(struct config_set));
+       else
+               git_configset_clear(repo->config);
+
+       git_configset_init(repo->config);
+
+       if (config_with_options(config_set_callback, repo->config, NULL, &opts) < 0)
+               /*
+                * config_with_options() normally returns only
+                * zero, as most errors are fatal, and
+                * non-fatal potential errors are guarded by "if"
+                * statements that are entered only when no error is
+                * possible.
+                *
+                * If we ever encounter a non-fatal error, it means
+                * something went really wrong and we should stop
+                * immediately.
+                */
+               die(_("unknown error occurred while reading the configuration files"));
+}
+
+static void git_config_check_init(struct repository *repo)
 {
-       if (the_config_set.hash_initialized)
+       if (repo->config && repo->config->hash_initialized)
                return;
-       git_configset_init(&the_config_set);
-       git_config_raw(config_set_callback, &the_config_set);
+       repo_read_config(repo);
 }
 
-void git_config_clear(void)
+static void repo_config_clear(struct repository *repo)
 {
-       if (!the_config_set.hash_initialized)
+       if (!repo->config || !repo->config->hash_initialized)
                return;
-       git_configset_clear(&the_config_set);
+       git_configset_clear(repo->config);
 }
 
-int git_config_get_value(const char *key, const char **value)
+void repo_config(struct repository *repo, config_fn_t fn, void *data)
 {
-       git_config_check_init();
-       return git_configset_get_value(&the_config_set, key, value);
+       git_config_check_init(repo);
+       configset_iter(repo->config, fn, data);
 }
 
-const struct string_list *git_config_get_value_multi(const char *key)
+int repo_config_get_value(struct repository *repo,
+                         const char *key, const char **value)
 {
-       git_config_check_init();
-       return git_configset_get_value_multi(&the_config_set, key);
+       git_config_check_init(repo);
+       return git_configset_get_value(repo->config, key, value);
 }
 
-int git_config_get_string_const(const char *key, const char **dest)
+const struct string_list *repo_config_get_value_multi(struct repository *repo,
+                                                     const char *key)
+{
+       git_config_check_init(repo);
+       return git_configset_get_value_multi(repo->config, key);
+}
+
+int repo_config_get_string_const(struct repository *repo,
+                                const char *key, const char **dest)
 {
        int ret;
-       git_config_check_init();
-       ret = git_configset_get_string_const(&the_config_set, key, dest);
+       git_config_check_init(repo);
+       ret = git_configset_get_string_const(repo->config, key, dest);
        if (ret < 0)
                git_die_config(key, NULL);
        return ret;
 }
 
+int repo_config_get_string(struct repository *repo,
+                          const char *key, char **dest)
+{
+       git_config_check_init(repo);
+       return repo_config_get_string_const(repo, key, (const char **)dest);
+}
+
+int repo_config_get_int(struct repository *repo,
+                       const char *key, int *dest)
+{
+       git_config_check_init(repo);
+       return git_configset_get_int(repo->config, key, dest);
+}
+
+int repo_config_get_ulong(struct repository *repo,
+                         const char *key, unsigned long *dest)
+{
+       git_config_check_init(repo);
+       return git_configset_get_ulong(repo->config, key, dest);
+}
+
+int repo_config_get_bool(struct repository *repo,
+                        const char *key, int *dest)
+{
+       git_config_check_init(repo);
+       return git_configset_get_bool(repo->config, key, dest);
+}
+
+int repo_config_get_bool_or_int(struct repository *repo,
+                               const char *key, int *is_bool, int *dest)
+{
+       git_config_check_init(repo);
+       return git_configset_get_bool_or_int(repo->config, key, is_bool, dest);
+}
+
+int repo_config_get_maybe_bool(struct repository *repo,
+                              const char *key, int *dest)
+{
+       git_config_check_init(repo);
+       return git_configset_get_maybe_bool(repo->config, key, dest);
+}
+
+int repo_config_get_pathname(struct repository *repo,
+                            const char *key, const char **dest)
+{
+       int ret;
+       git_config_check_init(repo);
+       ret = git_configset_get_pathname(repo->config, key, dest);
+       if (ret < 0)
+               git_die_config(key, NULL);
+       return ret;
+}
+
+/* Functions used historically to read configuration from 'the_repository' */
+void git_config(config_fn_t fn, void *data)
+{
+       repo_config(the_repository, fn, data);
+}
+
+void git_config_clear(void)
+{
+       repo_config_clear(the_repository);
+}
+
+int git_config_get_value(const char *key, const char **value)
+{
+       return repo_config_get_value(the_repository, key, value);
+}
+
+const struct string_list *git_config_get_value_multi(const char *key)
+{
+       return repo_config_get_value_multi(the_repository, key);
+}
+
+int git_config_get_string_const(const char *key, const char **dest)
+{
+       return repo_config_get_string_const(the_repository, key, dest);
+}
+
 int git_config_get_string(const char *key, char **dest)
 {
-       git_config_check_init();
-       return git_config_get_string_const(key, (const char **)dest);
+       return repo_config_get_string(the_repository, key, dest);
 }
 
 int git_config_get_int(const char *key, int *dest)
 {
-       git_config_check_init();
-       return git_configset_get_int(&the_config_set, key, dest);
+       return repo_config_get_int(the_repository, key, dest);
 }
 
 int git_config_get_ulong(const char *key, unsigned long *dest)
 {
-       git_config_check_init();
-       return git_configset_get_ulong(&the_config_set, key, dest);
+       return repo_config_get_ulong(the_repository, key, dest);
 }
 
 int git_config_get_bool(const char *key, int *dest)
 {
-       git_config_check_init();
-       return git_configset_get_bool(&the_config_set, key, dest);
+       return repo_config_get_bool(the_repository, key, dest);
 }
 
 int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)
 {
-       git_config_check_init();
-       return git_configset_get_bool_or_int(&the_config_set, key, is_bool, dest);
+       return repo_config_get_bool_or_int(the_repository, key, is_bool, dest);
 }
 
 int git_config_get_maybe_bool(const char *key, int *dest)
 {
-       git_config_check_init();
-       return git_configset_get_maybe_bool(&the_config_set, key, dest);
+       return repo_config_get_maybe_bool(the_repository, key, dest);
 }
 
 int git_config_get_pathname(const char *key, const char **dest)
 {
-       int ret;
-       git_config_check_init();
-       ret = git_configset_get_pathname(&the_config_set, key, dest);
-       if (ret < 0)
-               git_die_config(key, NULL);
-       return ret;
+       return repo_config_get_pathname(the_repository, key, dest);
 }
 
 int git_config_get_expiry(const char *key, const char **output)
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..0352da1
--- /dev/null
+++ b/config.h
@@ -0,0 +1,218 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+/* git_config_parse_key() returns these negated: */
+#define CONFIG_INVALID_KEY 1
+#define CONFIG_NO_SECTION_OR_NAME 2
+/* git_config_set_gently(), git_config_set_multivar_gently() return the above or these: */
+#define CONFIG_NO_LOCK -1
+#define CONFIG_INVALID_FILE 3
+#define CONFIG_NO_WRITE 4
+#define CONFIG_NOTHING_SET 5
+#define CONFIG_INVALID_PATTERN 6
+#define CONFIG_GENERIC_ERROR 7
+
+#define CONFIG_REGEX_NONE ((void *)1)
+
+struct git_config_source {
+       unsigned int use_stdin:1;
+       const char *file;
+       const char *blob;
+};
+
+enum config_origin_type {
+       CONFIG_ORIGIN_BLOB,
+       CONFIG_ORIGIN_FILE,
+       CONFIG_ORIGIN_STDIN,
+       CONFIG_ORIGIN_SUBMODULE_BLOB,
+       CONFIG_ORIGIN_CMDLINE
+};
+
+struct config_options {
+       unsigned int respect_includes : 1;
+       const char *commondir;
+       const char *git_dir;
+};
+
+typedef int (*config_fn_t)(const char *, const char *, void *);
+extern int git_default_config(const char *, const char *, void *);
+extern int git_config_from_file(config_fn_t fn, const char *, void *);
+extern int git_config_from_mem(config_fn_t fn, const enum config_origin_type,
+                                       const char *name, const char *buf, size_t len, void *data);
+extern int git_config_from_blob_sha1(config_fn_t fn, const char *name,
+                                    const unsigned char *sha1, void *data);
+extern void git_config_push_parameter(const char *text);
+extern int git_config_from_parameters(config_fn_t fn, void *data);
+extern void read_early_config(config_fn_t cb, void *data);
+extern void git_config(config_fn_t fn, void *);
+extern int config_with_options(config_fn_t fn, void *,
+                              struct git_config_source *config_source,
+                              const struct config_options *opts);
+extern int git_parse_ulong(const char *, unsigned long *);
+extern int git_parse_maybe_bool(const char *);
+extern int git_config_int(const char *, const char *);
+extern int64_t git_config_int64(const char *, const char *);
+extern unsigned long git_config_ulong(const char *, const char *);
+extern ssize_t git_config_ssize_t(const char *, const char *);
+extern int git_config_bool_or_int(const char *, const char *, int *);
+extern int git_config_bool(const char *, const char *);
+extern int git_config_maybe_bool(const char *, const char *);
+extern int git_config_string(const char **, const char *, const char *);
+extern int git_config_pathname(const char **, const char *, const char *);
+extern int git_config_set_in_file_gently(const char *, const char *, const char *);
+extern void git_config_set_in_file(const char *, const char *, const char *);
+extern int git_config_set_gently(const char *, const char *);
+extern void git_config_set(const char *, const char *);
+extern int git_config_parse_key(const char *, char **, int *);
+extern int git_config_key_is_valid(const char *key);
+extern int git_config_set_multivar_gently(const char *, const char *, const char *, int);
+extern void git_config_set_multivar(const char *, const char *, const char *, int);
+extern int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, int);
+extern void git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
+extern int git_config_rename_section(const char *, const char *);
+extern int git_config_rename_section_in_file(const char *, const char *, const char *);
+extern const char *git_etc_gitconfig(void);
+extern int git_env_bool(const char *, int);
+extern unsigned long git_env_ulong(const char *, unsigned long);
+extern int git_config_system(void);
+extern int config_error_nonbool(const char *);
+#if defined(__GNUC__)
+#define config_error_nonbool(s) (config_error_nonbool(s), const_error())
+#endif
+
+extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
+
+enum config_scope {
+       CONFIG_SCOPE_UNKNOWN = 0,
+       CONFIG_SCOPE_SYSTEM,
+       CONFIG_SCOPE_GLOBAL,
+       CONFIG_SCOPE_REPO,
+       CONFIG_SCOPE_CMDLINE,
+};
+
+extern enum config_scope current_config_scope(void);
+extern const char *current_config_origin_type(void);
+extern const char *current_config_name(void);
+
+struct config_include_data {
+       int depth;
+       config_fn_t fn;
+       void *data;
+       const struct config_options *opts;
+};
+#define CONFIG_INCLUDE_INIT { 0 }
+extern int git_config_include(const char *name, const char *value, void *data);
+
+/*
+ * Match and parse a config key of the form:
+ *
+ *   section.(subsection.)?key
+ *
+ * (i.e., what gets handed to a config_fn_t). The caller provides the section;
+ * we return -1 if it does not match, 0 otherwise. The subsection and key
+ * out-parameters are filled by the function (and *subsection is NULL if it is
+ * missing).
+ *
+ * If the subsection pointer-to-pointer passed in is NULL, returns 0 only if
+ * there is no subsection at all.
+ */
+extern int parse_config_key(const char *var,
+                           const char *section,
+                           const char **subsection, int *subsection_len,
+                           const char **key);
+
+struct config_set_element {
+       struct hashmap_entry ent;
+       char *key;
+       struct string_list value_list;
+};
+
+struct configset_list_item {
+       struct config_set_element *e;
+       int value_index;
+};
+
+/*
+ * the contents of the list are ordered according to their
+ * position in the config files and order of parsing the files.
+ * (i.e. key-value pair at the last position of .git/config will
+ * be at the last item of the list)
+ */
+struct configset_list {
+       struct configset_list_item *items;
+       unsigned int nr, alloc;
+};
+
+struct config_set {
+       struct hashmap config_hash;
+       int hash_initialized;
+       struct configset_list list;
+};
+
+extern void git_configset_init(struct config_set *cs);
+extern int git_configset_add_file(struct config_set *cs, const char *filename);
+extern int git_configset_get_value(struct config_set *cs, const char *key, const char **value);
+extern const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);
+extern void git_configset_clear(struct config_set *cs);
+extern int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest);
+extern int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
+extern int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
+extern int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest);
+extern int git_configset_get_bool(struct config_set *cs, const char *key, int *dest);
+extern int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *is_bool, int *dest);
+extern int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);
+extern int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest);
+
+/* Functions for reading a repository's config */
+struct repository;
+extern void repo_config(struct repository *repo, config_fn_t fn, void *data);
+extern int repo_config_get_value(struct repository *repo,
+                                const char *key, const char **value);
+extern const struct string_list *repo_config_get_value_multi(struct repository *repo,
+                                                            const char *key);
+extern int repo_config_get_string_const(struct repository *repo,
+                                       const char *key, const char **dest);
+extern int repo_config_get_string(struct repository *repo,
+                                 const char *key, char **dest);
+extern int repo_config_get_int(struct repository *repo,
+                              const char *key, int *dest);
+extern int repo_config_get_ulong(struct repository *repo,
+                                const char *key, unsigned long *dest);
+extern int repo_config_get_bool(struct repository *repo,
+                               const char *key, int *dest);
+extern int repo_config_get_bool_or_int(struct repository *repo,
+                                      const char *key, int *is_bool, int *dest);
+extern int repo_config_get_maybe_bool(struct repository *repo,
+                                     const char *key, int *dest);
+extern int repo_config_get_pathname(struct repository *repo,
+                                   const char *key, const char **dest);
+
+extern int git_config_get_value(const char *key, const char **value);
+extern const struct string_list *git_config_get_value_multi(const char *key);
+extern void git_config_clear(void);
+extern int git_config_get_string_const(const char *key, const char **dest);
+extern int git_config_get_string(const char *key, char **dest);
+extern int git_config_get_int(const char *key, int *dest);
+extern int git_config_get_ulong(const char *key, unsigned long *dest);
+extern int git_config_get_bool(const char *key, int *dest);
+extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
+extern int git_config_get_maybe_bool(const char *key, int *dest);
+extern int git_config_get_pathname(const char *key, const char **dest);
+extern int git_config_get_untracked_cache(void);
+extern int git_config_get_split_index(void);
+extern int git_config_get_max_percent_split_change(void);
+
+/* This dies if the configured or default date is in the future */
+extern int git_config_get_expiry(const char *key, const char **output);
+
+struct key_value_info {
+       const char *filename;
+       int linenr;
+       enum config_origin_type origin_type;
+       enum config_scope scope;
+};
+
+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);
+
+#endif /* CONFIG_H */
index c72b1d1151744c5e7c7b82f453892a1bc9b26021..e78d3f43d84b7f90f4395cb289c9cf0cb34e8297 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "cache.h"
+#include "config.h"
 #include "pkt-line.h"
 #include "quote.h"
 #include "refs.h"
index c03ba737e5fafe63218c7023ce8bbd66c47f7dc5..4490069df9650df6be58a8ad3f566329f7afd6ae 100644 (file)
@@ -9,3 +9,10 @@ expression E;
 @@
 - if (!E)
   free(E);
+
+@@
+expression E;
+@@
+- free(E);
++ FREE_AND_NULL(E);
+- E = NULL;
index 48a2f26622d992b89462edb3658b5cdccee806bc..d93441747523ab2971e114cd6a02d56b79ba3382 100644 (file)
@@ -2641,6 +2641,8 @@ _git_config ()
                sendemail.thread
                sendemail.to
                sendemail.validate
+               sendemail.smtpbatchsize
+               sendemail.smtprelogindelay
                showbranch.default
                status.relativePaths
                status.showUntrackedFiles
diff --git a/contrib/diff-highlight/.gitignore b/contrib/diff-highlight/.gitignore
new file mode 100644 (file)
index 0000000..c074548
--- /dev/null
@@ -0,0 +1,2 @@
+shebang.perl
+diff-highlight
diff --git a/contrib/diff-highlight/DiffHighlight.pm b/contrib/diff-highlight/DiffHighlight.pm
new file mode 100644 (file)
index 0000000..663992e
--- /dev/null
@@ -0,0 +1,233 @@
+package DiffHighlight;
+
+use 5.008;
+use warnings FATAL => 'all';
+use strict;
+
+# Highlight by reversing foreground and background. You could do
+# other things like bold or underline if you prefer.
+my @OLD_HIGHLIGHT = (
+       color_config('color.diff-highlight.oldnormal'),
+       color_config('color.diff-highlight.oldhighlight', "\x1b[7m"),
+       color_config('color.diff-highlight.oldreset', "\x1b[27m")
+);
+my @NEW_HIGHLIGHT = (
+       color_config('color.diff-highlight.newnormal', $OLD_HIGHLIGHT[0]),
+       color_config('color.diff-highlight.newhighlight', $OLD_HIGHLIGHT[1]),
+       color_config('color.diff-highlight.newreset', $OLD_HIGHLIGHT[2])
+);
+
+my $RESET = "\x1b[m";
+my $COLOR = qr/\x1b\[[0-9;]*m/;
+my $BORING = qr/$COLOR|\s/;
+
+# The patch portion of git log -p --graph should only ever have preceding | and
+# not / or \ as merge history only shows up on the commit line.
+my $GRAPH = qr/$COLOR?\|$COLOR?\s+/;
+
+my @removed;
+my @added;
+my $in_hunk;
+
+our $line_cb = sub { print @_ };
+our $flush_cb = sub { local $| = 1 };
+
+sub handle_line {
+       local $_ = shift;
+
+       if (!$in_hunk) {
+               $line_cb->($_);
+               $in_hunk = /^$GRAPH*$COLOR*\@\@ /;
+       }
+       elsif (/^$GRAPH*$COLOR*-/) {
+               push @removed, $_;
+       }
+       elsif (/^$GRAPH*$COLOR*\+/) {
+               push @added, $_;
+       }
+       else {
+               show_hunk(\@removed, \@added);
+               @removed = ();
+               @added = ();
+
+               $line_cb->($_);
+               $in_hunk = /^$GRAPH*$COLOR*[\@ ]/;
+       }
+
+       # Most of the time there is enough output to keep things streaming,
+       # but for something like "git log -Sfoo", you can get one early
+       # commit and then many seconds of nothing. We want to show
+       # that one commit as soon as possible.
+       #
+       # Since we can receive arbitrary input, there's no optimal
+       # place to flush. Flushing on a blank line is a heuristic that
+       # happens to match git-log output.
+       if (!length) {
+               $flush_cb->();
+       }
+}
+
+sub flush {
+       # Flush any queued hunk (this can happen when there is no trailing
+       # context in the final diff of the input).
+       show_hunk(\@removed, \@added);
+}
+
+sub highlight_stdin {
+       while (<STDIN>) {
+               handle_line($_);
+       }
+       flush();
+}
+
+# Ideally we would feed the default as a human-readable color to
+# git-config as the fallback value. But diff-highlight does
+# not otherwise depend on git at all, and there are reports
+# of it being used in other settings. Let's handle our own
+# fallback, which means we will work even if git can't be run.
+sub color_config {
+       my ($key, $default) = @_;
+       my $s = `git config --get-color $key 2>/dev/null`;
+       return length($s) ? $s : $default;
+}
+
+sub show_hunk {
+       my ($a, $b) = @_;
+
+       # If one side is empty, then there is nothing to compare or highlight.
+       if (!@$a || !@$b) {
+               $line_cb->(@$a, @$b);
+               return;
+       }
+
+       # If we have mismatched numbers of lines on each side, we could try to
+       # be clever and match up similar lines. But for now we are simple and
+       # stupid, and only handle multi-line hunks that remove and add the same
+       # number of lines.
+       if (@$a != @$b) {
+               $line_cb->(@$a, @$b);
+               return;
+       }
+
+       my @queue;
+       for (my $i = 0; $i < @$a; $i++) {
+               my ($rm, $add) = highlight_pair($a->[$i], $b->[$i]);
+               $line_cb->($rm);
+               push @queue, $add;
+       }
+       $line_cb->(@queue);
+}
+
+sub highlight_pair {
+       my @a = split_line(shift);
+       my @b = split_line(shift);
+
+       # Find common prefix, taking care to skip any ansi
+       # color codes.
+       my $seen_plusminus;
+       my ($pa, $pb) = (0, 0);
+       while ($pa < @a && $pb < @b) {
+               if ($a[$pa] =~ /$COLOR/) {
+                       $pa++;
+               }
+               elsif ($b[$pb] =~ /$COLOR/) {
+                       $pb++;
+               }
+               elsif ($a[$pa] eq $b[$pb]) {
+                       $pa++;
+                       $pb++;
+               }
+               elsif (!$seen_plusminus && $a[$pa] eq '-' && $b[$pb] eq '+') {
+                       $seen_plusminus = 1;
+                       $pa++;
+                       $pb++;
+               }
+               else {
+                       last;
+               }
+       }
+
+       # Find common suffix, ignoring colors.
+       my ($sa, $sb) = ($#a, $#b);
+       while ($sa >= $pa && $sb >= $pb) {
+               if ($a[$sa] =~ /$COLOR/) {
+                       $sa--;
+               }
+               elsif ($b[$sb] =~ /$COLOR/) {
+                       $sb--;
+               }
+               elsif ($a[$sa] eq $b[$sb]) {
+                       $sa--;
+                       $sb--;
+               }
+               else {
+                       last;
+               }
+       }
+
+       if (is_pair_interesting(\@a, $pa, $sa, \@b, $pb, $sb)) {
+               return highlight_line(\@a, $pa, $sa, \@OLD_HIGHLIGHT),
+                      highlight_line(\@b, $pb, $sb, \@NEW_HIGHLIGHT);
+       }
+       else {
+               return join('', @a),
+                      join('', @b);
+       }
+}
+
+# we split either by $COLOR or by character. This has the side effect of
+# leaving in graph cruft. It works because the graph cruft does not contain "-"
+# or "+"
+sub split_line {
+       local $_ = shift;
+       return utf8::decode($_) ?
+               map { utf8::encode($_); $_ }
+                       map { /$COLOR/ ? $_ : (split //) }
+                       split /($COLOR+)/ :
+               map { /$COLOR/ ? $_ : (split //) }
+               split /($COLOR+)/;
+}
+
+sub highlight_line {
+       my ($line, $prefix, $suffix, $theme) = @_;
+
+       my $start = join('', @{$line}[0..($prefix-1)]);
+       my $mid = join('', @{$line}[$prefix..$suffix]);
+       my $end = join('', @{$line}[($suffix+1)..$#$line]);
+
+       # If we have a "normal" color specified, then take over the whole line.
+       # Otherwise, we try to just manipulate the highlighted bits.
+       if (defined $theme->[0]) {
+               s/$COLOR//g for ($start, $mid, $end);
+               chomp $end;
+               return join('',
+                       $theme->[0], $start, $RESET,
+                       $theme->[1], $mid, $RESET,
+                       $theme->[0], $end, $RESET,
+                       "\n"
+               );
+       } else {
+               return join('',
+                       $start,
+                       $theme->[1], $mid, $theme->[2],
+                       $end
+               );
+       }
+}
+
+# Pairs are interesting to highlight only if we are going to end up
+# highlighting a subset (i.e., not the whole line). Otherwise, the highlighting
+# is just useless noise. We can detect this by finding either a matching prefix
+# or suffix (disregarding boring bits like whitespace and colorization).
+sub is_pair_interesting {
+       my ($a, $pa, $sa, $b, $pb, $sb) = @_;
+       my $prefix_a = join('', @$a[0..($pa-1)]);
+       my $prefix_b = join('', @$b[0..($pb-1)]);
+       my $suffix_a = join('', @$a[($sa+1)..$#$a]);
+       my $suffix_b = join('', @$b[($sb+1)..$#$b]);
+
+       return $prefix_a !~ /^$GRAPH*$COLOR*-$BORING*$/ ||
+              $prefix_b !~ /^$GRAPH*$COLOR*\+$BORING*$/ ||
+              $suffix_a !~ /^$BORING*$/ ||
+              $suffix_b !~ /^$BORING*$/;
+}
index 9018724524ab7868bb015696e301396f1f9b5667..fbf5c582496eece56b29a91a2f3085716f4b0e9f 100644 (file)
@@ -1,5 +1,20 @@
-# nothing to build
-all:
+all: diff-highlight
 
-test:
+PERL_PATH = /usr/bin/perl
+-include ../../config.mak
+
+PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
+
+diff-highlight: shebang.perl DiffHighlight.pm diff-highlight.perl
+       cat $^ >$@+
+       chmod +x $@+
+       mv $@+ $@
+
+shebang.perl: FORCE
+       @echo '#!$(PERL_PATH_SQ)' >$@+
+       @cmp $@+ $@ >/dev/null 2>/dev/null || mv $@+ $@
+
+test: all
        $(MAKE) -C t
+
+.PHONY: FORCE
index 836b97a73075a51ef8bc66ba080085a7de4c8f32..d4c23431752063c7b455d429321264a4bd6becf7 100644 (file)
@@ -99,6 +99,36 @@ newHighlight = "black #aaffaa"
 ---------------------------------------------
 
 
+Using diff-highlight as a module
+--------------------------------
+
+If you want to pre- or post- process the highlighted lines as part of
+another perl script, you can use the DiffHighlight module. You can
+either "require" it or just cat the module together with your script (to
+avoid run-time dependencies).
+
+Your script may set up one or more of the following variables:
+
+  - $DiffHighlight::line_cb - this should point to a function which is
+    called whenever DiffHighlight has lines (which may contain
+    highlights) to output. The default function prints each line to
+    stdout. Note that the function may be called with multiple lines.
+
+  - $DiffHighlight::flush_cb - this should point to a function which
+    flushes the output (because DiffHighlight believes it has completed
+    processing a logical chunk of input). The default function flushes
+    stdout.
+
+The script may then feed lines, one at a time, to DiffHighlight::handle_line().
+When lines are done processing, they will be fed to $line_cb. Note that
+DiffHighlight may queue up many input lines (to analyze a whole hunk)
+before calling $line_cb. After providing all lines, call
+DiffHighlight::flush() to flush any unprocessed lines.
+
+If you just want to process stdin, DiffHighlight::highlight_stdin()
+is a convenience helper which will loop and flush for you.
+
+
 Bugs
 ----
 
diff --git a/contrib/diff-highlight/diff-highlight b/contrib/diff-highlight/diff-highlight
deleted file mode 100755 (executable)
index 81bd804..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-#!/usr/bin/perl
-
-use 5.008;
-use warnings FATAL => 'all';
-use strict;
-
-# Highlight by reversing foreground and background. You could do
-# other things like bold or underline if you prefer.
-my @OLD_HIGHLIGHT = (
-       color_config('color.diff-highlight.oldnormal'),
-       color_config('color.diff-highlight.oldhighlight', "\x1b[7m"),
-       color_config('color.diff-highlight.oldreset', "\x1b[27m")
-);
-my @NEW_HIGHLIGHT = (
-       color_config('color.diff-highlight.newnormal', $OLD_HIGHLIGHT[0]),
-       color_config('color.diff-highlight.newhighlight', $OLD_HIGHLIGHT[1]),
-       color_config('color.diff-highlight.newreset', $OLD_HIGHLIGHT[2])
-);
-
-my $RESET = "\x1b[m";
-my $COLOR = qr/\x1b\[[0-9;]*m/;
-my $BORING = qr/$COLOR|\s/;
-
-# The patch portion of git log -p --graph should only ever have preceding | and
-# not / or \ as merge history only shows up on the commit line.
-my $GRAPH = qr/$COLOR?\|$COLOR?\s+/;
-
-my @removed;
-my @added;
-my $in_hunk;
-
-# Some scripts may not realize that SIGPIPE is being ignored when launching the
-# pager--for instance scripts written in Python.
-$SIG{PIPE} = 'DEFAULT';
-
-while (<>) {
-       if (!$in_hunk) {
-               print;
-               $in_hunk = /^$GRAPH*$COLOR*\@\@ /;
-       }
-       elsif (/^$GRAPH*$COLOR*-/) {
-               push @removed, $_;
-       }
-       elsif (/^$GRAPH*$COLOR*\+/) {
-               push @added, $_;
-       }
-       else {
-               show_hunk(\@removed, \@added);
-               @removed = ();
-               @added = ();
-
-               print;
-               $in_hunk = /^$GRAPH*$COLOR*[\@ ]/;
-       }
-
-       # Most of the time there is enough output to keep things streaming,
-       # but for something like "git log -Sfoo", you can get one early
-       # commit and then many seconds of nothing. We want to show
-       # that one commit as soon as possible.
-       #
-       # Since we can receive arbitrary input, there's no optimal
-       # place to flush. Flushing on a blank line is a heuristic that
-       # happens to match git-log output.
-       if (!length) {
-               local $| = 1;
-       }
-}
-
-# Flush any queued hunk (this can happen when there is no trailing context in
-# the final diff of the input).
-show_hunk(\@removed, \@added);
-
-exit 0;
-
-# Ideally we would feed the default as a human-readable color to
-# git-config as the fallback value. But diff-highlight does
-# not otherwise depend on git at all, and there are reports
-# of it being used in other settings. Let's handle our own
-# fallback, which means we will work even if git can't be run.
-sub color_config {
-       my ($key, $default) = @_;
-       my $s = `git config --get-color $key 2>/dev/null`;
-       return length($s) ? $s : $default;
-}
-
-sub show_hunk {
-       my ($a, $b) = @_;
-
-       # If one side is empty, then there is nothing to compare or highlight.
-       if (!@$a || !@$b) {
-               print @$a, @$b;
-               return;
-       }
-
-       # If we have mismatched numbers of lines on each side, we could try to
-       # be clever and match up similar lines. But for now we are simple and
-       # stupid, and only handle multi-line hunks that remove and add the same
-       # number of lines.
-       if (@$a != @$b) {
-               print @$a, @$b;
-               return;
-       }
-
-       my @queue;
-       for (my $i = 0; $i < @$a; $i++) {
-               my ($rm, $add) = highlight_pair($a->[$i], $b->[$i]);
-               print $rm;
-               push @queue, $add;
-       }
-       print @queue;
-}
-
-sub highlight_pair {
-       my @a = split_line(shift);
-       my @b = split_line(shift);
-
-       # Find common prefix, taking care to skip any ansi
-       # color codes.
-       my $seen_plusminus;
-       my ($pa, $pb) = (0, 0);
-       while ($pa < @a && $pb < @b) {
-               if ($a[$pa] =~ /$COLOR/) {
-                       $pa++;
-               }
-               elsif ($b[$pb] =~ /$COLOR/) {
-                       $pb++;
-               }
-               elsif ($a[$pa] eq $b[$pb]) {
-                       $pa++;
-                       $pb++;
-               }
-               elsif (!$seen_plusminus && $a[$pa] eq '-' && $b[$pb] eq '+') {
-                       $seen_plusminus = 1;
-                       $pa++;
-                       $pb++;
-               }
-               else {
-                       last;
-               }
-       }
-
-       # Find common suffix, ignoring colors.
-       my ($sa, $sb) = ($#a, $#b);
-       while ($sa >= $pa && $sb >= $pb) {
-               if ($a[$sa] =~ /$COLOR/) {
-                       $sa--;
-               }
-               elsif ($b[$sb] =~ /$COLOR/) {
-                       $sb--;
-               }
-               elsif ($a[$sa] eq $b[$sb]) {
-                       $sa--;
-                       $sb--;
-               }
-               else {
-                       last;
-               }
-       }
-
-       if (is_pair_interesting(\@a, $pa, $sa, \@b, $pb, $sb)) {
-               return highlight_line(\@a, $pa, $sa, \@OLD_HIGHLIGHT),
-                      highlight_line(\@b, $pb, $sb, \@NEW_HIGHLIGHT);
-       }
-       else {
-               return join('', @a),
-                      join('', @b);
-       }
-}
-
-# we split either by $COLOR or by character. This has the side effect of
-# leaving in graph cruft. It works because the graph cruft does not contain "-"
-# or "+"
-sub split_line {
-       local $_ = shift;
-       return utf8::decode($_) ?
-               map { utf8::encode($_); $_ }
-                       map { /$COLOR/ ? $_ : (split //) }
-                       split /($COLOR+)/ :
-               map { /$COLOR/ ? $_ : (split //) }
-               split /($COLOR+)/;
-}
-
-sub highlight_line {
-       my ($line, $prefix, $suffix, $theme) = @_;
-
-       my $start = join('', @{$line}[0..($prefix-1)]);
-       my $mid = join('', @{$line}[$prefix..$suffix]);
-       my $end = join('', @{$line}[($suffix+1)..$#$line]);
-
-       # If we have a "normal" color specified, then take over the whole line.
-       # Otherwise, we try to just manipulate the highlighted bits.
-       if (defined $theme->[0]) {
-               s/$COLOR//g for ($start, $mid, $end);
-               chomp $end;
-               return join('',
-                       $theme->[0], $start, $RESET,
-                       $theme->[1], $mid, $RESET,
-                       $theme->[0], $end, $RESET,
-                       "\n"
-               );
-       } else {
-               return join('',
-                       $start,
-                       $theme->[1], $mid, $theme->[2],
-                       $end
-               );
-       }
-}
-
-# Pairs are interesting to highlight only if we are going to end up
-# highlighting a subset (i.e., not the whole line). Otherwise, the highlighting
-# is just useless noise. We can detect this by finding either a matching prefix
-# or suffix (disregarding boring bits like whitespace and colorization).
-sub is_pair_interesting {
-       my ($a, $pa, $sa, $b, $pb, $sb) = @_;
-       my $prefix_a = join('', @$a[0..($pa-1)]);
-       my $prefix_b = join('', @$b[0..($pb-1)]);
-       my $suffix_a = join('', @$a[($sa+1)..$#$a]);
-       my $suffix_b = join('', @$b[($sb+1)..$#$b]);
-
-       return $prefix_a !~ /^$GRAPH*$COLOR*-$BORING*$/ ||
-              $prefix_b !~ /^$GRAPH*$COLOR*\+$BORING*$/ ||
-              $suffix_a !~ /^$BORING*$/ ||
-              $suffix_b !~ /^$BORING*$/;
-}
diff --git a/contrib/diff-highlight/diff-highlight.perl b/contrib/diff-highlight/diff-highlight.perl
new file mode 100644 (file)
index 0000000..9b3e9c1
--- /dev/null
@@ -0,0 +1,8 @@
+package main;
+
+# Some scripts may not realize that SIGPIPE is being ignored when launching the
+# pager--for instance scripts written in Python.
+$SIG{PIPE} = 'DEFAULT';
+
+DiffHighlight::highlight_stdin();
+exit 0;
index c7f86403cf0750289b08be6d7d66180c78242f0c..73fdda6b14e331871cf4879ba85906b09cc0add3 100755 (executable)
@@ -2964,7 +2964,7 @@ def get_revision_recipients(self, revision):
 
 
 class CLIRecipientsEnvironmentMixin(Environment):
-    """Mixin storing recipients information comming from the
+    """Mixin storing recipients information coming from the
     command-line."""
 
     def __init__(self, cli_recipients=None, **kw):
index 41e74fba1e1b1a0b310160e98c0fa26a74e859ca..e7f857c1a2882c7c701af3e2ce6c3223bfd88c7c 100755 (executable)
@@ -857,7 +857,7 @@ sub mw_import_revids {
 
        my $n = 0;
        my $n_actual = 0;
-       my $last_timestamp = 0; # Placeholer in case $rev->timestamp is undefined
+       my $last_timestamp = 0; # Placeholder in case $rev->timestamp is undefined
 
        foreach my $pagerevid (@{$revision_ids}) {
                # Count page even if we skip it, since we display
index 03f6ee5d72f5096e287c23e048746fe1f756f062..2ee34be7e491d34d3dfd7b8236de59bcd777b942 100644 (file)
@@ -121,4 +121,4 @@ How to write a new test
 
 Please, follow the standards given by git. See git/t/README.
 New file should be named as t936[0-9]-*.sh.
-Be sure to reset your wiki regulary with the function `wiki_reset`.
+Be sure to reset your wiki regularly with the function `wiki_reset`.
index 6afa9aafdf3b85b44e69aac419d0cd611bb48017..5c6cc4ab2c270acda160df7a5997266d0076d504 100644 (file)
@@ -19,15 +19,27 @@ htmldir ?= $(prefix)/share/doc/git-doc
 INSTALL  ?= install
 RM       ?= rm -f
 
-ASCIIDOC = asciidoc
-XMLTO    = xmlto
+ASCIIDOC         = asciidoc
+ASCIIDOC_CONF    = -f ../../Documentation/asciidoc.conf
+ASCIIDOC_HTML    = xhtml11
+ASCIIDOC_DOCBOOK = docbook
+ASCIIDOC_EXTRA   =
+XMLTO            = xmlto
+
+ifdef USE_ASCIIDOCTOR
+ASCIIDOC         = asciidoctor
+ASCIIDOC_CONF    =
+ASCIIDOC_HTML    = xhtml5
+ASCIIDOC_DOCBOOK = docbook45
+ASCIIDOC_EXTRA  += -I../../Documentation -rasciidoctor-extensions
+ASCIIDOC_EXTRA  += -alitdd='&\#x2d;&\#x2d;'
+endif
 
 ifndef SHELL_PATH
        SHELL_PATH = /bin/sh
 endif
 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
 
-ASCIIDOC_CONF = ../../Documentation/asciidoc.conf
 MANPAGE_XSL   = ../../Documentation/manpage-normal.xsl
 
 GIT_SUBTREE_SH := git-subtree.sh
@@ -65,12 +77,12 @@ $(GIT_SUBTREE_DOC): $(GIT_SUBTREE_XML)
        $(XMLTO) -m $(MANPAGE_XSL) man $^
 
 $(GIT_SUBTREE_XML): $(GIT_SUBTREE_TXT)
-       $(ASCIIDOC) -b docbook -d manpage -f $(ASCIIDOC_CONF) \
-               -agit_version=$(GIT_VERSION) $^
+       $(ASCIIDOC) -b $(ASCIIDOC_DOCBOOK) -d manpage $(ASCIIDOC_CONF) \
+               -agit_version=$(GIT_VERSION) $(ASCIIDOC_EXTRA) $^
 
 $(GIT_SUBTREE_HTML): $(GIT_SUBTREE_TXT)
-       $(ASCIIDOC) -b xhtml11 -d manpage -f $(ASCIIDOC_CONF) \
-               -agit_version=$(GIT_VERSION) $^
+       $(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage $(ASCIIDOC_CONF) \
+               -agit_version=$(GIT_VERSION) $(ASCIIDOC_EXTRA) $^
 
 $(GIT_SUBTREE_TEST): $(GIT_SUBTREE)
        cp $< $@
index f1e168bc303c71542b692b2b9d08cdb2e2c98669..7d2a519dafe5dcf892df10c51e1bfb83bc8a2091 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -1,4 +1,6 @@
+#define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
+#include "config.h"
 #include "attr.h"
 #include "run-command.h"
 #include "quote.h"
@@ -134,11 +136,12 @@ static const char *gather_convert_stats_ascii(const char *data, unsigned long si
        }
 }
 
-const char *get_cached_convert_stats_ascii(const char *path)
+const char *get_cached_convert_stats_ascii(const struct index_state *istate,
+                                          const char *path)
 {
        const char *ret;
        unsigned long sz;
-       void *data = read_blob_data_from_cache(path, &sz);
+       void *data = read_blob_data_from_index(istate, path, &sz);
        ret = gather_convert_stats_ascii(data, sz);
        free(data);
        return ret;
@@ -217,13 +220,13 @@ static void check_safe_crlf(const char *path, enum crlf_action crlf_action,
        }
 }
 
-static int has_cr_in_index(const char *path)
+static int has_cr_in_index(const struct index_state *istate, const char *path)
 {
        unsigned long sz;
        void *data;
        int has_cr;
 
-       data = read_blob_data_from_cache(path, &sz);
+       data = read_blob_data_from_index(istate, path, &sz);
        if (!data)
                return 0;
        has_cr = memchr(data, '\r', sz) != NULL;
@@ -253,7 +256,8 @@ static int will_convert_lf_to_crlf(size_t len, struct text_stat *stats,
 
 }
 
-static int crlf_to_git(const char *path, const char *src, size_t len,
+static int crlf_to_git(const struct index_state *istate,
+                      const char *path, const char *src, size_t len,
                       struct strbuf *buf,
                       enum crlf_action crlf_action, enum safe_crlf checksafe)
 {
@@ -285,7 +289,8 @@ static int crlf_to_git(const char *path, const char *src, size_t len,
                 * unless we want to renormalize in a merge or
                 * cherry-pick.
                 */
-               if ((checksafe != SAFE_CRLF_RENORMALIZE) && has_cr_in_index(path))
+               if ((checksafe != SAFE_CRLF_RENORMALIZE) &&
+                   has_cr_in_index(istate, path))
                        convert_crlf_into_lf = 0;
        }
        if ((checksafe == SAFE_CRLF_WARN ||
@@ -1081,7 +1086,8 @@ const char *get_convert_attr_ascii(const char *path)
        return "";
 }
 
-int convert_to_git(const char *path, const char *src, size_t len,
+int convert_to_git(const struct index_state *istate,
+                  const char *path, const char *src, size_t len,
                    struct strbuf *dst, enum safe_crlf checksafe)
 {
        int ret = 0;
@@ -1097,7 +1103,7 @@ int convert_to_git(const char *path, const char *src, size_t len,
                src = dst->buf;
                len = dst->len;
        }
-       ret |= crlf_to_git(path, src, len, dst, ca.crlf_action, checksafe);
+       ret |= crlf_to_git(istate, path, src, len, dst, ca.crlf_action, checksafe);
        if (ret && dst) {
                src = dst->buf;
                len = dst->len;
@@ -1105,7 +1111,8 @@ int convert_to_git(const char *path, const char *src, size_t len,
        return ret | ident_to_git(path, src, len, dst, ca.ident);
 }
 
-void convert_to_git_filter_fd(const char *path, int fd, struct strbuf *dst,
+void convert_to_git_filter_fd(const struct index_state *istate,
+                             const char *path, int fd, struct strbuf *dst,
                              enum safe_crlf checksafe)
 {
        struct conv_attrs ca;
@@ -1117,7 +1124,7 @@ void convert_to_git_filter_fd(const char *path, int fd, struct strbuf *dst,
        if (!apply_filter(path, NULL, 0, fd, dst, ca.drv, CAP_CLEAN))
                die("%s: clean filter '%s' failed", path, ca.drv->name);
 
-       crlf_to_git(path, dst->buf, dst->len, dst, ca.crlf_action, checksafe);
+       crlf_to_git(istate, path, dst->buf, dst->len, dst, ca.crlf_action, checksafe);
        ident_to_git(path, dst->buf, dst->len, dst, ca.ident);
 }
 
@@ -1160,14 +1167,15 @@ int convert_to_working_tree(const char *path, const char *src, size_t len, struc
        return convert_to_working_tree_internal(path, src, len, dst, 0);
 }
 
-int renormalize_buffer(const char *path, const char *src, size_t len, struct strbuf *dst)
+int renormalize_buffer(const struct index_state *istate, const char *path,
+                      const char *src, size_t len, struct strbuf *dst)
 {
        int ret = convert_to_working_tree_internal(path, src, len, dst, 1);
        if (ret) {
                src = dst->buf;
                len = dst->len;
        }
-       return ret | convert_to_git(path, src, len, dst, SAFE_CRLF_RENORMALIZE);
+       return ret | convert_to_git(istate, path, src, len, dst, SAFE_CRLF_RENORMALIZE);
 }
 
 /*****************************************************************
index 82871a11d5fb45133096b26ad46c6c0f65797926..cecf59d1aa15f234473dc16520c0a6647e255280 100644 (file)
--- a/convert.h
+++ b/convert.h
@@ -4,6 +4,8 @@
 #ifndef CONVERT_H
 #define CONVERT_H
 
+struct index_state;
+
 enum safe_crlf {
        SAFE_CRLF_FALSE = 0,
        SAFE_CRLF_FAIL = 1,
@@ -33,23 +35,28 @@ enum eol {
 };
 
 extern enum eol core_eol;
-extern const char *get_cached_convert_stats_ascii(const char *path);
+extern const char *get_cached_convert_stats_ascii(const struct index_state *istate,
+                                                 const char *path);
 extern const char *get_wt_convert_stats_ascii(const char *path);
 extern const char *get_convert_attr_ascii(const char *path);
 
 /* returns 1 if *dst was used */
-extern int convert_to_git(const char *path, const char *src, size_t len,
+extern int convert_to_git(const struct index_state *istate,
+                         const char *path, const char *src, size_t len,
                          struct strbuf *dst, enum safe_crlf checksafe);
 extern int convert_to_working_tree(const char *path, const char *src,
                                   size_t len, struct strbuf *dst);
-extern int renormalize_buffer(const char *path, const char *src, size_t len,
+extern int renormalize_buffer(const struct index_state *istate,
+                             const char *path, const char *src, size_t len,
                              struct strbuf *dst);
-static inline int would_convert_to_git(const char *path)
+static inline int would_convert_to_git(const struct index_state *istate,
+                                      const char *path)
 {
-       return convert_to_git(path, NULL, 0, NULL, 0);
+       return convert_to_git(istate, path, NULL, 0, NULL, 0);
 }
 /* Precondition: would_convert_to_git_filter_fd(path) == true */
-extern void convert_to_git_filter_fd(const char *path, int fd,
+extern void convert_to_git_filter_fd(const struct index_state *istate,
+                                    const char *path, int fd,
                                     struct strbuf *dst,
                                     enum safe_crlf checksafe);
 extern int would_convert_to_git_filter_fd(const char *path);
index f3814cc47a059227e24ca52007c7e19fdf2db480..0d5c6250940633e75e2c9fb4b59b242a52188411 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "tempfile.h"
 #include "credential.h"
 #include "unix-socket.h"
index aa996669fc40021e0c8cb01fa8021da7064e2781..9747f47b18bf2e622f11f41889faaa4b1845ac8d 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "credential.h"
 #include "string-list.h"
 #include "run-command.h"
@@ -93,8 +94,7 @@ static void credential_apply_config(struct credential *c)
        c->configured = 1;
 
        if (!c->use_http_path && proto_is_http(c->protocol)) {
-               free(c->path);
-               c->path = NULL;
+               FREE_AND_NULL(c->path);
        }
 }
 
@@ -314,10 +314,8 @@ void credential_reject(struct credential *c)
        for (i = 0; i < c->helpers.nr; i++)
                credential_do(c, c->helpers.items[i].string, "erase");
 
-       free(c->username);
-       c->username = NULL;
-       free(c->password);
-       c->password = NULL;
+       FREE_AND_NULL(c->username);
+       FREE_AND_NULL(c->password);
        c->approved = 0;
 }
 
index ac7181a4832672ef1e599324a15868d1b06f8fc0..30747075f0c45942220f63202f8c984e3e0956a7 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "pkt-line.h"
 #include "run-command.h"
 #include "strbuf.h"
diff --git a/date.c b/date.c
index 1fd6d663758de5a4b9d7f395b16716864317ed84..c3e673fd04221bb444e357ac01a1fe5984375daf 100644 (file)
--- a/date.c
+++ b/date.c
@@ -256,7 +256,7 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
                        tm->tm_hour, tm->tm_min, tm->tm_sec, tz);
        else if (mode->type == DATE_STRFTIME)
                strbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz,
-                               mode->local ? NULL : "");
+                               !mode->local);
        else
                strbuf_addf(&timebuf, "%.3s %.3s %d %02d:%02d:%02d %d%c%+05d",
                                weekday_names[tm->tm_wday],
index 0c0e20f7c004119cd86bc377722eca6d318cdf5d..2a52b079546cb01d8dfe708f7e7c7e38ec582435 100644 (file)
@@ -179,8 +179,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                                free(dpath);
                                continue;
                        }
-                       free(dpath);
-                       dpath = NULL;
+                       FREE_AND_NULL(dpath);
 
                        /*
                         * Show the diff for the 'ce' if we found the one
diff --git a/diff.c b/diff.c
index acedf86aecc151112898ff54575151f157776281..00b4c86698e6badb5d2904cacb3ba7d92c018d76 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -2,6 +2,7 @@
  * Copyright (C) 2005 Junio C Hamano
  */
 #include "cache.h"
+#include "config.h"
 #include "tempfile.h"
 #include "quote.h"
 #include "diff.h"
@@ -1218,8 +1219,7 @@ static void free_diff_words_data(struct emit_callback *ecbdata)
                        regfree(ecbdata->diff_words->word_regex);
                        free(ecbdata->diff_words->word_regex);
                }
-               free(ecbdata->diff_words);
-               ecbdata->diff_words = NULL;
+               FREE_AND_NULL(ecbdata->diff_words);
        }
 }
 
@@ -2755,7 +2755,7 @@ static int reuse_worktree_file(const char *name, const struct object_id *oid, in
         * Similarly, if we'd have to convert the file contents anyway, that
         * makes the optimization not worthwhile.
         */
-       if (!want_file && would_convert_to_git(name))
+       if (!want_file && would_convert_to_git(&the_index, name))
                return 0;
 
        len = strlen(name);
@@ -2877,7 +2877,7 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
                 * point if the path requires us to run the content
                 * conversion.
                 */
-               if (size_only && !would_convert_to_git(s->path))
+               if (size_only && !would_convert_to_git(&the_index, s->path))
                        return 0;
 
                /*
@@ -2904,7 +2904,7 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
                /*
                 * Convert from working tree format to canonical git format
                 */
-               if (convert_to_git(s->path, s->data, s->size, &buf, crlf_warn)) {
+               if (convert_to_git(&the_index, s->path, s->data, s->size, &buf, crlf_warn)) {
                        size_t size = 0;
                        munmap(s->data, s->size);
                        s->should_munmap = 0;
@@ -2951,8 +2951,7 @@ void diff_free_filespec_blob(struct diff_filespec *s)
 void diff_free_filespec_data(struct diff_filespec *s)
 {
        diff_free_filespec_blob(s);
-       free(s->cnt_data);
-       s->cnt_data = NULL;
+       FREE_AND_NULL(s->cnt_data);
 }
 
 static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
index 03d1e8d40bb78d03c6b7257b05275de739693671..1e4678b7d7cb56ee52f160b55924ddeb863e2872 100644 (file)
@@ -667,11 +667,9 @@ void diffcore_rename(struct diff_options *options)
        for (i = 0; i < rename_dst_nr; i++)
                free_filespec(rename_dst[i].two);
 
-       free(rename_dst);
-       rename_dst = NULL;
+       FREE_AND_NULL(rename_dst);
        rename_dst_nr = rename_dst_alloc = 0;
-       free(rename_src);
-       rename_src = NULL;
+       FREE_AND_NULL(rename_src);
        rename_src_nr = rename_src_alloc = 0;
        return;
 }
diff --git a/dir.c b/dir.c
index c64965f237461fd9a40a6850c6d74f65bd2c201e..ae6f5c9636abd34d026579b7ddc8452825af9b30 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -9,6 +9,7 @@
  */
 #define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
+#include "config.h"
 #include "dir.h"
 #include "attr.h"
 #include "refs.h"
@@ -802,7 +803,7 @@ static int add_excludes(const char *fname, const char *base, int baselen,
                                 (pos = index_name_pos(istate, fname, strlen(fname))) >= 0 &&
                                 !ce_stage(istate->cache[pos]) &&
                                 ce_uptodate(istate->cache[pos]) &&
-                                !would_convert_to_git(fname))
+                                !would_convert_to_git(istate, fname))
                                hashcpy(sha1_stat->sha1,
                                        istate->cache[pos]->oid.hash);
                        else
@@ -2124,8 +2125,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
                for (i = j = 0; j < dir->nr; j++) {
                        if (i &&
                            check_dir_entry_contains(dir->entries[i - 1], dir->entries[j])) {
-                               free(dir->entries[j]);
-                               dir->entries[j] = NULL;
+                               FREE_AND_NULL(dir->entries[j]);
                        } else {
                                dir->entries[i++] = dir->entries[j];
                        }
@@ -2151,8 +2151,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
                     dir->untracked->dir_invalidated))
                        istate->cache_changed |= UNTRACKED_CHANGED;
                if (dir->untracked != istate->untracked) {
-                       free(dir->untracked);
-                       dir->untracked = NULL;
+                       FREE_AND_NULL(dir->untracked);
                }
        }
        return dir->nr;
@@ -2495,8 +2494,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra
        strbuf_addbuf(out, &untracked->ident);
 
        strbuf_add(out, ouc, ouc_size(len));
-       free(ouc);
-       ouc = NULL;
+       FREE_AND_NULL(ouc);
 
        if (!untracked->root) {
                varint_len = encode_varint(0, varbuf);
index aa478e71de9d9c233593de050d6823e96be77b88..3fd4b1084590d0118cad5e7ae32fb37e570e7523 100644 (file)
@@ -8,6 +8,8 @@
  * are.
  */
 #include "cache.h"
+#include "repository.h"
+#include "config.h"
 #include "refs.h"
 #include "fmt-merge-msg.h"
 #include "commit.h"
@@ -94,17 +96,11 @@ int ignore_untracked_cache_config;
 
 /* This is set by setup_git_dir_gently() and/or git_default_config() */
 char *git_work_tree_cfg;
-static char *work_tree;
 
 static const char *namespace;
-static size_t namespace_len;
 
 static const char *super_prefix;
 
-static const char *git_dir, *git_common_dir;
-static char *git_object_dir, *git_index_file, *git_graft_file;
-int git_db_env, git_index_env, git_graft_env, git_common_dir_env;
-
 /*
  * Repository-local GIT_* environment variables; see cache.h for details.
  */
@@ -148,48 +144,17 @@ static char *expand_namespace(const char *raw_namespace)
        return strbuf_detach(&buf, NULL);
 }
 
-static char *git_path_from_env(const char *envvar, const char *git_dir,
-                              const char *path, int *fromenv)
+void setup_git_env(void)
 {
-       const char *value = getenv(envvar);
-       if (!value)
-               return xstrfmt("%s/%s", git_dir, path);
-       if (fromenv)
-               *fromenv = 1;
-       return xstrdup(value);
-}
-
-static void setup_git_env(void)
-{
-       struct strbuf sb = STRBUF_INIT;
-       const char *gitfile;
        const char *shallow_file;
        const char *replace_ref_base;
 
-       git_dir = getenv(GIT_DIR_ENVIRONMENT);
-       if (!git_dir) {
-               if (!startup_info->have_repository)
-                       BUG("setup_git_env called without repository");
-               git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
-       }
-       gitfile = read_gitfile(git_dir);
-       git_dir = xstrdup(gitfile ? gitfile : git_dir);
-       if (get_common_dir(&sb, git_dir))
-               git_common_dir_env = 1;
-       git_common_dir = strbuf_detach(&sb, NULL);
-       git_object_dir = git_path_from_env(DB_ENVIRONMENT, git_common_dir,
-                                          "objects", &git_db_env);
-       git_index_file = git_path_from_env(INDEX_ENVIRONMENT, git_dir,
-                                          "index", &git_index_env);
-       git_graft_file = git_path_from_env(GRAFT_ENVIRONMENT, git_common_dir,
-                                          "info/grafts", &git_graft_env);
        if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
                check_replace_refs = 0;
        replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
        git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
                                                          : "refs/replace/");
        namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
-       namespace_len = strlen(namespace);
        shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
        if (shallow_file)
                set_alternate_shallow_file(shallow_file, 0);
@@ -204,36 +169,36 @@ int is_bare_repository(void)
 int have_git_dir(void)
 {
        return startup_info->have_repository
-               || git_dir
-               || getenv(GIT_DIR_ENVIRONMENT);
+               || the_repository->gitdir;
 }
 
 const char *get_git_dir(void)
 {
-       if (!git_dir)
-               setup_git_env();
-       return git_dir;
+       if (!the_repository->gitdir)
+               BUG("git environment hasn't been setup");
+       return the_repository->gitdir;
 }
 
 const char *get_git_common_dir(void)
 {
-       if (!git_dir)
-               setup_git_env();
-       return git_common_dir;
+       if (!the_repository->commondir)
+               BUG("git environment hasn't been setup");
+       return the_repository->commondir;
 }
 
 const char *get_git_namespace(void)
 {
        if (!namespace)
-               setup_git_env();
+               BUG("git environment hasn't been setup");
        return namespace;
 }
 
 const char *strip_namespace(const char *namespaced_ref)
 {
-       if (!starts_with(namespaced_ref, get_git_namespace()))
-               return NULL;
-       return namespaced_ref + namespace_len;
+       const char *out;
+       if (skip_prefix(namespaced_ref, get_git_namespace(), &out))
+               return out;
+       return NULL;
 }
 
 const char *get_super_prefix(void)
@@ -257,26 +222,26 @@ void set_git_work_tree(const char *new_work_tree)
 {
        if (git_work_tree_initialized) {
                new_work_tree = real_path(new_work_tree);
-               if (strcmp(new_work_tree, work_tree))
+               if (strcmp(new_work_tree, the_repository->worktree))
                        die("internal error: work tree has already been set\n"
                            "Current worktree: %s\nNew worktree: %s",
-                           work_tree, new_work_tree);
+                           the_repository->worktree, new_work_tree);
                return;
        }
        git_work_tree_initialized = 1;
-       work_tree = real_pathdup(new_work_tree, 1);
+       repo_set_worktree(the_repository, new_work_tree);
 }
 
 const char *get_git_work_tree(void)
 {
-       return work_tree;
+       return the_repository->worktree;
 }
 
 char *get_object_directory(void)
 {
-       if (!git_object_dir)
-               setup_git_env();
-       return git_object_dir;
+       if (!the_repository->objectdir)
+               BUG("git environment hasn't been setup");
+       return the_repository->objectdir;
 }
 
 int odb_mkstemp(struct strbuf *template, const char *pattern)
@@ -314,22 +279,23 @@ int odb_pack_keep(const char *name)
 
 char *get_index_file(void)
 {
-       if (!git_index_file)
-               setup_git_env();
-       return git_index_file;
+       if (!the_repository->index_file)
+               BUG("git environment hasn't been setup");
+       return the_repository->index_file;
 }
 
 char *get_graft_file(void)
 {
-       if (!git_graft_file)
-               setup_git_env();
-       return git_graft_file;
+       if (!the_repository->graft_file)
+               BUG("git environment hasn't been setup");
+       return the_repository->graft_file;
 }
 
 int set_git_dir(const char *path)
 {
        if (setenv(GIT_DIR_ENVIRONMENT, path, 1))
                return error("Could not set GIT_DIR to '%s'", path);
+       repo_set_gitdir(the_repository, path);
        setup_git_env();
        return 0;
 }
index fc2b22033b0f5748adbc173b6099fa7347bb9088..a959161b4631e134602aa9b5502105ee5c5bcfb8 100644 (file)
@@ -154,6 +154,7 @@ Format of STDIN stream:
 
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "object.h"
 #include "blob.h"
@@ -1063,8 +1064,7 @@ static void end_packfile(void)
                close(pack_data->pack_fd);
                unlink_or_warn(pack_data->pack_name);
        }
-       free(pack_data);
-       pack_data = NULL;
+       FREE_AND_NULL(pack_data);
        running = 0;
 
        /* We can't carry a delta across packfiles. */
@@ -1149,8 +1149,7 @@ static int store_object(
 
                /* We cannot carry a delta into the new pack. */
                if (delta) {
-                       free(delta);
-                       delta = NULL;
+                       FREE_AND_NULL(delta);
 
                        git_deflate_init(&s, pack_compression_level);
                        s.next_in = (void *)dat->buf;
index cd86865beba62ffade9f8aa63427781f301e79e7..fbbc99c88856a773326e4bb310d30fe3021e2333 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "refs.h"
 #include "pkt-line.h"
index 79d675b5b02ee73a025f86acc6cc29e530ee8db6..28b325d75481b74e8f7b16485e1fc18ad854161c 100755 (executable)
@@ -3,7 +3,7 @@
 use 5.008;
 use strict;
 use warnings;
-use Git;
+use Git qw(unquote_path);
 use Git::I18N;
 
 binmode(STDOUT, ":raw");
@@ -174,47 +174,6 @@ sub run_cmd_pipe {
 }
 chomp($GIT_DIR);
 
-my %cquote_map = (
- "b" => chr(8),
- "t" => chr(9),
- "n" => chr(10),
- "v" => chr(11),
- "f" => chr(12),
- "r" => chr(13),
- "\\" => "\\",
- "\042" => "\042",
-);
-
-sub unquote_path {
-       local ($_) = @_;
-       my ($retval, $remainder);
-       if (!/^\042(.*)\042$/) {
-               return $_;
-       }
-       ($_, $retval) = ($1, "");
-       while (/^([^\\]*)\\(.*)$/) {
-               $remainder = $2;
-               $retval .= $1;
-               for ($remainder) {
-                       if (/^([0-3][0-7][0-7])(.*)$/) {
-                               $retval .= chr(oct($1));
-                               $_ = $2;
-                               last;
-                       }
-                       if (/^([\\\042btnvfr])(.*)$/) {
-                               $retval .= $cquote_map{$1};
-                               $_ = $2;
-                               last;
-                       }
-                       # This is malformed -- just return it as-is for now.
-                       return $_[0];
-               }
-               $_ = $remainder;
-       }
-       $retval .= $_;
-       return $retval;
-}
-
 sub refresh {
        my $fh;
        open $fh, 'git update-index --refresh |'
@@ -1081,7 +1040,7 @@ sub edit_hunk_manually {
 
        open $fh, '<', $hunkfile
                or die sprintf(__("failed to open hunk edit file for reading: %s"), $!);
-       my @newtext = grep { !/^$comment_line_char/ } <$fh>;
+       my @newtext = grep { !/^\Q$comment_line_char\E/ } <$fh>;
        close $fh;
        unlink $hunkfile;
 
@@ -1136,6 +1095,7 @@ sub prompt_yesno {
        while (1) {
                print colored $prompt_color, $prompt;
                my $line = prompt_single_character;
+               return undef unless defined $line;
                return 0 if $line =~ /^n/i;
                return 1 if $line =~ /^y/i;
        }
index 51ba4e6b3b7822915e3867722ec0b54b314111f7..047172d173c495d7e723a00db5d563113978f917 100644 (file)
@@ -808,6 +808,12 @@ extern char *xgetcwd(void);
 extern FILE *fopen_for_writing(const char *path);
 extern FILE *fopen_or_warn(const char *path, const char *mode);
 
+/*
+ * FREE_AND_NULL(ptr) is like free(ptr) followed by ptr = NULL. Note
+ * that ptr is used twice, so don't pass e.g. ptr++.
+ */
+#define FREE_AND_NULL(p) do { free(p); (p) = NULL; } while (0)
+
 #define ALLOC_ARRAY(x, alloc) (x) = xmalloc(st_mult(sizeof(*(x)), (alloc)))
 #define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), st_mult(sizeof(*(x)), (alloc)))
 
index db1deed8464f0643763ed6e3c5e54221cad8c985..2cf73b88e8e83ca34b9eb319dbc2b0a220139b0f 100755 (executable)
@@ -166,14 +166,14 @@ apply_autostash () {
                stash_sha1=$(cat "$state_dir/autostash")
                if git stash apply $stash_sha1 2>&1 >/dev/null
                then
-                       echo "$(gettext 'Applied autostash.')"
+                       echo "$(gettext 'Applied autostash.')" >&2
                else
                        git stash store -m "autostash" -q $stash_sha1 ||
                        die "$(eval_gettext "Cannot store \$stash_sha1")"
                        gettext 'Applying autostash resulted in conflicts.
 Your changes are safe in the stash.
 You can run "git stash pop" or "git stash drop" at any time.
-'
+' >&2
                fi
        fi
 }
index 7fd58744360a2bb14531ed3f73092b45449d5590..fa6526986ed40143a12ffcd6563fd52b49d209e7 100755 (executable)
@@ -82,6 +82,10 @@ sub usage {
                                      This setting forces to use one of the listed mechanisms.
     --smtp-debug            <0|1>  * Disable, enable Net::SMTP debug.
 
+    --batch-size            <int>  * send max <int> message per connection.
+    --relogin-delay         <int>  * delay <int> seconds between two successive login.
+                                     This option can only be used with --batch-size
+
   Automating:
     --identity              <str>  * Use the sendemail.<id> options.
     --to-cmd                <str>  * Email To: via `<str> \$patch_path`
@@ -154,6 +158,7 @@ sub format_2822_time {
 my $have_mail_address = eval { require Mail::Address; 1 };
 my $smtp;
 my $auth;
+my $num_sent = 0;
 
 # Regexes for RFC 2047 productions.
 my $re_token = qr/[^][()<>@,;:\\"\/?.= \000-\037\177-\377]+/;
@@ -217,6 +222,7 @@ sub do_edit {
 my ($to_cmd, $cc_cmd);
 my ($smtp_server, $smtp_server_port, @smtp_server_options);
 my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path);
+my ($batch_size, $relogin_delay);
 my ($identity, $aliasfiletype, @alias_files, $smtp_domain, $smtp_auth);
 my ($validate, $confirm);
 my (@suppress_cc);
@@ -248,6 +254,8 @@ sub do_edit {
     "smtppass" => \$smtp_authpass,
     "smtpdomain" => \$smtp_domain,
     "smtpauth" => \$smtp_auth,
+    "smtpbatchsize" => \$batch_size,
+    "smtprelogindelay" => \$relogin_delay,
     "to" => \@initial_to,
     "tocmd" => \$to_cmd,
     "cc" => \@initial_cc,
@@ -359,6 +367,8 @@ sub signal_handler {
                    "force" => \$force,
                    "xmailer!" => \$use_xmailer,
                    "no-xmailer" => sub {$use_xmailer = 0},
+                   "batch-size=i" => \$batch_size,
+                   "relogin-delay=i" => \$relogin_delay,
         );
 
 usage() if $help;
@@ -1681,6 +1691,14 @@ sub send_message {
                }
        }
        $message_id = undef;
+       $num_sent++;
+       if (defined $batch_size && $num_sent == $batch_size) {
+               $num_sent = 0;
+               $smtp->quit if defined $smtp;
+               undef $smtp;
+               undef $auth;
+               sleep($relogin_delay) if defined $relogin_delay;
+       }
 }
 
 # Execute a command (e.g. $to_cmd) to get a list of email addresses
index e7b85932d6ba62ec9f581c692a321ac24e52dcac..9b6c2da7b4b75980403d836f6fa1fc516bdc3639 100755 (executable)
@@ -484,7 +484,7 @@ parse_flags_and_rev()
 
        case $# in
                0)
-                       have_stash || die "$(gettext "No stash found.")"
+                       have_stash || die "$(gettext "No stash entries found.")"
                        set -- ${ref_stash}@{0}
                ;;
                1)
@@ -576,7 +576,7 @@ apply_stash () {
                GIT_INDEX_FILE="$TMPindex" git-read-tree "$u_tree" &&
                GIT_INDEX_FILE="$TMPindex" git checkout-index --all &&
                rm -f "$TMPindex" ||
-               die "$(gettext "Could not restore untracked files from stash")"
+               die "$(gettext "Could not restore untracked files from stash entry")"
        fi
 
        eval "
@@ -630,7 +630,7 @@ pop_stash() {
                drop_stash "$@"
        else
                status=$?
-               say "$(gettext "The stash is kept in case you need it again.")"
+               say "$(gettext "The stash entry is kept in case you need it again.")"
                exit $status
        fi
 }
index c0d0e9a4c63495d4522666b6edf984c01c0cfa23..e131760eecf944aee97e18a68ab1f171fc0e1d1b 100755 (executable)
@@ -213,7 +213,8 @@ cmd_add()
                die "$(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
        fi
 
-       if test -z "$force" && ! git add --dry-run --ignore-missing "$sm_path" > /dev/null 2>&1
+       if test -z "$force" &&
+               ! git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" > /dev/null 2>&1
        then
                eval_gettextln "The following path is ignored by one of your .gitignore files:
 \$sm_path
@@ -267,7 +268,7 @@ or you are unsure what this means choose another name with the '--name' option."
        fi
        git config submodule."$sm_name".url "$realrepo"
 
-       git add $force "$sm_path" ||
+       git add --no-warn-embedded-repo $force "$sm_path" ||
        die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
 
        git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
diff --git a/git.c b/git.c
index 1b8b7f51a65fa2a8e62d11d7ad99f19e2926977f..489aab4d83a1e222c3e5f3b3bd812b4f29ecd34f 100644 (file)
--- a/git.c
+++ b/git.c
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "exec_cmd.h"
 #include "help.h"
 #include "run-command.h"
@@ -16,53 +17,9 @@ const char git_more_info_string[] =
           "to read about a specific subcommand or concept.");
 
 static int use_pager = -1;
-static char *orig_cwd;
-static const char *env_names[] = {
-       GIT_DIR_ENVIRONMENT,
-       GIT_WORK_TREE_ENVIRONMENT,
-       GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,
-       GIT_PREFIX_ENVIRONMENT
-};
-static char *orig_env[4];
-static int save_restore_env_balance;
 
 static void list_builtins(void);
 
-static void save_env_before_alias(void)
-{
-       int i;
-
-       assert(save_restore_env_balance == 0);
-       save_restore_env_balance = 1;
-       orig_cwd = xgetcwd();
-       for (i = 0; i < ARRAY_SIZE(env_names); i++) {
-               orig_env[i] = getenv(env_names[i]);
-               orig_env[i] = xstrdup_or_null(orig_env[i]);
-       }
-}
-
-static void restore_env(int external_alias)
-{
-       int i;
-
-       assert(save_restore_env_balance == 1);
-       save_restore_env_balance = 0;
-       if (!external_alias && orig_cwd && chdir(orig_cwd))
-               die_errno("could not move to %s", orig_cwd);
-       free(orig_cwd);
-       for (i = 0; i < ARRAY_SIZE(env_names); i++) {
-               if (external_alias &&
-                   !strcmp(env_names[i], GIT_PREFIX_ENVIRONMENT))
-                       continue;
-               if (orig_env[i]) {
-                       setenv(env_names[i], orig_env[i], 1);
-                       free(orig_env[i]);
-               } else {
-                       unsetenv(env_names[i]);
-               }
-       }
-}
-
 static void commit_pager_choice(void) {
        switch (use_pager) {
        case 0:
@@ -255,19 +212,18 @@ static int handle_alias(int *argcp, const char ***argv)
        const char **new_argv;
        const char *alias_command;
        char *alias_string;
-       int unused_nongit;
-
-       save_env_before_alias();
-       setup_git_directory_gently(&unused_nongit);
 
        alias_command = (*argv)[0];
        alias_string = alias_lookup(alias_command);
        if (alias_string) {
                if (alias_string[0] == '!') {
                        struct child_process child = CHILD_PROCESS_INIT;
+                       int nongit_ok;
+
+                       /* Aliases expect GIT_PREFIX, GIT_DIR etc to be set */
+                       setup_git_directory_gently(&nongit_ok);
 
                        commit_pager_choice();
-                       restore_env(1);
 
                        child.use_shell = 1;
                        argv_array_push(&child.args, alias_string + 1);
@@ -313,8 +269,6 @@ static int handle_alias(int *argcp, const char ***argv)
                ret = 1;
        }
 
-       restore_env(0);
-
        errno = saved_errno;
 
        return ret;
@@ -446,7 +400,7 @@ static struct cmd_struct commands[] = {
        { "init-db", cmd_init_db },
        { "interpret-trailers", cmd_interpret_trailers, RUN_SETUP_GENTLY },
        { "log", cmd_log, RUN_SETUP },
-       { "ls-files", cmd_ls_files, RUN_SETUP | SUPPORT_SUPER_PREFIX },
+       { "ls-files", cmd_ls_files, RUN_SETUP },
        { "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
        { "ls-tree", cmd_ls_tree, RUN_SETUP },
        { "mailinfo", cmd_mailinfo, RUN_SETUP_GENTLY },
index d8209c7a02d8753af4724f385a4ea783384536f6..3d4a8ee27c96a8e1eb94f95771aeca7825f8a076 100755 (executable)
@@ -3125,7 +3125,7 @@ sub git_get_projects_list {
        return @list;
 }
 
-# written with help of Tree::Trie module (Perl Artistic License, GPL compatibile)
+# written with help of Tree::Trie module (Perl Artistic License, GPL compatible)
 # as side effects it sets 'forks' field to list of forks for forked projects
 sub filter_forks_from_projects_list {
        my $projects = shift;
@@ -4376,7 +4376,7 @@ sub git_print_page_nav {
              "</div>\n";
 }
 
-# returns a submenu for the nagivation of the refs views (tags, heads,
+# returns a submenu for the navigation of the refs views (tags, heads,
 # remotes) with the current view disabled and the remotes view only
 # available if the feature is enabled
 sub format_ref_views {
index e44cc27da15f03629989ee0083664d0af09c55b3..d936f3a32fe5d38c2b41ae0488ac2c02250a1618 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "run-command.h"
 #include "strbuf.h"
 #include "gpg-interface.h"
@@ -13,16 +14,11 @@ static const char *gpg_program = "gpg";
 
 void signature_check_clear(struct signature_check *sigc)
 {
-       free(sigc->payload);
-       free(sigc->gpg_output);
-       free(sigc->gpg_status);
-       free(sigc->signer);
-       free(sigc->key);
-       sigc->payload = NULL;
-       sigc->gpg_output = NULL;
-       sigc->gpg_status = NULL;
-       sigc->signer = NULL;
-       sigc->key = NULL;
+       FREE_AND_NULL(sigc->payload);
+       FREE_AND_NULL(sigc->gpg_output);
+       FREE_AND_NULL(sigc->gpg_status);
+       FREE_AND_NULL(sigc->signer);
+       FREE_AND_NULL(sigc->key);
 }
 
 static struct {
diff --git a/graph.c b/graph.c
index 8b9049dd2c725f58314042deebfb69030e4321d3..e7e20650da6983ada7c94c22aea7ecaec41c5c17 100644 (file)
--- a/graph.c
+++ b/graph.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "color.h"
 #include "graph.h"
diff --git a/grep.c b/grep.c
index d7ef21358ea7f592dffff98884eb34169e097880..98733db623ae2a0c4b3c11b71e3560429ec975ff 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "grep.h"
 #include "userdiff.h"
 #include "xdiff-interface.h"
@@ -508,7 +509,7 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
                if (!p->pcre2_jit_stack)
                        die("Couldn't allocate PCRE2 JIT stack");
                p->pcre2_match_context = pcre2_match_context_create(NULL);
-               if (!p->pcre2_jit_stack)
+               if (!p->pcre2_match_context)
                        die("Couldn't allocate PCRE2 match context");
                pcre2_jit_stack_assign(p->pcre2_match_context, NULL, p->pcre2_jit_stack);
        } else if (p->pcre2_jit_on != 0) {
@@ -1939,12 +1940,9 @@ void grep_source_init(struct grep_source *gs, enum grep_source_type type,
 
 void grep_source_clear(struct grep_source *gs)
 {
-       free(gs->name);
-       gs->name = NULL;
-       free(gs->path);
-       gs->path = NULL;
-       free(gs->identifier);
-       gs->identifier = NULL;
+       FREE_AND_NULL(gs->name);
+       FREE_AND_NULL(gs->path);
+       FREE_AND_NULL(gs->identifier);
        grep_source_clear_data(gs);
 }
 
@@ -1954,8 +1952,7 @@ void grep_source_clear_data(struct grep_source *gs)
        case GREP_SOURCE_FILE:
        case GREP_SOURCE_OID:
        case GREP_SOURCE_SUBMODULE:
-               free(gs->buf);
-               gs->buf = NULL;
+               FREE_AND_NULL(gs->buf);
                gs->size = 0;
                break;
        case GREP_SOURCE_BUF:
diff --git a/hash.h b/hash.h
index a11fc9233fc9bb7d876e2e97a1a149260d7a633c..bef3e630a093b508e78419c5f4e228e836ecb88c 100644 (file)
--- a/hash.h
+++ b/hash.h
@@ -8,7 +8,11 @@
 #elif defined(SHA1_OPENSSL)
 #include <openssl/sha.h>
 #elif defined(SHA1_DC)
+#ifdef DC_SHA1_SUBMODULE
+#include "sha1collisiondetection/lib/sha1.h"
+#else
 #include "sha1dc/sha1.h"
+#endif
 #else /* SHA1_BLK */
 #include "block-sha1/sha1.h"
 #endif
diff --git a/help.c b/help.c
index f637fc80062094784d5734df91523642933ddcfc..88a3aeaeb9f0b3983c9cd035fd371133506a54ec 100644 (file)
--- a/help.c
+++ b/help.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "exec_cmd.h"
 #include "run-command.h"
@@ -268,9 +269,8 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
 
        for (i = 0; i < old->cnt; i++)
                cmds->names[cmds->cnt++] = old->names[i];
-       free(old->names);
+       FREE_AND_NULL(old->names);
        old->cnt = 0;
-       old->names = NULL;
 }
 
 /* An empirically derived magic number */
@@ -290,7 +290,7 @@ const char *help_unknown_cmd(const char *cmd)
        memset(&other_cmds, 0, sizeof(other_cmds));
        memset(&aliases, 0, sizeof(aliases));
 
-       git_config(git_unknown_cmd_config, NULL);
+       read_early_config(git_unknown_cmd_config, NULL);
 
        load_command_list("git-", &main_cmds, &other_cmds);
 
@@ -356,12 +356,18 @@ const char *help_unknown_cmd(const char *cmd)
                clean_cmdnames(&main_cmds);
                fprintf_ln(stderr,
                           _("WARNING: You called a Git command named '%s', "
-                            "which does not exist.\n"
-                            "Continuing under the assumption that you meant '%s'"),
-                       cmd, assumed);
-               if (autocorrect > 0) {
-                       fprintf_ln(stderr, _("in %0.1f seconds automatically..."),
-                               (float)autocorrect/10.0);
+                            "which does not exist."),
+                          cmd);
+               if (autocorrect < 0)
+                       fprintf_ln(stderr,
+                                  _("Continuing under the assumption that "
+                                    "you meant '%s'."),
+                                  assumed);
+               else {
+                       fprintf_ln(stderr,
+                                  _("Continuing in %0.1f seconds, "
+                                    "assuming that you meant '%s'."),
+                                  (float)autocorrect/10.0, assumed);
                        sleep_millisec(autocorrect * 100);
                }
                return assumed;
index ba5ff1aa2994633c055611ce566ea8cf3c09e8cc..519025d2c3d944afb6fdd6ca1f3b091827a67272 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "pkt-line.h"
 #include "object.h"
index 3b556d66196277b2730f7e3d366a28a9d5ad1c56..8af380050ce6a43a6764ad871f0de141c316421a 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "exec_cmd.h"
 #include "http.h"
 #include "walker.h"
index 67c4d4b472cb1065bcfa20007fdbca55ac8e0052..c91f40a610541d6201edf2a2c95b8fef203f3c2f 100644 (file)
@@ -291,8 +291,7 @@ static void start_mkcol(struct transfer_request *request)
                request->state = RUN_MKCOL;
        } else {
                request->state = ABORTED;
-               free(request->url);
-               request->url = NULL;
+               FREE_AND_NULL(request->url);
        }
 }
 #endif
@@ -409,8 +408,7 @@ static void start_put(struct transfer_request *request)
                request->state = RUN_PUT;
        } else {
                request->state = ABORTED;
-               free(request->url);
-               request->url = NULL;
+               FREE_AND_NULL(request->url);
        }
 }
 
@@ -432,8 +430,7 @@ static void start_move(struct transfer_request *request)
                request->state = RUN_MOVE;
        } else {
                request->state = ABORTED;
-               free(request->url);
-               request->url = NULL;
+               FREE_AND_NULL(request->url);
        }
 }
 
@@ -526,8 +523,7 @@ static void finish_request(struct transfer_request *request)
 
        /* URL is reused for MOVE after PUT */
        if (request->state != RUN_PUT) {
-               free(request->url);
-               request->url = NULL;
+               FREE_AND_NULL(request->url);
        }
 
        if (request->state == RUN_MKCOL) {
@@ -803,8 +799,7 @@ xml_start_tag(void *userData, const char *name, const char **atts)
        }
        xsnprintf(ctx->name + old_namelen, ctx->len - old_namelen, ".%s", c);
 
-       free(ctx->cdata);
-       ctx->cdata = NULL;
+       FREE_AND_NULL(ctx->cdata);
 
        ctx->userFunc(ctx, 0);
 }
@@ -932,8 +927,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
                free(lock->token);
                free(lock->owner);
                free(url);
-               free(lock);
-               lock = NULL;
+               FREE_AND_NULL(lock);
        } else {
                lock->url = url;
                lock->start_time = time(NULL);
@@ -1105,8 +1099,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
                        ls->dentry_flags |= IS_DIR;
                }
        } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
-               free(ls->dentry_name);
-               ls->dentry_name = NULL;
+               FREE_AND_NULL(ls->dentry_name);
                ls->dentry_flags = 0;
        }
 }
@@ -1547,8 +1540,7 @@ static void fetch_symref(const char *path, char **symref, struct object_id *oid)
                    curl_errorstr);
        free(url);
 
-       free(*symref);
-       *symref = NULL;
+       FREE_AND_NULL(*symref);
        oidclr(oid);
 
        if (buffer.len == 0)
diff --git a/http.c b/http.c
index d2e11ec6f012d3b2a9570f0c322aebf53a13cc0a..c6c010f8816f4a01c4b7658a9044b179515590ea 100644 (file)
--- a/http.c
+++ b/http.c
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "http.h"
+#include "config.h"
 #include "pack.h"
 #include "sideband.h"
 #include "run-command.h"
@@ -1026,8 +1027,7 @@ void http_cleanup(void)
 
        if (proxy_auth.password) {
                memset(proxy_auth.password, 0, strlen(proxy_auth.password));
-               free(proxy_auth.password);
-               proxy_auth.password = NULL;
+               FREE_AND_NULL(proxy_auth.password);
        }
 
        free((void *)curl_proxyuserpwd);
@@ -1038,13 +1038,11 @@ void http_cleanup(void)
 
        if (cert_auth.password != NULL) {
                memset(cert_auth.password, 0, strlen(cert_auth.password));
-               free(cert_auth.password);
-               cert_auth.password = NULL;
+               FREE_AND_NULL(cert_auth.password);
        }
        ssl_cert_password_required = 0;
 
-       free(cached_accept_language);
-       cached_accept_language = NULL;
+       FREE_AND_NULL(cached_accept_language);
 }
 
 struct active_request_slot *get_active_slot(void)
@@ -1896,8 +1894,7 @@ static char *fetch_pack_index(unsigned char *sha1, const char *base_url)
 
        if (http_get_file(url, tmp, NULL) != HTTP_OK) {
                error("Unable to get pack index %s", url);
-               free(tmp);
-               tmp = NULL;
+               FREE_AND_NULL(tmp);
        }
 
        free(url);
@@ -2328,8 +2325,7 @@ void release_http_object_request(struct http_object_request *freq)
                freq->localfile = -1;
        }
        if (freq->url != NULL) {
-               free(freq->url);
-               freq->url = NULL;
+               FREE_AND_NULL(freq->url);
        }
        if (freq->slot != NULL) {
                freq->slot->callback_func = NULL;
diff --git a/ident.c b/ident.c
index 91c7609055bf3e0a4c0b7ae3cb46219ccaad53ef..327abe557f5a66546665664511d3e71b7f0929e7 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -6,6 +6,7 @@
  * Copyright (C) 2005 Linus Torvalds
  */
 #include "cache.h"
+#include "config.h"
 
 static struct strbuf git_default_name = STRBUF_INIT;
 static struct strbuf git_default_email = STRBUF_INIT;
index 857591660f485d65dec3390b22dd2083c94d7a44..351e84aea172415c94d7159c47b58abf508e0576 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "credential.h"
 #include "exec_cmd.h"
 #include "run-command.h"
@@ -776,8 +777,7 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
                               offsetof(struct imap_cmd, next));
                        if (cmdp->cb.data) {
                                n = socket_write(&imap->buf.sock, cmdp->cb.data, cmdp->cb.dlen);
-                               free(cmdp->cb.data);
-                               cmdp->cb.data = NULL;
+                               FREE_AND_NULL(cmdp->cb.data);
                                if (n != (int)cmdp->cb.dlen)
                                        return RESP_BAD;
                        } else if (cmdp->cb.cont) {
index 2588ce076749ecbb6bfbe591666430edf4ff9073..ab0709f9aecaacdfaf44aa31c88873b4ab5d8278 100644 (file)
@@ -34,9 +34,8 @@ void range_set_init(struct range_set *rs, size_t prealloc)
 
 void range_set_release(struct range_set *rs)
 {
-       free(rs->ranges);
+       FREE_AND_NULL(rs->ranges);
        rs->alloc = rs->nr = 0;
-       rs->ranges = NULL;
 }
 
 /* dst must be uninitialized! */
@@ -610,8 +609,7 @@ parse_lines(struct commit *commit, const char *prefix, struct string_list *args)
                line_log_data_insert(&ranges, full_name, begin, end);
 
                free_filespec(spec);
-               free(ends);
-               ends = NULL;
+               FREE_AND_NULL(ends);
        }
 
        for (p = ranges; p; p = p->next)
index ac0d4a5d78d956f09aa0082b286babc36f04b593..9fb855a90030e07e28c1ae9d0994006da22cd4ed 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "attr.h"
 #include "xdiff-interface.h"
 #include "run-command.h"
@@ -209,8 +210,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
        result->size = st.st_size;
        result->ptr = xmallocz(result->size);
        if (read_in_full(fd, result->ptr, result->size) != result->size) {
-               free(result->ptr);
-               result->ptr = NULL;
+               FREE_AND_NULL(result->ptr);
                result->size = 0;
        }
  close_bad:
@@ -339,7 +339,7 @@ static const struct ll_merge_driver *find_ll_merge_driver(const char *merge_attr
 static void normalize_file(mmfile_t *mm, const char *path)
 {
        struct strbuf strbuf = STRBUF_INIT;
-       if (renormalize_buffer(path, mm->ptr, mm->size, &strbuf)) {
+       if (renormalize_buffer(&the_index, path, mm->ptr, mm->size, &strbuf)) {
                free(mm->ptr);
                mm->size = strbuf.len;
                mm->ptr = strbuf_detach(&strbuf, NULL);
index 2903874ecf156c374ae0a120cdc20a5f5e41df53..410ab4f02de5b532485c46b5cceffc3c677df214 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "diff.h"
 #include "commit.h"
 #include "tag.h"
index f92cb9f729ca05ae1e80c9c27bc102dbb64a8dc0..bd574cb75210334b1a4628f182743b49bd389cd7 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "utf8.h"
 #include "strbuf.h"
 #include "mailinfo.h"
@@ -57,17 +58,17 @@ static void parse_bogus_from(struct mailinfo *mi, const struct strbuf *line)
 static const char *unquote_comment(struct strbuf *outbuf, const char *in)
 {
        int c;
-       int take_next_litterally = 0;
+       int take_next_literally = 0;
 
        strbuf_addch(outbuf, '(');
 
        while ((c = *in++) != 0) {
-               if (take_next_litterally == 1) {
-                       take_next_litterally = 0;
+               if (take_next_literally == 1) {
+                       take_next_literally = 0;
                } else {
                        switch (c) {
                        case '\\':
-                               take_next_litterally = 1;
+                               take_next_literally = 1;
                                continue;
                        case '(':
                                in = unquote_comment(outbuf, in);
@@ -87,15 +88,15 @@ static const char *unquote_comment(struct strbuf *outbuf, const char *in)
 static const char *unquote_quoted_string(struct strbuf *outbuf, const char *in)
 {
        int c;
-       int take_next_litterally = 0;
+       int take_next_literally = 0;
 
        while ((c = *in++) != 0) {
-               if (take_next_litterally == 1) {
-                       take_next_litterally = 0;
+               if (take_next_literally == 1) {
+                       take_next_literally = 0;
                } else {
                        switch (c) {
                        case '\\':
-                               take_next_litterally = 1;
+                               take_next_literally = 1;
                                continue;
                        case '"':
                                return in;
@@ -919,8 +920,7 @@ static int handle_boundary(struct mailinfo *mi, struct strbuf *line)
                /* we hit an end boundary */
                /* pop the current boundary off the stack */
                strbuf_release(*(mi->content_top));
-               free(*(mi->content_top));
-               *(mi->content_top) = NULL;
+               FREE_AND_NULL(*(mi->content_top));
 
                /* technically won't happen as is_multipart_boundary()
                   will fail first.  But just in case..
index 5cc86df2d15729e9b0e8b36fdb151d5986f42a10..1494ffdb828106882053065e3ac8cc383136cf80 100644 (file)
@@ -4,6 +4,7 @@
  * The thieves were Alex Riesen and Johannes Schindelin, in June/July 2006
  */
 #include "cache.h"
+#include "config.h"
 #include "advice.h"
 #include "lockfile.h"
 #include "cache-tree.h"
@@ -1639,8 +1640,8 @@ static int blob_unchanged(struct merge_options *opt,
         * performed.  Comparison can be skipped if both files are
         * unchanged since their sha1s have already been compared.
         */
-       if (renormalize_buffer(path, o.buf, o.len, &o) |
-           renormalize_buffer(path, a.buf, a.len, &a))
+       if (renormalize_buffer(&the_index, path, o.buf, o.len, &o) |
+           renormalize_buffer(&the_index, path, a.buf, a.len, &a))
                ret = (o.len == a.len && !memcmp(o.buf, a.buf, o.len));
 
 error_return:
@@ -2209,11 +2210,11 @@ int parse_merge_opt(struct merge_options *o, const char *s)
                o->xdl_opts |= value;
        }
        else if (!strcmp(s, "ignore-space-change"))
-               o->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
+               DIFF_XDL_SET(o, IGNORE_WHITESPACE_CHANGE);
        else if (!strcmp(s, "ignore-all-space"))
-               o->xdl_opts |= XDF_IGNORE_WHITESPACE;
+               DIFF_XDL_SET(o, IGNORE_WHITESPACE);
        else if (!strcmp(s, "ignore-space-at-eol"))
-               o->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
+               DIFF_XDL_SET(o, IGNORE_WHITESPACE_AT_EOL);
        else if (!strcmp(s, "renormalize"))
                o->renormalize = 1;
        else if (!strcmp(s, "no-renormalize"))
index bc178e88827a1a0558e9fbee1a6f18f6ede83df1..7a08470f8836e14824a215b29e0c3a5dbeba9c17 100644 (file)
@@ -10,7 +10,7 @@ merge_cmd () {
 
        if test "$meld_has_output_option" = true
        then
-               "$merge_tool_path" --output "$MERGED" \
+               "$merge_tool_path" --output="$MERGED" \
                        "$LOCAL" "$BASE" "$REMOTE"
        else
                "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
index 9ebf8419565019cca42d778be96e2f3b7d6f29df..9765deb41ab02dba909ec9027701bf2fdc53f310 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "refs.h"
 #include "notes-utils.h"
diff --git a/notes.c b/notes.c
index 4b3a1adda566bdc82ba7005083f37dff5bd62ed4..8f47c202c58752b6d9d56852ae9c315e2f144769 100644 (file)
--- a/notes.c
+++ b/notes.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "notes.h"
 #include "blob.h"
 #include "tree.h"
index 06ba3a11d87ad7b93f29aef535e773fcc4683004..f818777412187890b88a6c90507b8b41f131487c 100644 (file)
--- a/object.c
+++ b/object.c
@@ -377,8 +377,7 @@ void object_array_clear(struct object_array *array)
        int i;
        for (i = 0; i < array->nr; i++)
                object_array_release_entry(&array->objects[i]);
-       free(array->objects);
-       array->objects = NULL;
+       FREE_AND_NULL(array->objects);
        array->nr = array->alloc = 0;
 }
 
index a3ac3dccd4f8423fcd39ba0ee77a200500d75a81..327634cd71b5c8fdd5ab531493c2de020bee869d 100644 (file)
@@ -627,7 +627,7 @@ static void show_objects_for_type(
                        sha1 = nth_packed_object_sha1(bitmap_git.pack, entry->nr);
 
                        if (bitmap_git.hashes)
-                               hash = ntohl(bitmap_git.hashes[entry->nr]);
+                               hash = get_be32(bitmap_git.hashes + entry->nr);
 
                        show_reach(sha1, object_type, 0, hash, bitmap_git.pack, entry->offset);
                }
diff --git a/pager.c b/pager.c
index c113d898a4ab184cf5ad5ea04dc66365fdf8a8f8..4dd9e1b26592bd3e7a7ddb52182ea79971557db0 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "run-command.h"
 #include "sigchain.h"
 
index e5ad34a2c3f7c7d7fdb65171f8a142a2becc64bb..0dd9fc6a0dd0a518200d9bbd834decb3c3ee22c6 100644 (file)
@@ -1,6 +1,7 @@
 #include "git-compat-util.h"
 #include "parse-options.h"
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "color.h"
 #include "utf8.h"
diff --git a/path.c b/path.c
index c1cb1cf6273f4a5a7ed91d495c55a7d283497460..e485f9f93181778de3acfe3cd4b6811ec82c7940 100644 (file)
--- a/path.c
+++ b/path.c
@@ -2,11 +2,13 @@
  * Utilities for paths and pathnames
  */
 #include "cache.h"
+#include "repository.h"
 #include "strbuf.h"
 #include "string-list.h"
 #include "dir.h"
 #include "worktree.h"
 #include "submodule-config.h"
+#include "path.h"
 
 static int get_st_mode_bits(const char *path, int *mode)
 {
@@ -343,8 +345,6 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len,
 {
        char *base = buf->buf + git_dir_len;
        init_common_trie();
-       if (!common_dir)
-               common_dir = get_git_common_dir();
        if (trie_find(&common_trie, base, check_common, NULL) > 0)
                replace_dir(buf, git_dir_len, common_dir);
 }
@@ -355,7 +355,7 @@ void report_linked_checkout_garbage(void)
        const struct common_dir *p;
        int len;
 
-       if (!git_common_dir_env)
+       if (!the_repository->different_commondir)
                return;
        strbuf_addf(&sb, "%s/", get_git_dir());
        len = sb.len;
@@ -371,42 +371,78 @@ void report_linked_checkout_garbage(void)
        strbuf_release(&sb);
 }
 
-static void adjust_git_path(struct strbuf *buf, int git_dir_len)
+static void adjust_git_path(const struct repository *repo,
+                           struct strbuf *buf, int git_dir_len)
 {
        const char *base = buf->buf + git_dir_len;
-       if (git_graft_env && is_dir_file(base, "info", "grafts"))
+       if (is_dir_file(base, "info", "grafts"))
                strbuf_splice(buf, 0, buf->len,
-                             get_graft_file(), strlen(get_graft_file()));
-       else if (git_index_env && !strcmp(base, "index"))
+                             repo->graft_file, strlen(repo->graft_file));
+       else if (!strcmp(base, "index"))
                strbuf_splice(buf, 0, buf->len,
-                             get_index_file(), strlen(get_index_file()));
-       else if (git_db_env && dir_prefix(base, "objects"))
-               replace_dir(buf, git_dir_len + 7, get_object_directory());
+                             repo->index_file, strlen(repo->index_file));
+       else if (dir_prefix(base, "objects"))
+               replace_dir(buf, git_dir_len + 7, repo->objectdir);
        else if (git_hooks_path && dir_prefix(base, "hooks"))
                replace_dir(buf, git_dir_len + 5, git_hooks_path);
-       else if (git_common_dir_env)
-               update_common_dir(buf, git_dir_len, NULL);
+       else if (repo->different_commondir)
+               update_common_dir(buf, git_dir_len, repo->commondir);
 }
 
-static void do_git_path(const struct worktree *wt, struct strbuf *buf,
+static void strbuf_worktree_gitdir(struct strbuf *buf,
+                                  const struct repository *repo,
+                                  const struct worktree *wt)
+{
+       if (!wt)
+               strbuf_addstr(buf, repo->gitdir);
+       else if (!wt->id)
+               strbuf_addstr(buf, repo->commondir);
+       else
+               strbuf_git_common_path(buf, repo, "worktrees/%s", wt->id);
+}
+
+static void do_git_path(const struct repository *repo,
+                       const struct worktree *wt, struct strbuf *buf,
                        const char *fmt, va_list args)
 {
        int gitdir_len;
-       strbuf_addstr(buf, get_worktree_git_dir(wt));
+       strbuf_worktree_gitdir(buf, repo, wt);
        if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
                strbuf_addch(buf, '/');
        gitdir_len = buf->len;
        strbuf_vaddf(buf, fmt, args);
-       adjust_git_path(buf, gitdir_len);
+       if (!wt)
+               adjust_git_path(repo, buf, gitdir_len);
        strbuf_cleanup_path(buf);
 }
 
+char *repo_git_path(const struct repository *repo,
+                   const char *fmt, ...)
+{
+       struct strbuf path = STRBUF_INIT;
+       va_list args;
+       va_start(args, fmt);
+       do_git_path(repo, NULL, &path, fmt, args);
+       va_end(args);
+       return strbuf_detach(&path, NULL);
+}
+
+void strbuf_repo_git_path(struct strbuf *sb,
+                         const struct repository *repo,
+                         const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+       do_git_path(repo, NULL, sb, fmt, args);
+       va_end(args);
+}
+
 char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
 {
        va_list args;
        strbuf_reset(buf);
        va_start(args, fmt);
-       do_git_path(NULL, buf, fmt, args);
+       do_git_path(the_repository, NULL, buf, fmt, args);
        va_end(args);
        return buf->buf;
 }
@@ -415,7 +451,7 @@ void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
 {
        va_list args;
        va_start(args, fmt);
-       do_git_path(NULL, sb, fmt, args);
+       do_git_path(the_repository, NULL, sb, fmt, args);
        va_end(args);
 }
 
@@ -424,7 +460,7 @@ const char *git_path(const char *fmt, ...)
        struct strbuf *pathname = get_pathname();
        va_list args;
        va_start(args, fmt);
-       do_git_path(NULL, pathname, fmt, args);
+       do_git_path(the_repository, NULL, pathname, fmt, args);
        va_end(args);
        return pathname->buf;
 }
@@ -434,7 +470,7 @@ char *git_pathdup(const char *fmt, ...)
        struct strbuf path = STRBUF_INIT;
        va_list args;
        va_start(args, fmt);
-       do_git_path(NULL, &path, fmt, args);
+       do_git_path(the_repository, NULL, &path, fmt, args);
        va_end(args);
        return strbuf_detach(&path, NULL);
 }
@@ -465,11 +501,52 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)
        struct strbuf *pathname = get_pathname();
        va_list args;
        va_start(args, fmt);
-       do_git_path(wt, pathname, fmt, args);
+       do_git_path(the_repository, wt, pathname, fmt, args);
        va_end(args);
        return pathname->buf;
 }
 
+static void do_worktree_path(const struct repository *repo,
+                            struct strbuf *buf,
+                            const char *fmt, va_list args)
+{
+       strbuf_addstr(buf, repo->worktree);
+       if(buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
+               strbuf_addch(buf, '/');
+
+       strbuf_vaddf(buf, fmt, args);
+       strbuf_cleanup_path(buf);
+}
+
+char *repo_worktree_path(const struct repository *repo, const char *fmt, ...)
+{
+       struct strbuf path = STRBUF_INIT;
+       va_list args;
+
+       if (!repo->worktree)
+               return NULL;
+
+       va_start(args, fmt);
+       do_worktree_path(repo, &path, fmt, args);
+       va_end(args);
+
+       return strbuf_detach(&path, NULL);
+}
+
+void strbuf_repo_worktree_path(struct strbuf *sb,
+                              const struct repository *repo,
+                              const char *fmt, ...)
+{
+       va_list args;
+
+       if (!repo->worktree)
+               return;
+
+       va_start(args, fmt);
+       do_worktree_path(repo, sb, fmt, args);
+       va_end(args);
+}
+
 /* Returns 0 on success, negative on failure. */
 static int do_submodule_path(struct strbuf *buf, const char *path,
                             const char *fmt, va_list args)
@@ -524,11 +601,12 @@ int strbuf_git_path_submodule(struct strbuf *buf, const char *path,
        return err;
 }
 
-static void do_git_common_path(struct strbuf *buf,
+static void do_git_common_path(const struct repository *repo,
+                              struct strbuf *buf,
                               const char *fmt,
                               va_list args)
 {
-       strbuf_addstr(buf, get_git_common_dir());
+       strbuf_addstr(buf, repo->commondir);
        if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
                strbuf_addch(buf, '/');
        strbuf_vaddf(buf, fmt, args);
@@ -540,16 +618,18 @@ const char *git_common_path(const char *fmt, ...)
        struct strbuf *pathname = get_pathname();
        va_list args;
        va_start(args, fmt);
-       do_git_common_path(pathname, fmt, args);
+       do_git_common_path(the_repository, pathname, fmt, args);
        va_end(args);
        return pathname->buf;
 }
 
-void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...)
+void strbuf_git_common_path(struct strbuf *sb,
+                           const struct repository *repo,
+                           const char *fmt, ...)
 {
        va_list args;
        va_start(args, fmt);
-       do_git_common_path(sb, fmt, args);
+       do_git_common_path(repo, sb, fmt, args);
        va_end(args);
 }
 
diff --git a/path.h b/path.h
new file mode 100644 (file)
index 0000000..9541620
--- /dev/null
+++ b/path.h
@@ -0,0 +1,82 @@
+#ifndef PATH_H
+#define PATH_H
+
+struct repository;
+
+/*
+ * Return a statically allocated filename, either generically (mkpath), in
+ * the repository directory (git_path), or in a submodule's repository
+ * directory (git_path_submodule). In all cases, note that the result
+ * may be overwritten by another call to _any_ of the functions. Consider
+ * using the safer "dup" or "strbuf" formats below (in some cases, the
+ * unsafe versions have already been removed).
+ */
+extern const char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+extern const char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+extern const char *git_common_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+
+extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
+       __attribute__((format (printf, 3, 4)));
+extern void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
+       __attribute__((format (printf, 2, 3)));
+extern void strbuf_git_common_path(struct strbuf *sb,
+                                  const struct repository *repo,
+                                  const char *fmt, ...)
+       __attribute__((format (printf, 3, 4)));
+extern char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
+       __attribute__((format (printf, 2, 3)));
+extern int strbuf_git_path_submodule(struct strbuf *sb, const char *path,
+                                    const char *fmt, ...)
+       __attribute__((format (printf, 3, 4)));
+extern char *git_pathdup(const char *fmt, ...)
+       __attribute__((format (printf, 1, 2)));
+extern char *mkpathdup(const char *fmt, ...)
+       __attribute__((format (printf, 1, 2)));
+extern char *git_pathdup_submodule(const char *path, const char *fmt, ...)
+       __attribute__((format (printf, 2, 3)));
+
+extern char *repo_git_path(const struct repository *repo,
+                          const char *fmt, ...)
+       __attribute__((format (printf, 2, 3)));
+extern void strbuf_repo_git_path(struct strbuf *sb,
+                                const struct repository *repo,
+                                const char *fmt, ...)
+       __attribute__((format (printf, 3, 4)));
+
+extern char *repo_worktree_path(const struct repository *repo,
+                               const char *fmt, ...)
+       __attribute__((format (printf, 2, 3)));
+extern void strbuf_repo_worktree_path(struct strbuf *sb,
+                                     const struct repository *repo,
+                                     const char *fmt, ...)
+       __attribute__((format (printf, 3, 4)));
+
+extern void report_linked_checkout_garbage(void);
+
+/*
+ * You can define a static memoized git path like:
+ *
+ *    static GIT_PATH_FUNC(git_path_foo, "FOO");
+ *
+ * or use one of the global ones below.
+ */
+#define GIT_PATH_FUNC(func, filename) \
+       const char *func(void) \
+       { \
+               static char *ret; \
+               if (!ret) \
+                       ret = git_pathdup(filename); \
+               return ret; \
+       }
+
+const char *git_path_cherry_pick_head(void);
+const char *git_path_revert_head(void);
+const char *git_path_squash_msg(void);
+const char *git_path_merge_msg(void);
+const char *git_path_merge_rr(void);
+const char *git_path_merge_mode(void);
+const char *git_path_merge_head(void);
+const char *git_path_fetch_head(void);
+const char *git_path_shallow(void);
+
+#endif /* PATH_H */
index 828405021fca4214585e1d46b65f604d14e61143..e2a23ebc9668b066d337391e96139af49907edfa 100644 (file)
@@ -1,5 +1,6 @@
 #define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
+#include "config.h"
 #include "dir.h"
 #include "pathspec.h"
 #include "attr.h"
@@ -605,7 +606,7 @@ void parse_pathspec(struct pathspec *pathspec,
 
        /*
         * If everything is an exclude pattern, add one positive pattern
-        * that matches everyting. We allocated an extra one for this.
+        * that matches everything. We allocated an extra one for this.
         */
        if (nr_exclude == n) {
                int plen = (!(flags & PATHSPEC_PREFER_CWD)) ? 0 : prefixlen;
@@ -662,7 +663,6 @@ void clear_pathspec(struct pathspec *pathspec)
                        attr_check_free(pathspec->items[i].attr_check);
        }
 
-       free(pathspec->items);
-       pathspec->items = NULL;
+       FREE_AND_NULL(pathspec->items);
        pathspec->nr = 0;
 }
index bfce1f795dfa5fea05f4f96637a1ae2333038735..f4b56e6d4d38cbc4365ecfc9073f5caf3a05377a 100644 (file)
@@ -61,7 +61,8 @@ =head1 SYNOPSIS
                 remote_refs prompt
                 get_tz_offset get_record
                 credential credential_read credential_write
-                temp_acquire temp_is_locked temp_release temp_reset temp_path);
+                temp_acquire temp_is_locked temp_release temp_reset temp_path
+                unquote_path);
 
 
 =head1 DESCRIPTION
@@ -1451,6 +1452,57 @@ sub prefix_lines {
        return $string;
 }
 
+=item unquote_path ( PATH )
+
+Unquote a quoted path containing c-escapes as returned by ls-files etc.
+when not using -z or when parsing the output of diff -u.
+
+=cut
+
+{
+       my %cquote_map = (
+               "a" => chr(7),
+               "b" => chr(8),
+               "t" => chr(9),
+               "n" => chr(10),
+               "v" => chr(11),
+               "f" => chr(12),
+               "r" => chr(13),
+               "\\" => "\\",
+               "\042" => "\042",
+       );
+
+       sub unquote_path {
+               local ($_) = @_;
+               my ($retval, $remainder);
+               if (!/^\042(.*)\042$/) {
+                       return $_;
+               }
+               ($_, $retval) = ($1, "");
+               while (/^([^\\]*)\\(.*)$/) {
+                       $remainder = $2;
+                       $retval .= $1;
+                       for ($remainder) {
+                               if (/^([0-3][0-7][0-7])(.*)$/) {
+                                       $retval .= chr(oct($1));
+                                       $_ = $2;
+                                       last;
+                               }
+                               if (/^([\\\042abtnvfr])(.*)$/) {
+                                       $retval .= $cquote_map{$1};
+                                       $_ = $2;
+                                       last;
+                               }
+                               # This is malformed
+                               throw Error::Simple("invalid quoted path $_[0]");
+                       }
+                       $_ = $remainder;
+               }
+               $retval .= $_;
+               return $retval;
+       }
+}
+
 =item get_comment_line_char ( )
 
 Gets the core.commentchar configuration value.
index c41425c8d07a4b9a223ef3fb71e24ff526cb9fc9..836a5c23826328f7175faa6f9008b0534a4d1861 100644 (file)
@@ -74,7 +74,7 @@ =head1 SYNOPSIS
 
        printf __("The following error occurred: %s\n"), $error;
 
-       printf __n("commited %d file\n", "commited %d files\n", $files), $files;
+       printf __n("committed %d file\n", "committed %d files\n", $files), $files;
 
 
 =head1 DESCRIPTION
index 09701bd2ffef3eb6d9104916e4119f757c06c244..e4b561c5822b7b19878065c77a04ffa0c9e43d61 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "utf8.h"
 #include "diff.h"
@@ -783,29 +784,9 @@ struct format_commit_context {
        size_t body_off;
 
        /* The following ones are relative to the result struct strbuf. */
-       struct chunk abbrev_commit_hash;
-       struct chunk abbrev_tree_hash;
-       struct chunk abbrev_parent_hashes;
        size_t wrap_start;
 };
 
-static int add_again(struct strbuf *sb, struct chunk *chunk)
-{
-       if (chunk->len) {
-               strbuf_adddup(sb, chunk->off, chunk->len);
-               return 1;
-       }
-
-       /*
-        * We haven't seen this chunk before.  Our caller is surely
-        * going to add it the hard way now.  Remember the most likely
-        * start of the to-be-added chunk: the current end of the
-        * struct strbuf.
-        */
-       chunk->off = sb->len;
-       return 0;
-}
-
 static void parse_commit_header(struct format_commit_context *context)
 {
        const char *msg = context->message;
@@ -1147,24 +1128,16 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                return 1;
        case 'h':               /* abbreviated commit hash */
                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
-               if (add_again(sb, &c->abbrev_commit_hash)) {
-                       strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
-                       return 1;
-               }
                strbuf_add_unique_abbrev(sb, commit->object.oid.hash,
                                         c->pretty_ctx->abbrev);
                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
-               c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
                return 1;
        case 'T':               /* tree hash */
                strbuf_addstr(sb, oid_to_hex(&commit->tree->object.oid));
                return 1;
        case 't':               /* abbreviated tree hash */
-               if (add_again(sb, &c->abbrev_tree_hash))
-                       return 1;
                strbuf_add_unique_abbrev(sb, commit->tree->object.oid.hash,
                                         c->pretty_ctx->abbrev);
-               c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off;
                return 1;
        case 'P':               /* parent hashes */
                for (p = commit->parents; p; p = p->next) {
@@ -1174,16 +1147,12 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                }
                return 1;
        case 'p':               /* abbreviated parent hashes */
-               if (add_again(sb, &c->abbrev_parent_hashes))
-                       return 1;
                for (p = commit->parents; p; p = p->next) {
                        if (p != commit->parents)
                                strbuf_addch(sb, ' ');
                        strbuf_add_unique_abbrev(sb, p->item->object.oid.hash,
                                                 c->pretty_ctx->abbrev);
                }
-               c->abbrev_parent_hashes.len = sb->len -
-                                             c->abbrev_parent_hashes.off;
                return 1;
        case 'm':               /* left/right/bottom */
                strbuf_addstr(sb, get_revision_mark(NULL, commit));
index fc3860fdcb9fc50d4d883e1a8638cca474cfb8d0..126d09672738533b6ecc6b94b7405dff888bbaf6 100644 (file)
@@ -27,10 +27,9 @@ void prio_queue_reverse(struct prio_queue *queue)
 
 void clear_prio_queue(struct prio_queue *queue)
 {
-       free(queue->array);
+       FREE_AND_NULL(queue->array);
        queue->nr = 0;
        queue->alloc = 0;
-       queue->array = NULL;
        queue->insertion_ctr = 0;
 }
 
index 75406390c6fdabf74e74d4c2a90e6ac92afc4ccc..6d5885d0096407d7d12f4511100ebee5cb5f752d 100644 (file)
--- a/prompt.c
+++ b/prompt.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "run-command.h"
 #include "strbuf.h"
 #include "prompt.h"
index bc156a133e9ff197e3d98c63d66f2d958f47f564..2121b6e7bba5f310825e0b1f2eccd524cc8658ce 100644 (file)
@@ -5,6 +5,7 @@
  */
 #define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
+#include "config.h"
 #include "tempfile.h"
 #include "lockfile.h"
 #include "cache-tree.h"
@@ -1877,9 +1878,15 @@ int discard_index(struct index_state *istate)
 {
        int i;
 
-       unshare_split_index(istate, 1);
-       for (i = 0; i < istate->cache_nr; i++)
+       for (i = 0; i < istate->cache_nr; i++) {
+               if (istate->cache[i]->index &&
+                   istate->split_index &&
+                   istate->split_index->base &&
+                   istate->cache[i]->index <= istate->split_index->base->cache_nr &&
+                   istate->cache[i] == istate->split_index->base->cache[istate->cache[i]->index - 1])
+                       continue;
                free(istate->cache[i]);
+       }
        resolve_undo_clear_index(istate);
        istate->cache_nr = 0;
        istate->cache_changed = 0;
@@ -1888,8 +1895,7 @@ int discard_index(struct index_state *istate)
        free_name_hash(istate);
        cache_tree_free(&(istate->cache_tree));
        istate->initialized = 0;
-       free(istate->cache);
-       istate->cache = NULL;
+       FREE_AND_NULL(istate->cache);
        istate->cache_alloc = 0;
        discard_split_index(istate);
        free_untracked_cache(istate->untracked);
@@ -2425,6 +2431,14 @@ static int write_shared_index(struct index_state *istate,
                delete_tempfile(&temporary_sharedindex);
                return ret;
        }
+       ret = adjust_shared_perm(get_tempfile_path(&temporary_sharedindex));
+       if (ret) {
+               int save_errno = errno;
+               error("cannot fix permission bits on %s", get_tempfile_path(&temporary_sharedindex));
+               delete_tempfile(&temporary_sharedindex);
+               errno = save_errno;
+               return ret;
+       }
        ret = rename_tempfile(&temporary_sharedindex,
                              git_path("sharedindex.%s", sha1_to_hex(si->base->sha1)));
        if (!ret) {
@@ -2603,8 +2617,7 @@ void *read_blob_data_from_index(const struct index_state *istate,
 
 void stat_validity_clear(struct stat_validity *sv)
 {
-       free(sv->sd);
-       sv->sd = NULL;
+       FREE_AND_NULL(sv->sd);
 }
 
 int stat_validity_check(struct stat_validity *sv, const char *path)
index 718def443a0862c5ba90ce45b24abc22fa0aaf5b..e0578d8b5ae1a467082ee94ff798d054db1450bf 100644 (file)
@@ -1891,8 +1891,7 @@ void ref_array_clear(struct ref_array *array)
 
        for (i = 0; i < array->nr; i++)
                free_array_item(array->items[i]);
-       free(array->items);
-       array->items = NULL;
+       FREE_AND_NULL(array->items);
        array->nr = array->alloc = 0;
 }
 
diff --git a/refs.c b/refs.c
index 32626a4cd144ff1e06896f246d0d88344000f841..7aae78cb551fd2743982d7f9fc60e6de45df9a11 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -3,6 +3,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "hashmap.h"
 #include "lockfile.h"
 #include "iterator.h"
@@ -1341,6 +1342,18 @@ int for_each_ref_in_submodule(const char *submodule, const char *prefix,
                                    prefix, fn, cb_data);
 }
 
+int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
+                                 each_ref_fn fn, void *cb_data,
+                                 unsigned int broken)
+{
+       unsigned int flag = 0;
+
+       if (broken)
+               flag = DO_FOR_EACH_INCLUDE_BROKEN;
+       return do_for_each_ref(get_submodule_ref_store(submodule),
+                              prefix, fn, 0, flag, cb_data);
+}
+
 int for_each_replace_ref(each_ref_fn fn, void *cb_data)
 {
        return do_for_each_ref(get_main_ref_store(),
diff --git a/refs.h b/refs.h
index 4be14c4b3cc65de453c4eae438c245b0c91355e5..6daa78eb50ddc195c6d5bfb568d0b05ab08f7923 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -303,7 +303,10 @@ int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data);
 int for_each_ref_submodule(const char *submodule,
                           each_ref_fn fn, void *cb_data);
 int for_each_ref_in_submodule(const char *submodule, const char *prefix,
-               each_ref_fn fn, void *cb_data);
+                             each_ref_fn fn, void *cb_data);
+int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
+                                 each_ref_fn fn, void *cb_data,
+                                 unsigned int broken);
 int for_each_tag_ref_submodule(const char *submodule,
                               each_ref_fn fn, void *cb_data);
 int for_each_branch_ref_submodule(const char *submodule,
@@ -571,7 +574,7 @@ int ref_transaction_verify(struct ref_transaction *transaction,
 #define TRANSACTION_GENERIC_ERROR -2
 
 /*
- * Perform the preparatory stages of commiting `transaction`. Acquire
+ * Perform the preparatory stages of committing `transaction`. Acquire
  * any needed locks, check preconditions, etc.; basically, do as much
  * as possible to ensure that the transaction will be able to go
  * through, stopping just short of making any irrevocable or
@@ -583,7 +586,7 @@ int ref_transaction_verify(struct ref_transaction *transaction,
  * On failure, abort the transaction, write an error message to `err`,
  * and return one of the `TRANSACTION_*` constants.
  *
- * Callers who don't need such fine-grained control over commiting
+ * Callers who don't need such fine-grained control over committing
  * reference transactions should just call `ref_transaction_commit()`.
  */
 int ref_transaction_prepare(struct ref_transaction *transaction,
index d8b3f73147c8af88597ad71259aef0a9f53dd104..0404f2c2333c0fadeb57d225deedc6f0d4afadad 100644 (file)
@@ -1,4 +1,5 @@
 #include "../cache.h"
+#include "../config.h"
 #include "../refs.h"
 #include "refs-internal.h"
 #include "ref-cache.h"
@@ -369,6 +370,18 @@ static void files_ref_path(struct files_ref_store *refs,
        }
 }
 
+/*
+ * Check that the packed refs cache (if any) still reflects the
+ * contents of the file. If not, clear the cache.
+ */
+static void validate_packed_ref_cache(struct files_ref_store *refs)
+{
+       if (refs->packed &&
+           !stat_validity_check(&refs->packed->validity,
+                                files_packed_refs_path(refs)))
+               clear_packed_ref_cache(refs);
+}
+
 /*
  * Get the packed_ref_cache for the specified files_ref_store,
  * creating and populating it if it hasn't been read before or if the
@@ -381,10 +394,8 @@ static struct packed_ref_cache *get_packed_ref_cache(struct files_ref_store *ref
 {
        const char *packed_refs_file = files_packed_refs_path(refs);
 
-       if (refs->packed &&
-           !is_lock_file_locked(&refs->packed_refs_lock) &&
-           !stat_validity_check(&refs->packed->validity, packed_refs_file))
-               clear_packed_ref_cache(refs);
+       if (!is_lock_file_locked(&refs->packed_refs_lock))
+               validate_packed_ref_cache(refs);
 
        if (!refs->packed)
                refs->packed = read_packed_refs(packed_refs_file);
@@ -1311,13 +1322,17 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)
                            &refs->packed_refs_lock, files_packed_refs_path(refs),
                            flags, timeout_value) < 0)
                return -1;
+
        /*
-        * Get the current packed-refs while holding the lock. It is
-        * important that we call `get_packed_ref_cache()` before
-        * setting `packed_ref_cache->lock`, because otherwise the
-        * former will see that the file is locked and assume that the
-        * cache can't be stale.
+        * Now that we hold the `packed-refs` lock, make sure that our
+        * cache matches the current version of the file. Normally
+        * `get_packed_ref_cache()` does that for us, but that
+        * function assumes that when the file is locked, any existing
+        * cache is still valid. We've just locked the file, but it
+        * might have changed the moment *before* we locked it.
         */
+       validate_packed_ref_cache(refs);
+
        packed_ref_cache = get_packed_ref_cache(refs);
        /* Increment the reference count to prevent it from being freed: */
        acquire_packed_ref_cache(packed_ref_cache);
@@ -2944,8 +2959,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
                                       head_oid.hash, &head_type);
 
        if (head_ref && !(head_type & REF_ISSYMREF)) {
-               free(head_ref);
-               head_ref = NULL;
+               FREE_AND_NULL(head_ref);
        }
 
        /*
index af2fcb2c1217bc89e095515f6dcfcfb1c0e2befa..76bb723c8674c3022b271c93b587d941c8e6d397 100644 (file)
@@ -82,9 +82,8 @@ static void clear_ref_dir(struct ref_dir *dir)
        int i;
        for (i = 0; i < dir->nr; i++)
                free_ref_entry(dir->entries[i]);
-       free(dir->entries);
+       FREE_AND_NULL(dir->entries);
        dir->sorted = dir->nr = dir->alloc = 0;
-       dir->entries = NULL;
 }
 
 struct ref_entry *create_dir_entry(struct ref_cache *cache,
index ece45993dac582ddc6ba19b2362ba1716e075eae..0053b09549ab419ab8f2da2c519d689f5e0d83b3 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "remote.h"
 #include "strbuf.h"
 #include "walker.h"
index e034ea00d49c81675d664085c0d67763609bfd8a..0ff4a312629d4ed4250a076f39a9d78e76917158 100644 (file)
@@ -66,8 +66,7 @@ static char *read_ref_note(const struct object_id *oid)
        else if (!msglen || type != OBJ_BLOB) {
                error("Note contains unusable content. "
                        "Is something else using this notes tree? %s", notes_ref);
-               free(msg);
-               msg = NULL;
+               FREE_AND_NULL(msg);
        }
        free_notes(NULL);
        return msg;
index f998f989e92a6eb919828c72d444f091d5fdfa6a..d87482573d38b057257c08024fbe6b4339661481 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "remote.h"
 #include "refs.h"
 #include "commit.h"
diff --git a/repository.c b/repository.c
new file mode 100644 (file)
index 0000000..edca907
--- /dev/null
@@ -0,0 +1,242 @@
+#include "cache.h"
+#include "repository.h"
+#include "config.h"
+#include "submodule-config.h"
+
+/* The main repository */
+static struct repository the_repo;
+struct repository *the_repository = &the_repo;
+
+static char *git_path_from_env(const char *envvar, const char *git_dir,
+                              const char *path, int fromenv)
+{
+       if (fromenv) {
+               const char *value = getenv(envvar);
+               if (value)
+                       return xstrdup(value);
+       }
+
+       return xstrfmt("%s/%s", git_dir, path);
+}
+
+static int find_common_dir(struct strbuf *sb, const char *gitdir, int fromenv)
+{
+       if (fromenv) {
+               const char *value = getenv(GIT_COMMON_DIR_ENVIRONMENT);
+               if (value) {
+                       strbuf_addstr(sb, value);
+                       return 1;
+               }
+       }
+
+       return get_common_dir_noenv(sb, gitdir);
+}
+
+static void repo_setup_env(struct repository *repo)
+{
+       struct strbuf sb = STRBUF_INIT;
+
+       repo->different_commondir = find_common_dir(&sb, repo->gitdir,
+                                                   !repo->ignore_env);
+       repo->commondir = strbuf_detach(&sb, NULL);
+       repo->objectdir = git_path_from_env(DB_ENVIRONMENT, repo->commondir,
+                                           "objects", !repo->ignore_env);
+       repo->graft_file = git_path_from_env(GRAFT_ENVIRONMENT, repo->commondir,
+                                            "info/grafts", !repo->ignore_env);
+       repo->index_file = git_path_from_env(INDEX_ENVIRONMENT, repo->gitdir,
+                                            "index", !repo->ignore_env);
+}
+
+void repo_set_gitdir(struct repository *repo, const char *path)
+{
+       const char *gitfile = read_gitfile(path);
+
+       /*
+        * NEEDSWORK: Eventually we want to be able to free gitdir and the rest
+        * of the environment before reinitializing it again, but we have some
+        * crazy code paths where we try to set gitdir with the current gitdir
+        * and we don't want to free gitdir before copying the passed in value.
+        */
+       repo->gitdir = xstrdup(gitfile ? gitfile : path);
+
+       repo_setup_env(repo);
+}
+
+/*
+ * Attempt to resolve and set the provided 'gitdir' for repository 'repo'.
+ * Return 0 upon success and a non-zero value upon failure.
+ */
+static int repo_init_gitdir(struct repository *repo, const char *gitdir)
+{
+       int ret = 0;
+       int error = 0;
+       char *abspath = NULL;
+       const char *resolved_gitdir;
+
+       abspath = real_pathdup(gitdir, 0);
+       if (!abspath) {
+               ret = -1;
+               goto out;
+       }
+
+       /* 'gitdir' must reference the gitdir directly */
+       resolved_gitdir = resolve_gitdir_gently(abspath, &error);
+       if (!resolved_gitdir) {
+               ret = -1;
+               goto out;
+       }
+
+       repo_set_gitdir(repo, resolved_gitdir);
+
+out:
+       free(abspath);
+       return ret;
+}
+
+void repo_set_worktree(struct repository *repo, const char *path)
+{
+       repo->worktree = real_pathdup(path, 1);
+}
+
+static int read_and_verify_repository_format(struct repository_format *format,
+                                            const char *commondir)
+{
+       int ret = 0;
+       struct strbuf sb = STRBUF_INIT;
+
+       strbuf_addf(&sb, "%s/config", commondir);
+       read_repository_format(format, sb.buf);
+       strbuf_reset(&sb);
+
+       if (verify_repository_format(format, &sb) < 0) {
+               warning("%s", sb.buf);
+               ret = -1;
+       }
+
+       strbuf_release(&sb);
+       return ret;
+}
+
+/*
+ * Initialize 'repo' based on the provided 'gitdir'.
+ * Return 0 upon success and a non-zero value upon failure.
+ */
+int repo_init(struct repository *repo, const char *gitdir, const char *worktree)
+{
+       struct repository_format format;
+       memset(repo, 0, sizeof(*repo));
+
+       repo->ignore_env = 1;
+
+       if (repo_init_gitdir(repo, gitdir))
+               goto error;
+
+       if (read_and_verify_repository_format(&format, repo->commondir))
+               goto error;
+
+       if (worktree)
+               repo_set_worktree(repo, worktree);
+
+       return 0;
+
+error:
+       repo_clear(repo);
+       return -1;
+}
+
+/*
+ * Initialize 'submodule' as the submodule given by 'path' in parent repository
+ * 'superproject'.
+ * Return 0 upon success and a non-zero value upon failure.
+ */
+int repo_submodule_init(struct repository *submodule,
+                       struct repository *superproject,
+                       const char *path)
+{
+       const struct submodule *sub;
+       struct strbuf gitdir = STRBUF_INIT;
+       struct strbuf worktree = STRBUF_INIT;
+       int ret = 0;
+
+       sub = submodule_from_cache(superproject, null_sha1, path);
+       if (!sub) {
+               ret = -1;
+               goto out;
+       }
+
+       strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", path);
+       strbuf_repo_worktree_path(&worktree, superproject, "%s", path);
+
+       if (repo_init(submodule, gitdir.buf, worktree.buf)) {
+               /*
+                * If initilization fails then it may be due to the submodule
+                * not being populated in the superproject's worktree.  Instead
+                * we can try to initilize the submodule by finding it's gitdir
+                * in the superproject's 'modules' directory.  In this case the
+                * submodule would not have a worktree.
+                */
+               strbuf_reset(&gitdir);
+               strbuf_repo_git_path(&gitdir, superproject,
+                                    "modules/%s", sub->name);
+
+               if (repo_init(submodule, gitdir.buf, NULL)) {
+                       ret = -1;
+                       goto out;
+               }
+       }
+
+       submodule->submodule_prefix = xstrfmt("%s%s/",
+                                             superproject->submodule_prefix ?
+                                             superproject->submodule_prefix :
+                                             "", path);
+
+out:
+       strbuf_release(&gitdir);
+       strbuf_release(&worktree);
+       return ret;
+}
+
+void repo_clear(struct repository *repo)
+{
+       free(repo->gitdir);
+       repo->gitdir = NULL;
+       free(repo->commondir);
+       repo->commondir = NULL;
+       free(repo->objectdir);
+       repo->objectdir = NULL;
+       free(repo->graft_file);
+       repo->graft_file = NULL;
+       free(repo->index_file);
+       repo->index_file = NULL;
+       free(repo->worktree);
+       repo->worktree = NULL;
+       free(repo->submodule_prefix);
+       repo->submodule_prefix = NULL;
+
+       if (repo->config) {
+               git_configset_clear(repo->config);
+               free(repo->config);
+               repo->config = NULL;
+       }
+
+       if (repo->submodule_cache) {
+               submodule_cache_free(repo->submodule_cache);
+               repo->submodule_cache = NULL;
+       }
+
+       if (repo->index) {
+               discard_index(repo->index);
+               free(repo->index);
+               repo->index = NULL;
+       }
+}
+
+int repo_read_index(struct repository *repo)
+{
+       if (!repo->index)
+               repo->index = xcalloc(1, sizeof(*repo->index));
+       else
+               discard_index(repo->index);
+
+       return read_index_from(repo->index, repo->index_file);
+}
diff --git a/repository.h b/repository.h
new file mode 100644 (file)
index 0000000..417787f
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef REPOSITORY_H
+#define REPOSITORY_H
+
+struct config_set;
+struct index_state;
+struct submodule_cache;
+
+struct repository {
+       /* Environment */
+       /*
+        * Path to the git directory.
+        * Cannot be NULL after initialization.
+        */
+       char *gitdir;
+
+       /*
+        * Path to the common git directory.
+        * Cannot be NULL after initialization.
+        */
+       char *commondir;
+
+       /*
+        * Path to the repository's object store.
+        * Cannot be NULL after initialization.
+        */
+       char *objectdir;
+
+       /*
+        * Path to the repository's graft file.
+        * Cannot be NULL after initialization.
+        */
+       char *graft_file;
+
+       /*
+        * Path to the current worktree's index file.
+        * Cannot be NULL after initialization.
+        */
+       char *index_file;
+
+       /*
+        * Path to the working directory.
+        * A NULL value indicates that there is no working directory.
+        */
+       char *worktree;
+
+       /*
+        * Path from the root of the top-level superproject down to this
+        * repository.  This is only non-NULL if the repository is initialized
+        * as a submodule of another repository.
+        */
+       char *submodule_prefix;
+
+       /* Subsystems */
+       /*
+        * Repository's config which contains key-value pairs from the usual
+        * set of config files (i.e. repo specific .git/config, user wide
+        * ~/.gitconfig, XDG config file and the global /etc/gitconfig)
+        */
+       struct config_set *config;
+
+       /* Repository's submodule config as defined by '.gitmodules' */
+       struct submodule_cache *submodule_cache;
+
+       /*
+        * Repository's in-memory index.
+        * 'repo_read_index()' can be used to populate 'index'.
+        */
+       struct index_state *index;
+
+       /* Configurations */
+       /*
+        * Bit used during initialization to indicate if repository state (like
+        * the location of the 'objectdir') should be read from the
+        * environment.  By default this bit will be set at the begining of
+        * 'repo_init()' so that all repositories will ignore the environment.
+        * The exception to this is 'the_repository', which doesn't go through
+        * the normal 'repo_init()' process.
+        */
+       unsigned ignore_env:1;
+
+       /* Indicate if a repository has a different 'commondir' from 'gitdir' */
+       unsigned different_commondir:1;
+};
+
+extern struct repository *the_repository;
+
+extern void repo_set_gitdir(struct repository *repo, const char *path);
+extern void repo_set_worktree(struct repository *repo, const char *path);
+extern int repo_init(struct repository *repo, const char *gitdir, const char *worktree);
+extern int repo_submodule_init(struct repository *submodule,
+                              struct repository *superproject,
+                              const char *path);
+extern void repo_clear(struct repository *repo);
+
+extern int repo_read_index(struct repository *repo);
+
+#endif /* REPOSITORY_H */
index c26c29f87a6f35d2efffd226fa8922f36cd0bb37..70634d456cc0b70cdbac1579b82016761252c7d9 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "string-list.h"
 #include "rerere.h"
@@ -39,9 +40,8 @@ static void free_rerere_dirs(void)
                free(rerere_dir[i]->status);
                free(rerere_dir[i]);
        }
-       free(rerere_dir);
+       FREE_AND_NULL(rerere_dir);
        rerere_dir_nr = rerere_dir_alloc = 0;
-       rerere_dir = NULL;
 }
 
 static void free_rerere_id(struct string_list_item *item)
index 4ab8344ee87cfcaa64c038411693f12ed3c38dc7..9ff120b30518aa2b3f7cc214a1c921d739108d7c 100644 (file)
@@ -2075,7 +2075,7 @@ static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_d
        struct strbuf bisect_refs = STRBUF_INIT;
        int status;
        strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
-       status = for_each_ref_in_submodule(submodule, bisect_refs.buf, fn, cb_data);
+       status = for_each_fullref_in_submodule(submodule, bisect_refs.buf, fn, cb_data, 0);
        strbuf_release(&bisect_refs);
        return status;
 }
index 78bb34ebec297102c852a5b88ec7b4f10ffbc1d8..11d6f3d98398e8b7a1add501dd7ee85a736531b6 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "commit.h"
 #include "refs.h"
 #include "pkt-line.h"
@@ -132,7 +133,7 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *extra, struc
                 * For a normal non-zero exit, we assume pack-objects wrote
                 * something useful to stderr. For death by signal, though,
                 * we should mention it to the user. The exception is SIGPIPE
-                * (141), because that's a normal occurence if the remote end
+                * (141), because that's a normal occurrence if the remote end
                 * hangs up (and we'll report that by trying to read the unpack
                 * status).
                 */
index d63099d50fc4e23cb3585b12c61ba8863d2688f6..3010faf86398697469e903318a35421d911acb23 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "sequencer.h"
 #include "dir.h"
@@ -1211,8 +1212,7 @@ struct todo_list {
 static void todo_list_release(struct todo_list *todo_list)
 {
        strbuf_release(&todo_list->buf);
-       free(todo_list->items);
-       todo_list->items = NULL;
+       FREE_AND_NULL(todo_list->items);
        todo_list->nr = todo_list->alloc = 0;
 }
 
@@ -1922,7 +1922,7 @@ static int apply_autostash(struct replay_opts *opts)
        argv_array_push(&child.args, "apply");
        argv_array_push(&child.args, stash_sha1.buf);
        if (!run_command(&child))
-               printf(_("Applied autostash.\n"));
+               fprintf(stderr, _("Applied autostash.\n"));
        else {
                struct child_process store = CHILD_PROCESS_INIT;
 
@@ -1936,10 +1936,11 @@ static int apply_autostash(struct replay_opts *opts)
                if (run_command(&store))
                        ret = error(_("cannot store %s"), stash_sha1.buf);
                else
-                       printf(_("Applying autostash resulted in conflicts.\n"
-                               "Your changes are safe in the stash.\n"
-                               "You can run \"git stash pop\" or"
-                               " \"git stash drop\" at any time.\n"));
+                       fprintf(stderr,
+                               _("Applying autostash resulted in conflicts.\n"
+                                 "Your changes are safe in the stash.\n"
+                                 "You can run \"git stash pop\" or"
+                                 " \"git stash drop\" at any time.\n"));
        }
 
        strbuf_release(&stash_sha1);
diff --git a/setup.c b/setup.c
index 751d02b9be627176009cdda4f1b20a3674b0dc95..860507e1fdb2d61da71b27eb00d8413f2fabcfa9 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -1,4 +1,6 @@
 #include "cache.h"
+#include "repository.h"
+#include "config.h"
 #include "dir.h"
 #include "string-list.h"
 
@@ -397,6 +399,11 @@ void setup_work_tree(void)
        if (getenv(GIT_WORK_TREE_ENVIRONMENT))
                setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
 
+       /*
+        * NEEDSWORK: this call can essentially be set_git_dir(get_git_dir())
+        * which can cause some problems when trying to free the old value of
+        * gitdir.
+        */
        set_git_dir(remove_leading_path(git_dir, work_tree));
        initialized = 1;
 }
@@ -967,19 +974,21 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
        }
 }
 
-const char *discover_git_directory(struct strbuf *gitdir)
+int discover_git_directory(struct strbuf *commondir,
+                          struct strbuf *gitdir)
 {
        struct strbuf dir = STRBUF_INIT, err = STRBUF_INIT;
        size_t gitdir_offset = gitdir->len, cwd_len;
+       size_t commondir_offset = commondir->len;
        struct repository_format candidate;
 
        if (strbuf_getcwd(&dir))
-               return NULL;
+               return -1;
 
        cwd_len = dir.len;
        if (setup_git_directory_gently_1(&dir, gitdir, 0) <= 0) {
                strbuf_release(&dir);
-               return NULL;
+               return -1;
        }
 
        /*
@@ -995,8 +1004,10 @@ const char *discover_git_directory(struct strbuf *gitdir)
                strbuf_insert(gitdir, gitdir_offset, dir.buf, dir.len);
        }
 
+       get_common_dir(commondir, gitdir->buf + gitdir_offset);
+
        strbuf_reset(&dir);
-       strbuf_addf(&dir, "%s/config", gitdir->buf + gitdir_offset);
+       strbuf_addf(&dir, "%s/config", commondir->buf + commondir_offset);
        read_repository_format(&candidate, dir.buf);
        strbuf_release(&dir);
 
@@ -1004,10 +1015,12 @@ const char *discover_git_directory(struct strbuf *gitdir)
                warning("ignoring git dir '%s': %s",
                        gitdir->buf + gitdir_offset, err.buf);
                strbuf_release(&err);
-               return NULL;
+               strbuf_setlen(commondir, commondir_offset);
+               strbuf_setlen(gitdir, gitdir_offset);
+               return -1;
        }
 
-       return gitdir->buf + gitdir_offset;
+       return 0;
 }
 
 const char *setup_git_directory_gently(int *nongit_ok)
@@ -1072,6 +1085,12 @@ const char *setup_git_directory_gently(int *nongit_ok)
                die("BUG: unhandled setup_git_directory_1() result");
        }
 
+       /*
+        * NEEDSWORK: This was a hack in order to get ls-files and grep to have
+        * properly formated output when recursing submodules.  Once ls-files
+        * and grep have been changed to perform this recursing in-process this
+        * needs to be removed.
+        */
        env_prefix = getenv(GIT_TOPLEVEL_PREFIX_ENVIRONMENT);
        if (env_prefix)
                prefix = env_prefix;
@@ -1084,6 +1103,27 @@ const char *setup_git_directory_gently(int *nongit_ok)
        startup_info->have_repository = !nongit_ok || !*nongit_ok;
        startup_info->prefix = prefix;
 
+       /*
+        * Not all paths through the setup code will call 'set_git_dir()' (which
+        * directly sets up the environment) so in order to guarantee that the
+        * environment is in a consistent state after setup, explicitly setup
+        * the environment if we have a repository.
+        *
+        * NEEDSWORK: currently we allow bogus GIT_DIR values to be set in some
+        * code paths so we also need to explicitly setup the environment if
+        * the user has set GIT_DIR.  It may be beneficial to disallow bogus
+        * GIT_DIR values at some point in the future.
+        */
+       if (startup_info->have_repository || getenv(GIT_DIR_ENVIRONMENT)) {
+               if (!the_repository->gitdir) {
+                       const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
+                       if (!gitdir)
+                               gitdir = DEFAULT_GIT_DIR_ENVIRONMENT;
+                       repo_set_gitdir(the_repository, gitdir);
+                       setup_git_env();
+               }
+       }
+
        strbuf_release(&dir);
        strbuf_release(&gitdir);
 
index 7d646ab5b8cf80e47c6c1f339affeaa76a41d2d2..838b3bf8478cfdfcd78f866e69dc0f8c5cbf3c9e 100644 (file)
@@ -35,8 +35,7 @@ int oid_array_lookup(struct oid_array *array, const struct object_id *oid)
 
 void oid_array_clear(struct oid_array *array)
 {
-       free(array->oid);
-       array->oid = NULL;
+       FREE_AND_NULL(array->oid);
        array->nr = 0;
        array->alloc = 0;
        array->sorted = 0;
index 59a4ed2ed32336b41ab8f3b1d4aca30f045aa084..5862386cd0c2b2020890905bd06cd3a9d89c123b 100644 (file)
@@ -7,6 +7,7 @@
  * creation etc.
  */
 #include "cache.h"
+#include "config.h"
 #include "string-list.h"
 #include "lockfile.h"
 #include "delta.h"
@@ -610,8 +611,7 @@ char *compute_alternate_path(const char *path, struct strbuf *err)
 
 out:
        if (seen_error) {
-               free(ref_git);
-               ref_git = NULL;
+               FREE_AND_NULL(ref_git);
        }
 
        return ref_git;
@@ -1964,7 +1964,7 @@ static int parse_sha1_header_extended(const char *hdr, struct object_info *oi,
         * we're obtaining the type using '--allow-unknown-type'
         * option.
         */
-       if ((flags & LOOKUP_UNKNOWN_OBJECT) && (type < 0))
+       if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE) && (type < 0))
                type = 0;
        else if (type < 0)
                die("invalid object type");
@@ -2002,20 +2002,7 @@ int parse_sha1_header(const char *hdr, unsigned long *sizep)
        struct object_info oi = OBJECT_INFO_INIT;
 
        oi.sizep = sizep;
-       return parse_sha1_header_extended(hdr, &oi, LOOKUP_REPLACE_OBJECT);
-}
-
-static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size, const unsigned char *sha1)
-{
-       int ret;
-       git_zstream stream;
-       char hdr[8192];
-
-       ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr));
-       if (ret < Z_OK || (*type = parse_sha1_header(hdr, size)) < 0)
-               return NULL;
-
-       return unpack_sha1_rest(&stream, hdr, *size, sha1);
+       return parse_sha1_header_extended(hdr, &oi, 0);
 }
 
 unsigned long get_size_from_delta(struct packed_git *p,
@@ -2239,107 +2226,6 @@ static enum object_type packed_to_object_type(struct packed_git *p,
        goto out;
 }
 
-int packed_object_info(struct packed_git *p, off_t obj_offset,
-                      struct object_info *oi)
-{
-       struct pack_window *w_curs = NULL;
-       unsigned long size;
-       off_t curpos = obj_offset;
-       enum object_type type;
-
-       /*
-        * We always get the representation type, but only convert it to
-        * a "real" type later if the caller is interested.
-        */
-       type = unpack_object_header(p, &w_curs, &curpos, &size);
-
-       if (oi->sizep) {
-               if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
-                       off_t tmp_pos = curpos;
-                       off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
-                                                          type, obj_offset);
-                       if (!base_offset) {
-                               type = OBJ_BAD;
-                               goto out;
-                       }
-                       *oi->sizep = get_size_from_delta(p, &w_curs, tmp_pos);
-                       if (*oi->sizep == 0) {
-                               type = OBJ_BAD;
-                               goto out;
-                       }
-               } else {
-                       *oi->sizep = size;
-               }
-       }
-
-       if (oi->disk_sizep) {
-               struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
-               *oi->disk_sizep = revidx[1].offset - obj_offset;
-       }
-
-       if (oi->typep) {
-               *oi->typep = packed_to_object_type(p, obj_offset, type, &w_curs, curpos);
-               if (*oi->typep < 0) {
-                       type = OBJ_BAD;
-                       goto out;
-               }
-       }
-
-       if (oi->delta_base_sha1) {
-               if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
-                       const unsigned char *base;
-
-                       base = get_delta_base_sha1(p, &w_curs, curpos,
-                                                  type, obj_offset);
-                       if (!base) {
-                               type = OBJ_BAD;
-                               goto out;
-                       }
-
-                       hashcpy(oi->delta_base_sha1, base);
-               } else
-                       hashclr(oi->delta_base_sha1);
-       }
-
-out:
-       unuse_pack(&w_curs);
-       return type;
-}
-
-static void *unpack_compressed_entry(struct packed_git *p,
-                                   struct pack_window **w_curs,
-                                   off_t curpos,
-                                   unsigned long size)
-{
-       int st;
-       git_zstream stream;
-       unsigned char *buffer, *in;
-
-       buffer = xmallocz_gently(size);
-       if (!buffer)
-               return NULL;
-       memset(&stream, 0, sizeof(stream));
-       stream.next_out = buffer;
-       stream.avail_out = size + 1;
-
-       git_inflate_init(&stream);
-       do {
-               in = use_pack(p, w_curs, curpos, &stream.avail_in);
-               stream.next_in = in;
-               st = git_inflate(&stream, Z_FINISH);
-               if (!stream.avail_out)
-                       break; /* the payload is larger than it should be */
-               curpos += stream.next_in - in;
-       } while (st == Z_OK || st == Z_BUF_ERROR);
-       git_inflate_end(&stream);
-       if ((st != Z_STREAM_END) || stream.total_out != size) {
-               free(buffer);
-               return NULL;
-       }
-
-       return buffer;
-}
-
 static struct hashmap delta_base_cache;
 static size_t delta_base_cached;
 
@@ -2427,8 +2313,10 @@ static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
        if (!ent)
                return unpack_entry(p, base_offset, type, base_size);
 
-       *type = ent->type;
-       *base_size = ent->size;
+       if (type)
+               *type = ent->type;
+       if (base_size)
+               *base_size = ent->size;
        return xmemdupz(ent->data, ent->size);
 }
 
@@ -2477,6 +2365,123 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
        hashmap_add(&delta_base_cache, ent);
 }
 
+int packed_object_info(struct packed_git *p, off_t obj_offset,
+                      struct object_info *oi)
+{
+       struct pack_window *w_curs = NULL;
+       unsigned long size;
+       off_t curpos = obj_offset;
+       enum object_type type;
+
+       /*
+        * We always get the representation type, but only convert it to
+        * a "real" type later if the caller is interested.
+        */
+       if (oi->contentp) {
+               *oi->contentp = cache_or_unpack_entry(p, obj_offset, oi->sizep,
+                                                     &type);
+               if (!*oi->contentp)
+                       type = OBJ_BAD;
+       } else {
+               type = unpack_object_header(p, &w_curs, &curpos, &size);
+       }
+
+       if (!oi->contentp && oi->sizep) {
+               if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
+                       off_t tmp_pos = curpos;
+                       off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
+                                                          type, obj_offset);
+                       if (!base_offset) {
+                               type = OBJ_BAD;
+                               goto out;
+                       }
+                       *oi->sizep = get_size_from_delta(p, &w_curs, tmp_pos);
+                       if (*oi->sizep == 0) {
+                               type = OBJ_BAD;
+                               goto out;
+                       }
+               } else {
+                       *oi->sizep = size;
+               }
+       }
+
+       if (oi->disk_sizep) {
+               struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
+               *oi->disk_sizep = revidx[1].offset - obj_offset;
+       }
+
+       if (oi->typep || oi->typename) {
+               enum object_type ptot;
+               ptot = packed_to_object_type(p, obj_offset, type, &w_curs,
+                                            curpos);
+               if (oi->typep)
+                       *oi->typep = ptot;
+               if (oi->typename) {
+                       const char *tn = typename(ptot);
+                       if (tn)
+                               strbuf_addstr(oi->typename, tn);
+               }
+               if (ptot < 0) {
+                       type = OBJ_BAD;
+                       goto out;
+               }
+       }
+
+       if (oi->delta_base_sha1) {
+               if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
+                       const unsigned char *base;
+
+                       base = get_delta_base_sha1(p, &w_curs, curpos,
+                                                  type, obj_offset);
+                       if (!base) {
+                               type = OBJ_BAD;
+                               goto out;
+                       }
+
+                       hashcpy(oi->delta_base_sha1, base);
+               } else
+                       hashclr(oi->delta_base_sha1);
+       }
+
+out:
+       unuse_pack(&w_curs);
+       return type;
+}
+
+static void *unpack_compressed_entry(struct packed_git *p,
+                                   struct pack_window **w_curs,
+                                   off_t curpos,
+                                   unsigned long size)
+{
+       int st;
+       git_zstream stream;
+       unsigned char *buffer, *in;
+
+       buffer = xmallocz_gently(size);
+       if (!buffer)
+               return NULL;
+       memset(&stream, 0, sizeof(stream));
+       stream.next_out = buffer;
+       stream.avail_out = size + 1;
+
+       git_inflate_init(&stream);
+       do {
+               in = use_pack(p, w_curs, curpos, &stream.avail_in);
+               stream.next_in = in;
+               st = git_inflate(&stream, Z_FINISH);
+               if (!stream.avail_out)
+                       break; /* the payload is larger than it should be */
+               curpos += stream.next_in - in;
+       } while (st == Z_OK || st == Z_BUF_ERROR);
+       git_inflate_end(&stream);
+       if ((st != Z_STREAM_END) || stream.total_out != size) {
+               free(buffer);
+               return NULL;
+       }
+
+       return buffer;
+}
+
 static void *read_object(const unsigned char *sha1, enum object_type *type,
                         unsigned long *size);
 
@@ -2670,8 +2675,10 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
                free(external_base);
        }
 
-       *final_type = type;
-       *final_size = size;
+       if (final_type)
+               *final_type = type;
+       if (final_size)
+               *final_size = size;
 
        unuse_pack(&w_curs);
 
@@ -2905,6 +2912,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
        git_zstream stream;
        char hdr[32];
        struct strbuf hdrbuf = STRBUF_INIT;
+       unsigned long size_scratch;
 
        if (oi->delta_base_sha1)
                hashclr(oi->delta_base_sha1);
@@ -2917,7 +2925,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
         * return value implicitly indicates whether the
         * object even exists.
         */
-       if (!oi->typep && !oi->typename && !oi->sizep) {
+       if (!oi->typep && !oi->typename && !oi->sizep && !oi->contentp) {
                const char *path;
                struct stat st;
                if (stat_sha1_file(sha1, &st, &path) < 0)
@@ -2930,9 +2938,13 @@ static int sha1_loose_object_info(const unsigned char *sha1,
        map = map_sha1_file(sha1, &mapsize);
        if (!map)
                return -1;
+
+       if (!oi->sizep)
+               oi->sizep = &size_scratch;
+
        if (oi->disk_sizep)
                *oi->disk_sizep = mapsize;
-       if ((flags & LOOKUP_UNKNOWN_OBJECT)) {
+       if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE)) {
                if (unpack_sha1_header_to_strbuf(&stream, map, mapsize, hdr, sizeof(hdr), &hdrbuf) < 0)
                        status = error("unable to unpack %s header with --allow-unknown-type",
                                       sha1_to_hex(sha1));
@@ -2947,36 +2959,52 @@ static int sha1_loose_object_info(const unsigned char *sha1,
                                       sha1_to_hex(sha1));
        } else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0)
                status = error("unable to parse %s header", sha1_to_hex(sha1));
-       git_inflate_end(&stream);
+
+       if (status >= 0 && oi->contentp)
+               *oi->contentp = unpack_sha1_rest(&stream, hdr,
+                                                *oi->sizep, sha1);
+       else
+               git_inflate_end(&stream);
+
        munmap(map, mapsize);
        if (status && oi->typep)
                *oi->typep = status;
+       if (oi->sizep == &size_scratch)
+               oi->sizep = NULL;
        strbuf_release(&hdrbuf);
        return (status < 0) ? status : 0;
 }
 
 int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags)
 {
-       struct cached_object *co;
+       static struct object_info blank_oi = OBJECT_INFO_INIT;
        struct pack_entry e;
        int rtype;
-       enum object_type real_type;
-       const unsigned char *real = lookup_replace_object_extended(sha1, flags);
-
-       co = find_cached_object(real);
-       if (co) {
-               if (oi->typep)
-                       *(oi->typep) = co->type;
-               if (oi->sizep)
-                       *(oi->sizep) = co->size;
-               if (oi->disk_sizep)
-                       *(oi->disk_sizep) = 0;
-               if (oi->delta_base_sha1)
-                       hashclr(oi->delta_base_sha1);
-               if (oi->typename)
-                       strbuf_addstr(oi->typename, typename(co->type));
-               oi->whence = OI_CACHED;
-               return 0;
+       const unsigned char *real = (flags & OBJECT_INFO_LOOKUP_REPLACE) ?
+                                   lookup_replace_object(sha1) :
+                                   sha1;
+
+       if (!oi)
+               oi = &blank_oi;
+
+       if (!(flags & OBJECT_INFO_SKIP_CACHED)) {
+               struct cached_object *co = find_cached_object(real);
+               if (co) {
+                       if (oi->typep)
+                               *(oi->typep) = co->type;
+                       if (oi->sizep)
+                               *(oi->sizep) = co->size;
+                       if (oi->disk_sizep)
+                               *(oi->disk_sizep) = 0;
+                       if (oi->delta_base_sha1)
+                               hashclr(oi->delta_base_sha1);
+                       if (oi->typename)
+                               strbuf_addstr(oi->typename, typename(co->type));
+                       if (oi->contentp)
+                               *oi->contentp = xmemdupz(co->buf, co->size);
+                       oi->whence = OI_CACHED;
+                       return 0;
+               }
        }
 
        if (!find_pack_entry(real, &e)) {
@@ -2987,23 +3015,25 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
                }
 
                /* Not a loose object; someone else may have just packed it. */
-               reprepare_packed_git();
-               if (!find_pack_entry(real, &e))
+               if (flags & OBJECT_INFO_QUICK) {
                        return -1;
+               } else {
+                       reprepare_packed_git();
+                       if (!find_pack_entry(real, &e))
+                               return -1;
+               }
        }
 
-       /*
-        * packed_object_info() does not follow the delta chain to
-        * find out the real type, unless it is given oi->typep.
-        */
-       if (oi->typename && !oi->typep)
-               oi->typep = &real_type;
+       if (oi == &blank_oi)
+               /*
+                * We know that the caller doesn't actually need the
+                * information below, so return early.
+                */
+               return 0;
 
        rtype = packed_object_info(e.p, e.offset, oi);
        if (rtype < 0) {
                mark_bad_packed_object(e.p, real);
-               if (oi->typep == &real_type)
-                       oi->typep = NULL;
                return sha1_object_info_extended(real, oi, 0);
        } else if (in_delta_base_cache(e.p, e.offset)) {
                oi->whence = OI_DBCACHED;
@@ -3014,10 +3044,6 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
                oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||
                                         rtype == OBJ_OFS_DELTA);
        }
-       if (oi->typename)
-               strbuf_addstr(oi->typename, typename(*oi->typep));
-       if (oi->typep == &real_type)
-               oi->typep = NULL;
 
        return 0;
 }
@@ -3030,7 +3056,8 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
 
        oi.typep = &type;
        oi.sizep = sizep;
-       if (sha1_object_info_extended(sha1, &oi, LOOKUP_REPLACE_OBJECT) < 0)
+       if (sha1_object_info_extended(sha1, &oi,
+                                     OBJECT_INFO_LOOKUP_REPLACE) < 0)
                return -1;
        return type;
 }
@@ -3080,28 +3107,15 @@ int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
 static void *read_object(const unsigned char *sha1, enum object_type *type,
                         unsigned long *size)
 {
-       unsigned long mapsize;
-       void *map, *buf;
-       struct cached_object *co;
-
-       co = find_cached_object(sha1);
-       if (co) {
-               *type = co->type;
-               *size = co->size;
-               return xmemdupz(co->buf, co->size);
-       }
+       struct object_info oi = OBJECT_INFO_INIT;
+       void *content;
+       oi.typep = type;
+       oi.sizep = size;
+       oi.contentp = &content;
 
-       buf = read_packed_sha1(sha1, type, size);
-       if (buf)
-               return buf;
-       map = map_sha1_file(sha1, &mapsize);
-       if (map) {
-               buf = unpack_sha1_file(map, mapsize, type, size, sha1);
-               munmap(map, mapsize);
-               return buf;
-       }
-       reprepare_packed_git();
-       return read_packed_sha1(sha1, type, size);
+       if (sha1_object_info_extended(sha1, &oi, 0) < 0)
+               return NULL;
+       return content;
 }
 
 /*
@@ -3112,13 +3126,14 @@ static void *read_object(const unsigned char *sha1, enum object_type *type,
 void *read_sha1_file_extended(const unsigned char *sha1,
                              enum object_type *type,
                              unsigned long *size,
-                             unsigned flag)
+                             int lookup_replace)
 {
        void *data;
        const struct packed_git *p;
        const char *path;
        struct stat st;
-       const unsigned char *repl = lookup_replace_object_extended(sha1, flag);
+       const unsigned char *repl = lookup_replace ? lookup_replace_object(sha1)
+                                                  : sha1;
 
        errno = 0;
        data = read_object(repl, type, size);
@@ -3479,18 +3494,10 @@ int has_sha1_pack(const unsigned char *sha1)
 
 int has_sha1_file_with_flags(const unsigned char *sha1, int flags)
 {
-       struct pack_entry e;
-
        if (!startup_info->have_repository)
                return 0;
-       if (find_pack_entry(sha1, &e))
-               return 1;
-       if (has_loose_object(sha1))
-               return 1;
-       if (flags & HAS_SHA1_QUICK)
-               return 0;
-       reprepare_packed_git();
-       return find_pack_entry(sha1, &e);
+       return sha1_object_info_extended(sha1, NULL,
+                                        flags | OBJECT_INFO_SKIP_CACHED) >= 0;
 }
 
 int has_object_file(const struct object_id *oid)
@@ -3546,7 +3553,7 @@ static int index_mem(unsigned char *sha1, void *buf, size_t size,
         */
        if ((type == OBJ_BLOB) && path) {
                struct strbuf nbuf = STRBUF_INIT;
-               if (convert_to_git(path, buf, size, &nbuf,
+               if (convert_to_git(&the_index, path, buf, size, &nbuf,
                                   write_object ? safe_crlf : SAFE_CRLF_FALSE)) {
                        buf = strbuf_detach(&nbuf, &size);
                        re_allocated = 1;
@@ -3580,7 +3587,7 @@ static int index_stream_convert_blob(unsigned char *sha1, int fd,
        assert(path);
        assert(would_convert_to_git_filter_fd(path));
 
-       convert_to_git_filter_fd(path, fd, &sbuf,
+       convert_to_git_filter_fd(&the_index, path, fd, &sbuf,
                                 write_object ? safe_crlf : SAFE_CRLF_FALSE);
 
        if (write_object)
@@ -3668,7 +3675,7 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st,
        else if (!S_ISREG(st->st_mode))
                ret = index_pipe(sha1, fd, type, path, flags);
        else if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||
-                (path && would_convert_to_git(path)))
+                (path && would_convert_to_git(&the_index, path)))
                ret = index_core(sha1, fd, xsize_t(st->st_size), type, path,
                                 flags);
        else
@@ -3735,22 +3742,32 @@ void assert_sha1_type(const unsigned char *sha1, enum object_type expect)
                    typename(expect));
 }
 
-static int for_each_file_in_obj_subdir(int subdir_nr,
-                                      struct strbuf *path,
-                                      each_loose_object_fn obj_cb,
-                                      each_loose_cruft_fn cruft_cb,
-                                      each_loose_subdir_fn subdir_cb,
-                                      void *data)
+int for_each_file_in_obj_subdir(unsigned int subdir_nr,
+                               struct strbuf *path,
+                               each_loose_object_fn obj_cb,
+                               each_loose_cruft_fn cruft_cb,
+                               each_loose_subdir_fn subdir_cb,
+                               void *data)
 {
-       size_t baselen = path->len;
-       DIR *dir = opendir(path->buf);
+       size_t origlen, baselen;
+       DIR *dir;
        struct dirent *de;
        int r = 0;
 
+       if (subdir_nr > 0xff)
+               BUG("invalid loose object subdirectory: %x", subdir_nr);
+
+       origlen = path->len;
+       strbuf_complete(path, '/');
+       strbuf_addf(path, "%02x", subdir_nr);
+       baselen = path->len;
+
+       dir = opendir(path->buf);
        if (!dir) {
-               if (errno == ENOENT)
-                       return 0;
-               return error_errno("unable to open %s", path->buf);
+               if (errno != ENOENT)
+                       r = error_errno("unable to open %s", path->buf);
+               strbuf_setlen(path, origlen);
+               return r;
        }
 
        while ((de = readdir(dir))) {
@@ -3788,6 +3805,8 @@ static int for_each_file_in_obj_subdir(int subdir_nr,
        if (!r && subdir_cb)
                r = subdir_cb(subdir_nr, path->buf, data);
 
+       strbuf_setlen(path, origlen);
+
        return r;
 }
 
@@ -3797,15 +3816,12 @@ int for_each_loose_file_in_objdir_buf(struct strbuf *path,
                            each_loose_subdir_fn subdir_cb,
                            void *data)
 {
-       size_t baselen = path->len;
        int r = 0;
        int i;
 
        for (i = 0; i < 256; i++) {
-               strbuf_addf(path, "/%02x", i);
                r = for_each_file_in_obj_subdir(i, path, obj_cb, cruft_cb,
                                                subdir_cb, data);
-               strbuf_setlen(path, baselen);
                if (r)
                        break;
        }
index 5126853bb5bda5f291039588db96064ffbd1ee5c..e7f7b12cebfb4060a5d3e6567029bb308c16f61f 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "tag.h"
 #include "commit.h"
 #include "tree.h"
@@ -77,10 +78,19 @@ static void update_candidates(struct disambiguate_state *ds, const struct object
        /* otherwise, current can be discarded and candidate is still good */
 }
 
+static int append_loose_object(const struct object_id *oid, const char *path,
+                              void *data)
+{
+       oid_array_append(data, oid);
+       return 0;
+}
+
+static int match_sha(unsigned, const unsigned char *, const unsigned char *);
+
 static void find_short_object_filename(struct disambiguate_state *ds)
 {
+       int subdir_nr = ds->bin_pfx.hash[0];
        struct alternate_object_database *alt;
-       char hex[GIT_MAX_HEXSZ];
        static struct alternate_object_database *fakeent;
 
        if (!fakeent) {
@@ -95,29 +105,29 @@ static void find_short_object_filename(struct disambiguate_state *ds)
        }
        fakeent->next = alt_odb_list;
 
-       xsnprintf(hex, sizeof(hex), "%.2s", ds->hex_pfx);
        for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
-               struct strbuf *buf = alt_scratch_buf(alt);
-               struct dirent *de;
-               DIR *dir;
-
-               strbuf_addf(buf, "%.2s/", ds->hex_pfx);
-               dir = opendir(buf->buf);
-               if (!dir)
-                       continue;
+               int pos;
 
-               while (!ds->ambiguous && (de = readdir(dir)) != NULL) {
-                       struct object_id oid;
+               if (!alt->loose_objects_subdir_seen[subdir_nr]) {
+                       struct strbuf *buf = alt_scratch_buf(alt);
+                       for_each_file_in_obj_subdir(subdir_nr, buf,
+                                                   append_loose_object,
+                                                   NULL, NULL,
+                                                   &alt->loose_objects_cache);
+                       alt->loose_objects_subdir_seen[subdir_nr] = 1;
+               }
 
-                       if (strlen(de->d_name) != GIT_SHA1_HEXSZ - 2)
-                               continue;
-                       if (memcmp(de->d_name, ds->hex_pfx + 2, ds->len - 2))
-                               continue;
-                       memcpy(hex + 2, de->d_name, GIT_SHA1_HEXSZ - 2);
-                       if (!get_oid_hex(hex, &oid))
-                               update_candidates(ds, &oid);
+               pos = oid_array_lookup(&alt->loose_objects_cache, &ds->bin_pfx);
+               if (pos < 0)
+                       pos = -1 - pos;
+               while (!ds->ambiguous && pos < alt->loose_objects_cache.nr) {
+                       const struct object_id *oid;
+                       oid = alt->loose_objects_cache.oid + pos;
+                       if (!match_sha(ds->len, ds->bin_pfx.hash, oid->hash))
+                               break;
+                       update_candidates(ds, oid);
+                       pos++;
                }
-               closedir(dir);
        }
 }
 
diff --git a/sha1collisiondetection b/sha1collisiondetection
new file mode 160000 (submodule)
index 0000000..19d97bf
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 19d97bf5af05312267c2e874ee6bcf584d9e9681
index facea1bb560b57bbe7419dd1cce49f6b1172ddca..25eded1399a8c3ae1532074ccdd388b24e660071 100644 (file)
@@ -10,6 +10,9 @@
 #include <memory.h>
 #include <stdio.h>
 #include <stdlib.h>
+#ifdef __unix__
+#include <sys/types.h> /* make sure macros like _BIG_ENDIAN visible */
+#endif
 #endif
 
 #ifdef SHA1DC_CUSTOM_INCLUDE_SHA1_C
 #include "sha1.h"
 #include "ubc_check.h"
 
+#if (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \
+     defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__)  || \
+     defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || \
+     defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || \
+     defined(__386) || defined(_M_X64) || defined(_M_AMD64))
+#define SHA1DC_ON_INTEL_LIKE_PROCESSOR
+#endif
 
 /*
    Because Little-Endian architectures are most common,
    If you are compiling on a big endian platform and your compiler does not define one of these,
    you will have to add whatever macros your tool chain defines to indicate Big-Endianness.
  */
-#ifdef SHA1DC_BIGENDIAN
-#undef SHA1DC_BIGENDIAN
-#endif
 
-#if (defined(_BYTE_ORDER) || defined(__BYTE_ORDER) || defined(__BYTE_ORDER__))
-
-#if ((defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN)) || \
-     (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || \
-     (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)) )
+#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
+/*
+ * Should detect Big Endian under GCC since at least 4.6.0 (gcc svn
+ * rev #165881). See
+ * https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
+ *
+ * This also works under clang since 3.2, it copied the GCC-ism. See
+ * clang.git's 3b198a97d2 ("Preprocessor: add __BYTE_ORDER__
+ * predefined macro", 2012-07-27)
+ */
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
 #define SHA1DC_BIGENDIAN
 #endif
 
-#else
-
-#if (defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN) || defined(__BIG_ENDIAN__) || \
-     defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
-     defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || \
-     defined(__sparc))
+/* Not under GCC-alike */
+#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN)
+/*
+ * Should detect Big Endian under glibc.git since 14245eb70e ("entered
+ * into RCS", 1992-11-25). Defined in <endian.h> which will have been
+ * brought in by standard headers. See glibc.git and
+ * https://sourceforge.net/p/predef/wiki/Endianness/
+ */
+#if __BYTE_ORDER == __BIG_ENDIAN
 #define SHA1DC_BIGENDIAN
 #endif
 
+/* Not under GCC-alike or glibc */
+#elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
+/*
+ * *BSD and newlib (embeded linux, cygwin, etc).
+ * the defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) part prevents
+ * this condition from matching with Solaris/sparc.
+ * (Solaris defines only one endian macro)
+ */
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define SHA1DC_BIGENDIAN
 #endif
 
+/* Not under GCC-alike or glibc or *BSD or newlib */
+#elif (defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
+       defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || \
+       defined(__sparc))
+/*
+ * Should define Big Endian for a whitelist of known processors. See
+ * https://sourceforge.net/p/predef/wiki/Endianness/ and
+ * http://www.oracle.com/technetwork/server-storage/solaris/portingtosolaris-138514.html
+ */
+#define SHA1DC_BIGENDIAN
+
+/* Not under GCC-alike or glibc or *BSD or newlib or <processor whitelist> */
+#elif defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR)
+/*
+ * As a last resort before we do anything else we're not 100% sure
+ * about below, we blacklist specific processors here. We could add
+ * more, see e.g. https://wiki.debian.org/ArchitectureSpecificsMemo
+ */
+#else /* Not under GCC-alike or glibc or *BSD or newlib or <processor whitelist>  or <processor blacklist> */
+
+/* We do nothing more here for now */
+/*#error "Uncomment this to see if you fall through all the detection"*/
+
+#endif /* Big Endian detection */
+
 #if (defined(SHA1DC_FORCE_LITTLEENDIAN) && defined(SHA1DC_BIGENDIAN))
 #undef SHA1DC_BIGENDIAN
 #endif
 #endif
 /*ENDIANNESS SELECTION*/
 
-#if (defined SHA1DC_FORCE_UNALIGNED_ACCESS || \
-     defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \
-     defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__)  || \
-     defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || \
-     defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || \
-     defined(__386) || defined(_M_X64) || defined(_M_AMD64))
-
+#if defined(SHA1DC_FORCE_UNALIGNED_ACCESS) || defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR)
 #define SHA1DC_ALLOW_UNALIGNED_ACCESS
-
 #endif /*UNALIGNMENT DETECTION*/
 
 
@@ -918,7 +962,7 @@ static void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], co
 
 #ifdef _MSC_VER
 #pragma warning(push)
-#pragma warning(disable: 4127)  /* Complier complains about the checks in the above macro being constant. */
+#pragma warning(disable: 4127)  /* Compiler complains about the checks in the above macro being constant. */
 #endif
 
 #ifdef DOSTORESTATE0
index 49bd197f715ae783d7fdbe8e1d638a1bcac0073c..83e39ec8d7739816188ba909a4cb9da302d48f73 100644 (file)
@@ -73,17 +73,10 @@ void move_cache_to_base_index(struct index_state *istate)
        int i;
 
        /*
-        * If "si" is shared with another index_state (e.g. by
-        * unpack-trees code), we will need to duplicate split_index
-        * struct. It's not happening now though, luckily.
+        * do not delete old si->base, its index entries may be shared
+        * with istate->cache[]. Accept a bit of leaking here because
+        * this code is only used by short-lived update-index.
         */
-       assert(si->refcount <= 1);
-
-       unshare_split_index(istate, 0);
-       if (si->base) {
-               discard_index(si->base);
-               free(si->base);
-       }
        si->base = xcalloc(1, sizeof(*si->base));
        si->base->version = istate->version;
        /* zero timestamp disables racy test in ce_write_index() */
@@ -174,10 +167,9 @@ void merge_base_index(struct index_state *istate)
 
        ewah_free(si->delete_bitmap);
        ewah_free(si->replace_bitmap);
-       free(si->saved_cache);
+       FREE_AND_NULL(si->saved_cache);
        si->delete_bitmap  = NULL;
        si->replace_bitmap = NULL;
-       si->saved_cache    = NULL;
        si->saved_cache_nr = 0;
 }
 
@@ -282,41 +274,11 @@ void finish_writing_split_index(struct index_state *istate)
        istate->cache_nr = si->saved_cache_nr;
 }
 
-void unshare_split_index(struct index_state *istate, int discard)
-{
-       struct split_index *si = istate->split_index;
-       int i;
-
-       if (!si || !si->base)
-               return;
-
-       for (i = 0; i < istate->cache_nr; i++) {
-               struct cache_entry *ce = istate->cache[i];
-               struct cache_entry *new = NULL;
-
-               if (!ce->index ||
-                   ce->index > si->base->cache_nr ||
-                   ce != si->base->cache[ce->index - 1])
-                       continue;
-
-               if (!discard) {
-                       int len = ce_namelen(ce);
-                       new = xcalloc(1, cache_entry_size(len));
-                       copy_cache_entry(new, ce);
-                       memcpy(new->name, ce->name, len);
-                       new->index = 0;
-               }
-               istate->cache[i] = new;
-       }
-}
-
-
 void discard_split_index(struct index_state *istate)
 {
        struct split_index *si = istate->split_index;
        if (!si)
                return;
-       unshare_split_index(istate, 0);
        istate->split_index = NULL;
        si->refcount--;
        if (si->refcount)
@@ -365,8 +327,14 @@ void add_split_index(struct index_state *istate)
 
 void remove_split_index(struct index_state *istate)
 {
-       if (!istate->split_index)
-               return;
-       discard_split_index(istate);
-       istate->cache_changed |= SOMETHING_CHANGED;
+       if (istate->split_index) {
+               /*
+                * can't discard_split_index(&the_index); because that
+                * will destroy split_index->base->cache[], which may
+                * be shared with the_index.cache[]. So yeah we're
+                * leaking a bit here.
+                */
+               istate->split_index = NULL;
+               istate->cache_changed |= SOMETHING_CHANGED;
+       }
 }
index 65c0f09b2bd413e091cc65ef2f0d3a2d92aeb858..df91c1bda8117fe7d0f25a0aaedce79370801ce0 100644 (file)
@@ -33,6 +33,5 @@ void finish_writing_split_index(struct index_state *istate);
 void discard_split_index(struct index_state *istate);
 void add_split_index(struct index_state *istate);
 void remove_split_index(struct index_state *istate);
-void unshare_split_index(struct index_state *istate, int discard);
 
 #endif
index be3b9e37b1d969e86e913cc69ccab935f516a063..89d22e3b0903a220fa958b8d912607828ab2a9ba 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -204,13 +204,6 @@ void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2)
        strbuf_setlen(sb, sb->len + sb2->len);
 }
 
-void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
-{
-       strbuf_grow(sb, len);
-       memcpy(sb->buf + sb->len, sb->buf + pos, len);
-       strbuf_setlen(sb, sb->len + len);
-}
-
 void strbuf_addchars(struct strbuf *sb, int c, size_t n)
 {
        strbuf_grow(sb, n);
@@ -786,7 +779,7 @@ char *xstrfmt(const char *fmt, ...)
 }
 
 void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm,
-                    int tz_offset, const char *tz_name)
+                    int tz_offset, int suppress_tz_name)
 {
        struct strbuf munged_fmt = STRBUF_INIT;
        size_t hint = 128;
@@ -815,8 +808,7 @@ void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm,
                        fmt++;
                        break;
                case 'Z':
-                       if (tz_name) {
-                               strbuf_addstr(&munged_fmt, tz_name);
+                       if (suppress_tz_name) {
                                fmt++;
                                break;
                        }
index 4559035c47268c0603119b90c7278c08c6b99a09..2075384e0b2df97a6d113acebcbcdcc853237166 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -263,12 +263,6 @@ static inline void strbuf_addstr(struct strbuf *sb, const char *s)
  */
 extern void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2);
 
-/**
- * Copy part of the buffer from a given position till a given length to the
- * end of the buffer.
- */
-extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
-
 /**
  * This function can be used to expand a format string containing
  * placeholders. To that end, it parses the string and calls the specified
@@ -340,14 +334,15 @@ extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);
 
 /**
  * Add the time specified by `tm`, as formatted by `strftime`.
- * `tz_name` is used to expand %Z internally unless it's NULL.
  * `tz_offset` is in decimal hhmm format, e.g. -600 means six hours west
  * of Greenwich, and it's used to expand %z internally.  However, tokens
  * with modifiers (e.g. %Ez) are passed to `strftime`.
+ * `suppress_tz_name`, when set, expands %Z internally to the empty
+ * string rather than passing it to `strftime`.
  */
 extern void strbuf_addftime(struct strbuf *sb, const char *fmt,
                            const struct tm *tm, int tz_offset,
-                           const char *tz_name);
+                           int suppress_tz_name);
 
 /**
  * Read a given size of data from a FILE* pointer to the buffer.
index 4f58491ddb0705ab56e238006199d35db19dfb5a..37cfcceb950b1777b46abecd5415196c76e11826 100644 (file)
@@ -1,4 +1,6 @@
 #include "cache.h"
+#include "repository.h"
+#include "config.h"
 #include "submodule-config.h"
 #include "submodule.h"
 #include "strbuf.h"
@@ -14,6 +16,7 @@
 struct submodule_cache {
        struct hashmap for_path;
        struct hashmap for_name;
+       unsigned initialized:1;
 };
 
 /*
@@ -30,9 +33,6 @@ enum lookup_type {
        lookup_path
 };
 
-static struct submodule_cache the_submodule_cache;
-static int is_cache_init;
-
 static int config_path_cmp(const struct submodule_entry *a,
                           const struct submodule_entry *b,
                           const void *unused)
@@ -49,10 +49,16 @@ static int config_name_cmp(const struct submodule_entry *a,
               hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);
 }
 
-static void cache_init(struct submodule_cache *cache)
+static struct submodule_cache *submodule_cache_alloc(void)
+{
+       return xcalloc(1, sizeof(struct submodule_cache));
+}
+
+static void submodule_cache_init(struct submodule_cache *cache)
 {
        hashmap_init(&cache->for_path, (hashmap_cmp_fn) config_path_cmp, 0);
        hashmap_init(&cache->for_name, (hashmap_cmp_fn) config_name_cmp, 0);
+       cache->initialized = 1;
 }
 
 static void free_one_config(struct submodule_entry *entry)
@@ -64,11 +70,14 @@ static void free_one_config(struct submodule_entry *entry)
        free(entry->config);
 }
 
-static void cache_free(struct submodule_cache *cache)
+static void submodule_cache_clear(struct submodule_cache *cache)
 {
        struct hashmap_iter iter;
        struct submodule_entry *entry;
 
+       if (!cache->initialized)
+               return;
+
        /*
         * We iterate over the name hash here to be symmetric with the
         * allocation of struct submodule entries. Each is allocated by
@@ -80,6 +89,13 @@ static void cache_free(struct submodule_cache *cache)
 
        hashmap_free(&cache->for_path, 1);
        hashmap_free(&cache->for_name, 1);
+       cache->initialized = 0;
+}
+
+void submodule_cache_free(struct submodule_cache *cache)
+{
+       submodule_cache_clear(cache);
+       free(cache);
 }
 
 static unsigned int hash_sha1_string(const unsigned char *sha1,
@@ -493,43 +509,62 @@ static const struct submodule *config_from(struct submodule_cache *cache,
        return submodule;
 }
 
-static void ensure_cache_init(void)
+static void submodule_cache_check_init(struct repository *repo)
 {
-       if (is_cache_init)
+       if (repo->submodule_cache && repo->submodule_cache->initialized)
                return;
 
-       cache_init(&the_submodule_cache);
-       is_cache_init = 1;
+       if (!repo->submodule_cache)
+               repo->submodule_cache = submodule_cache_alloc();
+
+       submodule_cache_init(repo->submodule_cache);
 }
 
-int parse_submodule_config_option(const char *var, const char *value)
+int submodule_config_option(struct repository *repo,
+                           const char *var, const char *value)
 {
        struct parse_config_parameter parameter;
-       parameter.cache = &the_submodule_cache;
+
+       submodule_cache_check_init(repo);
+
+       parameter.cache = repo->submodule_cache;
        parameter.treeish_name = NULL;
        parameter.gitmodules_sha1 = null_sha1;
        parameter.overwrite = 1;
 
-       ensure_cache_init();
        return parse_config(var, value, &parameter);
 }
 
+int parse_submodule_config_option(const char *var, const char *value)
+{
+       return submodule_config_option(the_repository, var, value);
+}
+
 const struct submodule *submodule_from_name(const unsigned char *treeish_name,
                const char *name)
 {
-       ensure_cache_init();
-       return config_from(&the_submodule_cache, treeish_name, name, lookup_name);
+       submodule_cache_check_init(the_repository);
+       return config_from(the_repository->submodule_cache, treeish_name, name, lookup_name);
 }
 
 const struct submodule *submodule_from_path(const unsigned char *treeish_name,
                const char *path)
 {
-       ensure_cache_init();
-       return config_from(&the_submodule_cache, treeish_name, path, lookup_path);
+       submodule_cache_check_init(the_repository);
+       return config_from(the_repository->submodule_cache, treeish_name, path, lookup_path);
+}
+
+const struct submodule *submodule_from_cache(struct repository *repo,
+                                            const unsigned char *treeish_name,
+                                            const char *key)
+{
+       submodule_cache_check_init(repo);
+       return config_from(repo->submodule_cache, treeish_name,
+                          key, lookup_path);
 }
 
 void submodule_free(void)
 {
-       cache_free(&the_submodule_cache);
-       is_cache_init = 0;
+       if (the_repository->submodule_cache)
+               submodule_cache_clear(the_repository->submodule_cache);
 }
index d434ecdb45c074dd386405f20ed73ac1c8b646bd..bc45a25e850eb600eb9883d83d1ec1d3fc08db4a 100644 (file)
@@ -22,14 +22,24 @@ struct submodule {
        int recommend_shallow;
 };
 
+struct submodule_cache;
+struct repository;
+
+extern void submodule_cache_free(struct submodule_cache *cache);
+
 extern int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
 extern int parse_update_recurse_submodules_arg(const char *opt, const char *arg);
 extern int parse_push_recurse_submodules_arg(const char *opt, const char *arg);
 extern int parse_submodule_config_option(const char *var, const char *value);
+extern int submodule_config_option(struct repository *repo,
+                                  const char *var, const char *value);
 extern const struct submodule *submodule_from_name(
                const unsigned char *commit_or_tree, const char *name);
 extern const struct submodule *submodule_from_path(
                const unsigned char *commit_or_tree, const char *path);
+extern const struct submodule *submodule_from_cache(struct repository *repo,
+                                                   const unsigned char *treeish_name,
+                                                   const char *key);
 extern int gitmodule_sha1_from_commit(const unsigned char *commit_sha1,
                                      unsigned char *gitmodules_sha1,
                                      struct strbuf *rev);
index 1b8a3b575db6c85a42e9c9e285617113ecac4a84..da2b4848791382b30147cd8fe921996cfb8a92a7 100644 (file)
@@ -1,4 +1,6 @@
 #include "cache.h"
+#include "repository.h"
+#include "config.h"
 #include "submodule-config.h"
 #include "submodule.h"
 #include "dir.h"
@@ -254,6 +256,20 @@ void gitmodules_config(void)
        }
 }
 
+static int gitmodules_cb(const char *var, const char *value, void *data)
+{
+       struct repository *repo = data;
+       return submodule_config_option(repo, var, value);
+}
+
+void repo_read_gitmodules(struct repository *repo)
+{
+       char *gitmodules_path = repo_worktree_path(repo, ".gitmodules");
+
+       git_config_from_file(gitmodules_cb, gitmodules_path, repo);
+       free(gitmodules_path);
+}
+
 void gitmodules_config_sha1(const unsigned char *commit_sha1)
 {
        struct strbuf rev = STRBUF_INIT;
@@ -267,21 +283,17 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)
 }
 
 /*
- * NEEDSWORK: With the addition of different configuration options to determine
- * if a submodule is of interests, the validity of this function's name comes
- * into question.  Once the dust has settled and more concrete terminology is
- * decided upon, come up with a more proper name for this function.  One
- * potential candidate could be 'is_submodule_active()'.
- *
  * Determine if a submodule has been initialized at a given 'path'
  */
-int is_submodule_initialized(const char *path)
+int is_submodule_active(struct repository *repo, const char *path)
 {
        int ret = 0;
        char *key = NULL;
        char *value = NULL;
        const struct string_list *sl;
-       const struct submodule *module = submodule_from_path(null_sha1, path);
+       const struct submodule *module;
+
+       module = submodule_from_cache(repo, null_sha1, path);
 
        /* early return if there isn't a path->module mapping */
        if (!module)
@@ -289,14 +301,14 @@ int is_submodule_initialized(const char *path)
 
        /* submodule.<name>.active is set */
        key = xstrfmt("submodule.%s.active", module->name);
-       if (!git_config_get_bool(key, &ret)) {
+       if (!repo_config_get_bool(repo, key, &ret)) {
                free(key);
                return ret;
        }
        free(key);
 
        /* submodule.active is set */
-       sl = git_config_get_value_multi("submodule.active");
+       sl = repo_config_get_value_multi(repo, "submodule.active");
        if (sl) {
                struct pathspec ps;
                struct argv_array args = ARGV_ARRAY_INIT;
@@ -316,7 +328,7 @@ int is_submodule_initialized(const char *path)
 
        /* fallback to checking if the URL is set */
        key = xstrfmt("submodule.%s.url", module->name);
-       ret = !git_config_get_string(key, &value);
+       ret = !repo_config_get_string(repo, key, &value);
 
        free(value);
        free(key);
@@ -845,9 +857,9 @@ static int submodule_has_commits(const char *path, struct oid_array *commits)
        int has_commit = 1;
 
        /*
-        * Perform a cheap, but incorrect check for the existance of 'commits'.
+        * Perform a cheap, but incorrect check for the existence of 'commits'.
         * This is done by adding the submodule's object store to the in-core
-        * object store, and then querying for each commit's existance.  If we
+        * object store, and then querying for each commit's existence.  If we
         * do not have the commit object anywhere, there is no chance we have
         * it in the object store of the correct submodule and have it
         * reachable from a ref, so we can fail early without spawning rev-list
@@ -1516,7 +1528,7 @@ int submodule_move_head(const char *path,
        const struct submodule *sub;
        int *error_code_ptr, error_code;
 
-       if (!is_submodule_initialized(path))
+       if (!is_submodule_active(the_repository, path))
                return 0;
 
        if (flags & SUBMODULE_MOVE_HEAD_FORCE)
index cbe5c1726f9adab2b032d872d4bd84425e6ce518..623ce6ad7716aa037e2970f6847cc145c41bff69 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef SUBMODULE_H
 #define SUBMODULE_H
 
+struct repository;
 struct diff_options;
 struct argv_array;
 struct oid_array;
@@ -46,8 +47,9 @@ int option_parse_recurse_submodules_worktree_updater(const struct option *opt,
                                                     const char *arg, int unset);
 void load_submodule_cache(void);
 extern void gitmodules_config(void);
+extern void repo_read_gitmodules(struct repository *repo);
 extern void gitmodules_config_sha1(const unsigned char *commit_sha1);
-extern int is_submodule_initialized(const char *path);
+extern int is_submodule_active(struct repository *repo, const char *path);
 /*
  * Determine if a submodule has been populated at a given 'path' by checking if
  * the <path>/.git resolves to a valid git repository.
index 8e3ed6a76cb97831e85152af8e9da21d18ed2fc1..1a7b8bd3d650fe1111c77115d2c68644b6ac9edb 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "string-list.h"
 
 /*
index 4a45a54e92745f1ec0102a01b05b338b846cd1d4..e159c9a127f6854541ab497c8fd4b6efb9d4ea39 100644 (file)
@@ -11,7 +11,7 @@ int cmd_main(int argc, const char **argv)
        result = strcmp_offset(argv[1], argv[2], &offset);
 
        /*
-        * Because differnt CRTs behave differently, only rely on signs
+        * Because different CRTs behave differently, only rely on signs
         * of the result values.
         */
        result = (result < 0 ? -1 :
index 2f144d539a4822619a9383ded2d3adb270484624..c6c57bba0d397e44e8897b05d479a30b53311517 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "submodule-config.h"
 #include "submodule.h"
 
diff --git a/t/perf/p4205-log-pretty-formats.sh b/t/perf/p4205-log-pretty-formats.sh
new file mode 100755 (executable)
index 0000000..7c26f4f
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+test_description='Tests the performance of various pretty format placeholders'
+
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+for format in %H %h %T %t %P %p %h-%h-%h
+do
+       test_perf "log with $format" "
+               git log --format=\"$format\" >/dev/null
+       "
+done
+
+test_done
index 13b7851f7c2feb87f63449d917380452e85c1f84..a37ef0422212eafdae4b4c0fae9e28d4a183117f 100755 (executable)
@@ -703,6 +703,12 @@ test_expect_success 'invalid unit' '
        test_i18ngrep "bad numeric config value .1auto. for .aninvalid.unit. in file .git/config: invalid unit" actual
 '
 
+test_expect_success 'line number is reported correctly' '
+       printf "[bool]\n\tvar\n" >invalid &&
+       test_must_fail git config -f invalid --path bool.var 2>actual &&
+       test_i18ngrep "line 2" actual
+'
+
 test_expect_success 'invalid stdin config' '
        echo "[broken" | test_must_fail git config --list --file - >output 2>&1 &&
        test_i18ngrep "bad config line 1 in standard input" output
index 1312004f8c8ab11b5aafe0eb1f1fb02f1e4f61d5..dfece751b572821464c390ee68f26d91624e2a33 100755 (executable)
@@ -19,10 +19,6 @@ test_expect_success 'shared = 0400 (faulty permission u-w)' '
        )
 '
 
-modebits () {
-       ls -l "$1" | sed -e 's|^\(..........\).*|\1|'
-}
-
 for u in 002 022
 do
        test_expect_success POSIXPERM "shared=1 does not clear bits preset by umask $u" '
@@ -88,7 +84,7 @@ do
 
                rm -f .git/info/refs &&
                git update-server-info &&
-               actual="$(modebits .git/info/refs)" &&
+               actual="$(test_modebits .git/info/refs)" &&
                verbose test "x$actual" = "x-$y"
 
        '
@@ -98,7 +94,7 @@ do
 
                rm -f .git/info/refs &&
                git update-server-info &&
-               actual="$(modebits .git/info/refs)" &&
+               actual="$(test_modebits .git/info/refs)" &&
                verbose test "x$actual" = "x-$x"
 
        '
@@ -111,7 +107,7 @@ test_expect_success POSIXPERM 'info/refs respects umask in unshared repo' '
        umask 002 &&
        git update-server-info &&
        echo "-rw-rw-r--" >expect &&
-       modebits .git/info/refs >actual &&
+       test_modebits .git/info/refs >actual &&
        test_cmp expect actual
 '
 
@@ -177,7 +173,7 @@ test_expect_success POSIXPERM 'remote init does not use config from cwd' '
        umask 0022 &&
        git init --bare child.git &&
        echo "-rw-r--r--" >expect &&
-       modebits child.git/config >actual &&
+       test_modebits child.git/config >actual &&
        test_cmp expect actual
 '
 
@@ -187,7 +183,7 @@ test_expect_success POSIXPERM 're-init respects core.sharedrepository (local)' '
        echo whatever >templates/foo &&
        git init --template=templates &&
        echo "-rw-rw-rw-" >expect &&
-       modebits .git/foo >actual &&
+       test_modebits .git/foo >actual &&
        test_cmp expect actual
 '
 
@@ -198,7 +194,7 @@ test_expect_success POSIXPERM 're-init respects core.sharedrepository (remote)'
        test_path_is_missing child.git/foo &&
        git init --bare --template=../templates child.git &&
        echo "-rw-rw-rw-" >expect &&
-       modebits child.git/foo >actual &&
+       test_modebits child.git/foo >actual &&
        test_cmp expect actual
 '
 
@@ -209,7 +205,7 @@ test_expect_success POSIXPERM 'template can set core.sharedrepository' '
        cp .git/config templates/config &&
        git init --bare --template=../templates child.git &&
        echo "-rw-rw-rw-" >expect &&
-       modebits child.git/HEAD >actual &&
+       test_modebits child.git/HEAD >actual &&
        test_cmp expect actual
 '
 
index e495a616161660bcade644dea42b5c8e53cc64b3..bafed5c9b88481992ca6cf4cd6c13596c7baf16b 100755 (executable)
@@ -226,7 +226,9 @@ test_expect_success 'check line errors for malformed values' '
                br
        EOF
        test_expect_code 128 git br 2>result &&
-       test_i18ngrep "fatal: .*alias\.br.*\.git/config.*line 2" result
+       test_i18ngrep "missing value for .alias\.br" result &&
+       test_i18ngrep "fatal: .*\.git/config" result &&
+       test_i18ngrep "fatal: .*line 2" result
 '
 
 test_expect_success 'error on modifying repo config without repo' '
index adf0bc88ba510f08d9429ae0f2fb2b2d37424ff4..bb89e1a5db293dd886bff9df668bcaf187a58d11 100755 (executable)
@@ -573,7 +573,7 @@ test_expect_success 'fsck --name-objects' '
                remove_object $(git rev-parse julius:caesar.t) &&
                test_must_fail git fsck --name-objects >out &&
                tree=$(git rev-parse --verify julius:) &&
-               grep "$tree (\(refs/heads/master\|HEAD\)@{[0-9]*}:" out
+               egrep "$tree \((refs/heads/master|HEAD)@\{[0-9]*\}:" out
        )
 '
 
index af3ec0da5ac0f5e0f6e19616d9c55b611ba5a701..22f69a410ba8194bbdff70471f5b3e746af116da 100755 (executable)
@@ -370,4 +370,34 @@ test_expect_success 'check splitIndex.sharedIndexExpire set to "never" and "now"
        test $(ls .git/sharedindex.* | wc -l) -le 2
 '
 
+while read -r mode modebits
+do
+       test_expect_success POSIXPERM "split index respects core.sharedrepository $mode" '
+               # Remove existing shared index files
+               git config core.splitIndex false &&
+               git update-index --force-remove one &&
+               rm -f .git/sharedindex.* &&
+               # Create one new shared index file
+               git config core.sharedrepository "$mode" &&
+               git config core.splitIndex true &&
+               : >one &&
+               git update-index --add one &&
+               echo "$modebits" >expect &&
+               test_modebits .git/index >actual &&
+               test_cmp expect actual &&
+               shared=$(ls .git/sharedindex.*) &&
+               case "$shared" in
+               *" "*)
+                       # we have more than one???
+                       false ;;
+               *)
+                       test_modebits "$shared" >actual &&
+                       test_cmp expect actual ;;
+               esac
+       '
+done <<\EOF
+0666 -rw-rw-rw-
+0642 -rw-r---w-
+EOF
+
 test_done
index 84a9028c433c02c72adcdf06222bcb409e2eb683..1bdf38e80dbe5322fc239371eb71b146a40586e0 100755 (executable)
@@ -129,10 +129,10 @@ test_expect_success 'cache-tree does skip dir that becomes empty' '
        )
 '
 
-test_expect_success 'commit: ita entries ignored in empty intial commit check' '
-       git init empty-intial-commit &&
+test_expect_success 'commit: ita entries ignored in empty initial commit check' '
+       git init empty-initial-commit &&
        (
-               cd empty-intial-commit &&
+               cd empty-initial-commit &&
                : >one &&
                git add -N one &&
                test_must_fail git commit -m nothing-new-here
index ebb956fd16ccce2536591da021239453da999140..318b5bce7ebeab2ad96097e992e37867b3a7adb5 100755 (executable)
@@ -135,6 +135,45 @@ test_expect_success '--recurse-submodules and pathspecs setup' '
        test_cmp expect actual
 '
 
+test_expect_success 'inactive submodule' '
+       test_when_finished "git config --bool submodule.submodule.active true" &&
+       test_when_finished "git -C submodule config --bool submodule.subsub.active true" &&
+       git config --bool submodule.submodule.active "false" &&
+
+       cat >expect <<-\EOF &&
+       .gitmodules
+       a
+       b/b
+       h.txt
+       sib/file
+       sub/file
+       submodule
+       EOF
+
+       git ls-files --recurse-submodules >actual &&
+       test_cmp expect actual &&
+
+       git config --bool submodule.submodule.active "true" &&
+       git -C submodule config --bool submodule.subsub.active "false" &&
+
+       cat >expect <<-\EOF &&
+       .gitmodules
+       a
+       b/b
+       h.txt
+       sib/file
+       sub/file
+       submodule/.gitmodules
+       submodule/c
+       submodule/f.TXT
+       submodule/g.txt
+       submodule/subsub
+       EOF
+
+       git ls-files --recurse-submodules >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success '--recurse-submodules and pathspecs' '
        cat >expect <<-\EOF &&
        h.txt
index 7ca69f4bed6438009808f35c2e212b269bffcfb0..163a14a1c2cb77b2a644a7342fd554940f7dd2e3 100755 (executable)
@@ -82,6 +82,7 @@ match 1 0 'foo/bar' 'foo/**/bar'
 match 1 0 'foo/bar' 'foo/**/**/bar'
 match 0 0 'foo/bar' 'foo?bar'
 match 0 0 'foo/bar' 'foo[/]bar'
+match 0 0 'foo/bar' 'foo[^a-z]bar'
 match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
 match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
 match 1 0 'foo' '**/foo'
@@ -225,6 +226,7 @@ pathmatch 0 foo/bba/arr 'foo/*z'
 pathmatch 0 foo/bba/arr 'foo/**z'
 pathmatch 1 foo/bar 'foo?bar'
 pathmatch 1 foo/bar 'foo[/]bar'
+pathmatch 1 foo/bar 'foo[^a-z]bar'
 pathmatch 0 foo '*/*/*'
 pathmatch 0 foo/bar '*/*/*'
 pathmatch 1 foo/bba/arr '*/*/*'
@@ -233,7 +235,7 @@ pathmatch 1 abcXdefXghi '*X*i'
 pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
 pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
 
-# Case-sensitivy features
+# Case-sensitivity features
 match 0 x 'a' '[A-Z]'
 match 1 x 'A' '[A-Z]'
 match 0 x 'A' '[a-z]'
index 5bd0275930b715c25507fc9744c8946e7f73900b..37821d245433f757fa13f0a3e27da0312bebb7db 100755 (executable)
@@ -169,6 +169,13 @@ test_expect_success 'reflog for the branch shows state before rebase' '
        test $(git rev-parse branch1@{1}) = $(git rev-parse original-branch1)
 '
 
+test_expect_success 'reflog for the branch shows correct finish message' '
+       printf "rebase -i (finish): refs/heads/branch1 onto %s\n" \
+               "$(git rev-parse branch2)" >expected &&
+       git log -g --pretty=%gs -1 refs/heads/branch1 >actual &&
+       test_cmp expected actual
+'
+
 test_expect_success 'exchange two commits' '
        set_fake_editor &&
        FAKE_LINES="2 1" git rebase -i HEAD~2 &&
index ab8a63e8d6dc643b28eb0c74ba3f032b7532226f..e24370066012fcb441aa0c59ff9c0c34e1d37e9c 100755 (executable)
@@ -33,7 +33,123 @@ test_expect_success setup '
        git commit -m "related commit"
 '
 
-testrebase() {
+create_expected_success_am () {
+       cat >expected <<-EOF
+       $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+       HEAD is now at $(git rev-parse --short feature-branch) third commit
+       First, rewinding head to replay your work on top of it...
+       Applying: second commit
+       Applying: third commit
+       Applied autostash.
+       EOF
+}
+
+create_expected_success_interactive () {
+       q_to_cr >expected <<-EOF
+       $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+       HEAD is now at $(git rev-parse --short feature-branch) third commit
+       Rebasing (1/2)QRebasing (2/2)QApplied autostash.
+       Successfully rebased and updated refs/heads/rebased-feature-branch.
+       EOF
+}
+
+create_expected_success_merge () {
+       cat >expected <<-EOF
+       $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+       HEAD is now at $(git rev-parse --short feature-branch) third commit
+       First, rewinding head to replay your work on top of it...
+       Merging unrelated-onto-branch with HEAD~1
+       Merging:
+       $(git rev-parse --short unrelated-onto-branch) unrelated commit
+       $(git rev-parse --short feature-branch^) second commit
+       found 1 common ancestor:
+       $(git rev-parse --short feature-branch~2) initial commit
+       [detached HEAD $(git rev-parse --short rebased-feature-branch~1)] second commit
+        Author: A U Thor <author@example.com>
+        Date: Thu Apr 7 15:14:13 2005 -0700
+        2 files changed, 2 insertions(+)
+        create mode 100644 file1
+        create mode 100644 file2
+       Committed: 0001 second commit
+       Merging unrelated-onto-branch with HEAD~0
+       Merging:
+       $(git rev-parse --short rebased-feature-branch~1) second commit
+       $(git rev-parse --short feature-branch) third commit
+       found 1 common ancestor:
+       $(git rev-parse --short feature-branch~1) second commit
+       [detached HEAD $(git rev-parse --short rebased-feature-branch)] third commit
+        Author: A U Thor <author@example.com>
+        Date: Thu Apr 7 15:15:13 2005 -0700
+        1 file changed, 1 insertion(+)
+        create mode 100644 file3
+       Committed: 0002 third commit
+       All done.
+       Applied autostash.
+       EOF
+}
+
+create_expected_failure_am () {
+       cat >expected <<-EOF
+       $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+       HEAD is now at $(git rev-parse --short feature-branch) third commit
+       First, rewinding head to replay your work on top of it...
+       Applying: second commit
+       Applying: third commit
+       Applying autostash resulted in conflicts.
+       Your changes are safe in the stash.
+       You can run "git stash pop" or "git stash drop" at any time.
+       EOF
+}
+
+create_expected_failure_interactive () {
+       q_to_cr >expected <<-EOF
+       $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+       HEAD is now at $(git rev-parse --short feature-branch) third commit
+       Rebasing (1/2)QRebasing (2/2)QApplying autostash resulted in conflicts.
+       Your changes are safe in the stash.
+       You can run "git stash pop" or "git stash drop" at any time.
+       Successfully rebased and updated refs/heads/rebased-feature-branch.
+       EOF
+}
+
+create_expected_failure_merge () {
+       cat >expected <<-EOF
+       $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+       HEAD is now at $(git rev-parse --short feature-branch) third commit
+       First, rewinding head to replay your work on top of it...
+       Merging unrelated-onto-branch with HEAD~1
+       Merging:
+       $(git rev-parse --short unrelated-onto-branch) unrelated commit
+       $(git rev-parse --short feature-branch^) second commit
+       found 1 common ancestor:
+       $(git rev-parse --short feature-branch~2) initial commit
+       [detached HEAD $(git rev-parse --short rebased-feature-branch~1)] second commit
+        Author: A U Thor <author@example.com>
+        Date: Thu Apr 7 15:14:13 2005 -0700
+        2 files changed, 2 insertions(+)
+        create mode 100644 file1
+        create mode 100644 file2
+       Committed: 0001 second commit
+       Merging unrelated-onto-branch with HEAD~0
+       Merging:
+       $(git rev-parse --short rebased-feature-branch~1) second commit
+       $(git rev-parse --short feature-branch) third commit
+       found 1 common ancestor:
+       $(git rev-parse --short feature-branch~1) second commit
+       [detached HEAD $(git rev-parse --short rebased-feature-branch)] third commit
+        Author: A U Thor <author@example.com>
+        Date: Thu Apr 7 15:15:13 2005 -0700
+        1 file changed, 1 insertion(+)
+        create mode 100644 file3
+       Committed: 0002 third commit
+       All done.
+       Applying autostash resulted in conflicts.
+       Your changes are safe in the stash.
+       You can run "git stash pop" or "git stash drop" at any time.
+       EOF
+}
+
+testrebase () {
        type=$1
        dotest=$2
 
@@ -51,14 +167,20 @@ testrebase() {
                test_config rebase.autostash true &&
                git reset --hard &&
                git checkout -b rebased-feature-branch feature-branch &&
-               test_when_finished git branch -D rebased-feature-branch &&
                echo dirty >>file3 &&
-               git rebase$type unrelated-onto-branch &&
+               git rebase$type unrelated-onto-branch >actual 2>&1 &&
                grep unrelated file4 &&
                grep dirty file3 &&
                git checkout feature-branch
        '
 
+       test_expect_success "rebase$type --autostash: check output" '
+               test_when_finished git branch -D rebased-feature-branch &&
+               suffix=${type#\ --} && suffix=${suffix:-am} &&
+               create_expected_success_$suffix &&
+               test_i18ncmp expected actual
+       '
+
        test_expect_success "rebase$type: dirty index, non-conflicting rebase" '
                test_config rebase.autostash true &&
                git reset --hard &&
@@ -137,10 +259,9 @@ testrebase() {
                test_config rebase.autostash true &&
                git reset --hard &&
                git checkout -b rebased-feature-branch feature-branch &&
-               test_when_finished git branch -D rebased-feature-branch &&
                echo dirty >file4 &&
                git add file4 &&
-               git rebase$type unrelated-onto-branch &&
+               git rebase$type unrelated-onto-branch >actual 2>&1 &&
                test_path_is_missing $dotest &&
                git reset --hard &&
                grep unrelated file4 &&
@@ -149,6 +270,13 @@ testrebase() {
                git stash pop &&
                grep dirty file4
        '
+
+       test_expect_success "rebase$type: check output with conflicting stash" '
+               test_when_finished git branch -D rebased-feature-branch &&
+               suffix=${type#\ --} && suffix=${suffix:-am} &&
+               create_expected_failure_$suffix &&
+               test_i18ncmp expected actual
+       '
 }
 
 test_expect_success "rebase: fast-forward rebase" '
index 2ecb43a61652032862d5a264ede8af473ef345e1..2f3e7cea64e897299d87196135032de22050354b 100755 (executable)
@@ -477,4 +477,12 @@ test_expect_success 'add -p does not expand argument lists' '
        ! grep not-changed trace.out
 '
 
+test_expect_success 'hunk-editing handles custom comment char' '
+       git reset --hard &&
+       echo change >>file &&
+       test_config core.commentChar "\$" &&
+       echo e | GIT_EDITOR=true git add -p &&
+       git diff --exit-code
+'
+
 test_done
index 2d9731b52d6b880d742e4722ddcc404c59e5f1bd..058ee0829ded8163f99325494f326ef6609fee06 100755 (executable)
@@ -430,9 +430,11 @@ test_expect_success 'deleted submodule' '
        test_cmp expected actual
 '
 
-test_create_repo sm2 &&
-head7=$(add_file sm2 foo8 foo9) &&
-git add sm2
+test_expect_success 'create second submodule' '
+       test_create_repo sm2 &&
+       head7=$(add_file sm2 foo8 foo9) &&
+       git add sm2
+'
 
 test_expect_success 'multiple submodules' '
        git diff-index -p --submodule=log HEAD >actual &&
index 33ec26d7557ab49888584396c14a1b58564c2dcd..4b168d0ed7ff2bbb1d93895de7fdf3f14bfe334e 100755 (executable)
@@ -643,9 +643,11 @@ test_expect_success 'deleted submodule' '
        test_cmp expected actual
 '
 
-test_create_repo sm2 &&
-head7=$(add_file sm2 foo8 foo9) &&
-git add sm2
+test_expect_success 'create second submodule' '
+       test_create_repo sm2 &&
+       head7=$(add_file sm2 foo8 foo9) &&
+       git add sm2
+'
 
 test_expect_success 'multiple submodules' '
        git diff-index -p --submodule=diff HEAD >actual &&
index c268298eaf5672c649ca3e4815dc4f43d71efece..5cdd76dfa726d32226b1dd625d21d6280125afb7 100755 (executable)
@@ -13,7 +13,9 @@ test_expect_success setup '
        echo modified >file &&
        git diff --stat -p >patch-0.txt &&
        chmod +x file &&
-       git diff --stat -p >patch-1.txt
+       git diff --stat -p >patch-1.txt &&
+       sed "s/^\(new mode \).*/\1/" <patch-1.txt >patch-empty-mode.txt &&
+       sed "s/^\(new mode \).*/\1garbage/" <patch-1.txt >patch-bogus-mode.txt
 '
 
 test_expect_success FILEMODE 'same mode (no index)' '
@@ -59,4 +61,16 @@ test_expect_success FILEMODE 'mode update (index only)' '
        git ls-files -s file | grep "^100755"
 '
 
+test_expect_success FILEMODE 'empty mode is rejected' '
+       git reset --hard &&
+       test_must_fail git apply patch-empty-mode.txt 2>err &&
+       test_i18ngrep "invalid mode" err
+'
+
+test_expect_success FILEMODE 'bogus mode is rejected' '
+       git reset --hard &&
+       test_must_fail git apply patch-bogus-mode.txt 2>err &&
+       test_i18ngrep "invalid mode" err
+'
+
 test_done
index 2ecb4216b7179ef836836d90a5f76f5e4349ca23..c5ed3b17c4a1196e154affc346b5fd3d4e0a7abf 100755 (executable)
@@ -35,4 +35,28 @@ test_expect_success 'apply diff with inconsistent filenames in headers' '
        test_i18ngrep "inconsistent old filename" err
 '
 
+test_expect_success 'apply diff with new filename missing from headers' '
+       cat >missing_new_filename.diff <<-\EOF &&
+       diff --git a/f b/f
+       index 0000000..d00491f
+       --- a/f
+       @@ -0,0 +1 @@
+       +1
+       EOF
+       test_must_fail git apply missing_new_filename.diff 2>err &&
+       test_i18ngrep "lacks filename information" err
+'
+
+test_expect_success 'apply diff with old filename missing from headers' '
+       cat >missing_old_filename.diff <<-\EOF &&
+       diff --git a/f b/f
+       index d00491f..0000000
+       +++ b/f
+       @@ -1 +0,0 @@
+       -1
+       EOF
+       test_must_fail git apply missing_old_filename.diff 2>err &&
+       test_i18ngrep "lacks filename information" err
+'
+
 test_done
index 4b0a374b63f4128405c88fdb2410fb679bdd06a1..6d9287231826ece18873b531186907cd75ef7461 100755 (executable)
@@ -29,4 +29,22 @@ test_expect_success 'apply exits non-zero with no-op patch' '
        test_must_fail git apply --check input
 '
 
+test_expect_success 'invalid combination: create and copy' '
+       test_must_fail git apply --check - <<-\EOF
+       diff --git a/1 b/2
+       new file mode 100644
+       copy from 1
+       copy to 2
+       EOF
+'
+
+test_expect_success 'invalid combination: create and rename' '
+       test_must_fail git apply --check - <<-\EOF
+       diff --git a/1 b/2
+       new file mode 100644
+       rename from 1
+       rename to 2
+       EOF
+'
+
 test_done
index e01a8f6ac9c0f2557f075979bc81d9e948e29f35..7f90f58c03e6fff921e65f9b4138de9dcf972941 100755 (executable)
@@ -37,7 +37,7 @@ count_expand ()
 
        # Prefix the output with the command line arguments, and
        # replace SP with a dot both in the expecte and actual output
-       # so that test_cmp would show the differene together with the
+       # so that test_cmp would show the difference together with the
        # breakage in a way easier to consume by the debugging user.
        {
                echo "git show -s $*"
index 5bcb288f5c4d02e7994d745bc07485bf1bf6c116..464ffdd147abbae354ae3adfe593b89a37d5c726 100755 (executable)
@@ -119,8 +119,11 @@ test_expect_success GPG 'signed push sends push certificate' '
                sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
        ) >expect &&
 
-       grep "$(git rev-parse noop ff) refs/heads/ff" dst/push-cert &&
-       grep "$(git rev-parse noop noff) refs/heads/noff" dst/push-cert &&
+       noop=$(git rev-parse noop) &&
+       ff=$(git rev-parse ff) &&
+       noff=$(git rev-parse noff) &&
+       grep "$noop $ff refs/heads/ff" dst/push-cert &&
+       grep "$noop $noff refs/heads/noff" dst/push-cert &&
        test_cmp expect dst/push-cert-status
 '
 
@@ -200,8 +203,11 @@ test_expect_success GPG 'fail without key and heed user.signingkey' '
                sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
        ) >expect &&
 
-       grep "$(git rev-parse noop ff) refs/heads/ff" dst/push-cert &&
-       grep "$(git rev-parse noop noff) refs/heads/noff" dst/push-cert &&
+       noop=$(git rev-parse noop) &&
+       ff=$(git rev-parse ff) &&
+       noff=$(git rev-parse noff) &&
+       grep "$noop $ff refs/heads/ff" dst/push-cert &&
+       grep "$noop $noff refs/heads/noff" dst/push-cert &&
        test_cmp expect dst/push-cert-status
 '
 
index a87d329656da6685e9d0846714f20a5aeeaa3556..e4e6ea4d527faa46ca30d0f09839bc3ac0aa2392 100755 (executable)
@@ -71,7 +71,7 @@ test_expect_success 'clone follows shallow recommendation' '
        test_when_finished "rm -rf super_clone" &&
        git config -f .gitmodules submodule.sub.shallow true &&
        git add .gitmodules &&
-       git commit -m "recommed shallow for sub" &&
+       git commit -m "recommend shallow for sub" &&
        git clone --recurse-submodules --no-local "file://$pwd/." super_clone &&
        (
                cd super_clone &&
@@ -105,7 +105,7 @@ test_expect_success 'clone follows non shallow recommendation' '
        test_when_finished "rm -rf super_clone" &&
        git config -f .gitmodules submodule.sub.shallow false &&
        git add .gitmodules &&
-       git commit -m "recommed non shallow for sub" &&
+       git commit -m "recommend non shallow for sub" &&
        git clone --recurse-submodules --no-local "file://$pwd/." super_clone &&
        (
                cd super_clone &&
index 3bf2759eaebd38bca5d37f624144436fc77828eb..534903bbd2972301965a3d7eed6fa8e380eeeb86 100755 (executable)
@@ -235,4 +235,18 @@ test_sequence "--bisect"
 
 #
 #
+
+test_expect_success '--bisect can default to good/bad refs' '
+       git update-ref refs/bisect/bad c3 &&
+       good=$(git rev-parse b1) &&
+       git update-ref refs/bisect/good-$good $good &&
+       good=$(git rev-parse c1) &&
+       git update-ref refs/bisect/good-$good $good &&
+
+       # the only thing between c3 and c1 is c2
+       git rev-parse c2 >expect &&
+       git rev-list --bisect >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 16952e44fcfd705e115b81099bdbff809ff1520d..aa74eb8f0d5dfb4f228b1e8c7b9dbbc0b88adb4d 100755 (executable)
@@ -244,7 +244,7 @@ test_expect_success 'setup and absorb a submodule' '
        test_cmp expect out
 '
 
-test_expect_success 'describe chokes on severly broken submodules' '
+test_expect_success 'describe chokes on severely broken submodules' '
        mv .git/modules/sub1/ .git/modules/sub_moved &&
        test_must_fail git describe --dirty
 '
index 4f3794d415e95b0b65ca29b829ce278b45ea5dbd..20b4d83c281e2fde8812f309bdebef012c6ecb74 100755 (executable)
@@ -391,6 +391,17 @@ test_expect_success TTY 'core.pager in repo config works and retains cwd' '
        )
 '
 
+test_expect_success TTY 'core.pager is found via alias in subdirectory' '
+       sane_unset GIT_PAGER &&
+       test_config core.pager "cat >via-alias" &&
+       (
+               cd sub &&
+               rm -f via-alias &&
+               test_terminal git -c alias.r="-p rev-parse" r HEAD &&
+               test_path_is_file via-alias
+       )
+'
+
 test_doesnt_paginate      expect_failure test_must_fail 'git -p nonsense'
 
 test_pager_choices                       'git shortlog'
index 366746f0d41342b38126eccc0f58c4ece64cb210..4e4c45550262ca75b36d15e80aa1f4bffc45465f 100755 (executable)
@@ -241,9 +241,11 @@ EOF
        test_cmp expected actual
 "
 
-test_create_repo sm2 &&
-head7=$(add_file sm2 foo8 foo9) &&
-git add sm2
+test_expect_success 'create second submodule' '
+       test_create_repo sm2 &&
+       head7=$(add_file sm2 foo8 foo9) &&
+       git add sm2
+'
 
 test_expect_success 'multiple submodules' "
        git submodule summary >actual &&
index e2bbb449b6a175c6dbb9f43b08f2fa7061d5d9f5..ce74c12da2daccd26edbb92070e5ff4eb1f09f9c 100755 (executable)
@@ -33,7 +33,7 @@ test_expect_success 'absorb the git dir' '
        test_cmp expect.2 actual.2
 '
 
-test_expect_success 'absorbing does not fail for deinitalized submodules' '
+test_expect_success 'absorbing does not fail for deinitialized submodules' '
        test_when_finished "git submodule update --init" &&
        git submodule deinit --all &&
        git submodule absorbgitdirs &&
index 9c785b07ec241440c64beed917ba248b1092b43a..c8e7e983317610b54da89101bea8f7c59a4dcec3 100755 (executable)
@@ -2,7 +2,7 @@
 
 test_description='Test submodule--helper is-active
 
-This test verifies that `git submodue--helper is-active` correclty identifies
+This test verifies that `git submodue--helper is-active` correctly identifies
 submodules which are "active" and interesting to the user.
 '
 
diff --git a/t/t7414-submodule-mistakes.sh b/t/t7414-submodule-mistakes.sh
new file mode 100755 (executable)
index 0000000..f2e7df5
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+test_description='handling of common mistakes people may make with submodules'
+. ./test-lib.sh
+
+test_expect_success 'create embedded repository' '
+       git init embed &&
+       test_commit -C embed one
+'
+
+test_expect_success 'git-add on embedded repository warns' '
+       test_when_finished "git rm --cached -f embed" &&
+       git add embed 2>stderr &&
+       test_i18ngrep warning stderr
+'
+
+test_expect_success '--no-warn-embedded-repo suppresses warning' '
+       test_when_finished "git rm --cached -f embed" &&
+       git add --no-warn-embedded-repo embed 2>stderr &&
+       test_i18ngrep ! warning stderr
+'
+
+test_expect_success 'no warning when updating entry' '
+       test_when_finished "git rm --cached -f embed" &&
+       git add embed &&
+       git -C embed commit --allow-empty -m two &&
+       git add embed 2>stderr &&
+       test_i18ngrep ! warning stderr
+'
+
+test_expect_success 'submodule add does not warn' '
+       test_when_finished "git rm -rf submodule .gitmodules" &&
+       git submodule add ./embed submodule 2>stderr &&
+       test_i18ngrep ! warning stderr
+'
+
+test_done
index 116885a260a56f94550ace2b541498a5e6f8e877..5739d3ed232268331517d59600d1e72b625360d2 100755 (executable)
@@ -329,4 +329,27 @@ test_expect_success 'invalid message options when using --fixup' '
        test_must_fail git commit --fixup HEAD~1 -F log
 '
 
+cat >expected-template <<EOF
+
+# Please enter the commit message for your changes. Lines starting
+# with '#' will be ignored, and an empty message aborts the commit.
+#
+# Author:    A U Thor <author@example.com>
+#
+# On branch commit-template-check
+# Changes to be committed:
+#      new file:   commit-template-check
+#
+# Untracked files not listed
+EOF
+
+test_expect_success 'new line found before status message in commit template' '
+       git checkout -b commit-template-check &&
+       git reset --hard HEAD &&
+       touch commit-template-check &&
+       git add commit-template-check &&
+       GIT_EDITOR="cat >editor-input" git commit --untracked-files=no --allow-empty-message &&
+       test_i18ncmp expected-template editor-input
+'
+
 test_done
index 0b6da7ae1fd3d15f0d47783d3af50cb17d2c66df..fa61b1a4ee4a1d5ba457cb30e5cc045f724ed503 100755 (executable)
@@ -18,7 +18,7 @@ test_expect_success 'initial status' '
        echo bongo bongo >file &&
        git add file &&
        git status >actual &&
-       test_i18ngrep "Initial commit" actual
+       test_i18ngrep "No commits yet" actual
 '
 
 test_expect_success 'fail initial amend' '
index 79427840a4faed765c06c9c9dcf35e4ec3c43c43..43d19a9b2292033fd0297afb7df162efa2eb5621 100755 (executable)
@@ -1603,9 +1603,71 @@ EOF
 test_expect_success 'git commit -m will commit a staged but ignored submodule' '
        git commit -uno -m message &&
        git status -s --ignore-submodules=dirty >output &&
-        test_i18ngrep ! "^M. sm" output &&
+       test_i18ngrep ! "^M. sm" output &&
        git config --remove-section submodule.subname &&
        git config -f .gitmodules  --remove-section submodule.subname
 '
 
+test_expect_success 'show stash info with "--show-stash"' '
+       git reset --hard &&
+       git stash clear &&
+       echo 1 >file &&
+       git add file &&
+       git stash &&
+       git status >expected_default &&
+       git status --show-stash >expected_with_stash &&
+       test_i18ngrep "^Your stash currently has 1 entry$" expected_with_stash
+'
+
+test_expect_success 'no stash info with "--show-stash --no-show-stash"' '
+       git status --show-stash --no-show-stash >expected_without_stash &&
+       test_cmp expected_default expected_without_stash
+'
+
+test_expect_success '"status.showStash=false" weaker than "--show-stash"' '
+       git -c status.showStash=false status --show-stash >actual &&
+       test_cmp expected_with_stash actual
+'
+
+test_expect_success '"status.showStash=true" weaker than "--no-show-stash"' '
+       git -c status.showStash=true status --no-show-stash >actual &&
+       test_cmp expected_without_stash actual
+'
+
+test_expect_success 'no additionnal info if no stash entries' '
+       git stash clear &&
+       git -c status.showStash=true status >actual &&
+       test_cmp expected_without_stash actual
+'
+
+test_expect_success '"No commits yet" should be noted in status output' '
+       git checkout --orphan empty-branch-1 &&
+       git status >output &&
+       test_i18ngrep "No commits yet" output
+'
+
+test_expect_success '"No commits yet" should not be noted in status output' '
+       git checkout --orphan empty-branch-2 &&
+       test_commit test-commit-1 &&
+       git status >output &&
+       test_i18ngrep ! "No commits yet" output
+'
+
+test_expect_success '"Initial commit" should be noted in commit template' '
+       git checkout --orphan empty-branch-3 &&
+       touch to_be_committed_1 &&
+       git add to_be_committed_1 &&
+       git commit --dry-run >output &&
+       test_i18ngrep "Initial commit" output
+'
+
+test_expect_success '"Initial commit" should not be noted in commit template' '
+       git checkout --orphan empty-branch-4 &&
+       test_commit test-commit-2 &&
+       touch to_be_committed_2 &&
+       git add to_be_committed_2 &&
+       git commit --dry-run >output &&
+       test_i18ngrep ! "Initial commit" output
+'
+
 test_done
index 2e0ba3ebd8ab3273144743dc38675e2b5d429ea1..67b8c50a5ab431345de2909209811fc8e4f12548 100755 (executable)
@@ -2822,7 +2822,7 @@ test_expect_success 'S: filemodify with garbage after sha1 must fail' '
 #
 # notemodify, three ways to say dataref
 #
-test_expect_success 'S: notemodify with garabge after mark dataref must fail' '
+test_expect_success 'S: notemodify with garbage after mark dataref must fail' '
        test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
        commit refs/heads/S
        committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
index 1b75c919651a8126e2a327f3d9645d4377823726..34cd01366f92164ffcd712cb86dac4eb1cffa3f5 100755 (executable)
@@ -133,6 +133,13 @@ sub adjust_dirsep {
 unlink $tmpfile3;
 chdir($abs_repo_dir);
 
+# unquoting paths
+is(Git::unquote_path('abc'), 'abc', 'unquote unquoted path');
+is(Git::unquote_path('"abc def"'), 'abc def', 'unquote simple quoted path');
+is(Git::unquote_path('"abc\"\\\\ \a\b\t\n\v\f\r\001\040"'),
+                    "abc\"\\ \x07\x08\x09\x0a\x0b\x0c\x0d\x01 ",
+                    'unquote escape sequences');
+
 printf "1..%d\n", Test::More->builder->current_test;
 
 my $is_passing = eval { Test::More->is_passing };
index 5ee124332a713b1dec984090401b08efb2b9cfe9..db622c3555dcbf7f66b45c05df5279b6db6b2a9e 100644 (file)
@@ -216,6 +216,11 @@ test_chmod () {
        git update-index --add "--chmod=$@"
 }
 
+# Get the modebits from a file.
+test_modebits () {
+       ls -l "$1" | sed -e 's|^\(..........\).*|\1|'
+}
+
 # Unset a configuration variable, but don't fail if it doesn't exist.
 test_unconfig () {
        config_dir=
index 11f0b9fb40bcedbfcd3111fa8076ce0d9e1eb20f..751b56c009a8c2f6c3531dab65565f9e06029778 100644 (file)
--- a/trailer.c
+++ b/trailer.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "string-list.h"
 #include "run-command.h"
 #include "commit.h"
index 36408046eb28d8af3c90614f73ee8112855b4677..33cff38cc0b9b4a2d05b26544c9edda9caa33e9a 100644 (file)
@@ -242,8 +242,7 @@ static int disconnect_helper(struct transport *transport)
                close(data->helper->out);
                fclose(data->out);
                res = finish_command(data->helper);
-               free(data->helper);
-               data->helper = NULL;
+               FREE_AND_NULL(data->helper);
        }
        return res;
 }
@@ -711,43 +710,35 @@ static int push_update_ref_status(struct strbuf *buf,
 
                if (!strcmp(msg, "no match")) {
                        status = REF_STATUS_NONE;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "up to date")) {
                        status = REF_STATUS_UPTODATE;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "non-fast forward")) {
                        status = REF_STATUS_REJECT_NONFASTFORWARD;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "already exists")) {
                        status = REF_STATUS_REJECT_ALREADY_EXISTS;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "fetch first")) {
                        status = REF_STATUS_REJECT_FETCH_FIRST;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "needs force")) {
                        status = REF_STATUS_REJECT_NEEDS_FORCE;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "stale info")) {
                        status = REF_STATUS_REJECT_STALE;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "forced update")) {
                        forced = 1;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
        }
 
index 9bfcf870f9078f75349bd3b4976c71bbf5c49ebf..d75ff0514d8d4dd05da1d618ddf2602e5a4f26a9 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "transport.h"
 #include "run-command.h"
 #include "pkt-line.h"
@@ -1145,8 +1146,7 @@ void transport_unlock_pack(struct transport *transport)
 {
        if (transport->pack_lockfile) {
                unlink_or_warn(transport->pack_lockfile);
-               free(transport->pack_lockfile);
-               transport->pack_lockfile = NULL;
+               FREE_AND_NULL(transport->pack_lockfile);
        }
 }
 
index 467e3817243567dadfaf853fddef8a0ef894f270..bd6d65a40920a547b9f27512e31341231273fa75 100644 (file)
@@ -141,8 +141,7 @@ static struct combine_diff_path *path_appendnew(struct combine_diff_path *last,
        /* if last->next is !NULL - it is a pre-allocated memory, we can reuse */
        p = last->next;
        if (p && (alloclen > (intptr_t)p->next)) {
-               free(p);
-               p = NULL;
+               FREE_AND_NULL(p);
        }
 
        if (!p) {
@@ -559,8 +558,7 @@ struct combine_diff_path *diff_tree_paths(
         * (see path_appendnew() for details about why)
         */
        if (p->next) {
-               free(p->next);
-               p->next = NULL;
+               FREE_AND_NULL(p->next);
        }
 
        return p;
diff --git a/tree.c b/tree.c
index 603b29ee805b00c4b1eeeebed51c917bfef7c009..b224115e0f4d61368560eba406a04f0259b7c4f0 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -1,3 +1,4 @@
+#define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
 #include "cache-tree.h"
 #include "tree.h"
@@ -8,7 +9,11 @@
 
 const char *tree_type = "tree";
 
-static int read_one_entry_opt(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, int opt)
+static int read_one_entry_opt(struct index_state *istate,
+                             const unsigned char *sha1,
+                             const char *base, int baselen,
+                             const char *pathname,
+                             unsigned mode, int stage, int opt)
 {
        int len;
        unsigned int size;
@@ -27,14 +32,15 @@ static int read_one_entry_opt(const unsigned char *sha1, const char *base, int b
        memcpy(ce->name, base, baselen);
        memcpy(ce->name + baselen, pathname, len+1);
        hashcpy(ce->oid.hash, sha1);
-       return add_cache_entry(ce, opt);
+       return add_index_entry(istate, ce, opt);
 }
 
 static int read_one_entry(const unsigned char *sha1, struct strbuf *base,
                          const char *pathname, unsigned mode, int stage,
                          void *context)
 {
-       return read_one_entry_opt(sha1, base->buf, base->len, pathname,
+       struct index_state *istate = context;
+       return read_one_entry_opt(istate, sha1, base->buf, base->len, pathname,
                                  mode, stage,
                                  ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
 }
@@ -47,7 +53,8 @@ static int read_one_entry_quick(const unsigned char *sha1, struct strbuf *base,
                                const char *pathname, unsigned mode, int stage,
                                void *context)
 {
-       return read_one_entry_opt(sha1, base->buf, base->len, pathname,
+       struct index_state *istate = context;
+       return read_one_entry_opt(istate, sha1, base->buf, base->len, pathname,
                                  mode, stage,
                                  ADD_CACHE_JUST_APPEND);
 }
@@ -144,7 +151,8 @@ static int cmp_cache_name_compare(const void *a_, const void *b_)
                                  ce2->name, ce2->ce_namelen, ce_stage(ce2));
 }
 
-int read_tree(struct tree *tree, int stage, struct pathspec *match)
+int read_tree(struct tree *tree, int stage, struct pathspec *match,
+             struct index_state *istate)
 {
        read_tree_fn_t fn = NULL;
        int i, err;
@@ -164,23 +172,23 @@ int read_tree(struct tree *tree, int stage, struct pathspec *match)
         * do it the original slow way, otherwise, append and then
         * sort at the end.
         */
-       for (i = 0; !fn && i < active_nr; i++) {
-               const struct cache_entry *ce = active_cache[i];
+       for (i = 0; !fn && i < istate->cache_nr; i++) {
+               const struct cache_entry *ce = istate->cache[i];
                if (ce_stage(ce) == stage)
                        fn = read_one_entry;
        }
 
        if (!fn)
                fn = read_one_entry_quick;
-       err = read_tree_recursive(tree, "", 0, stage, match, fn, NULL);
+       err = read_tree_recursive(tree, "", 0, stage, match, fn, istate);
        if (fn == read_one_entry || err)
                return err;
 
        /*
         * Sort the cache entry -- we need to nuke the cache tree, though.
         */
-       cache_tree_free(&active_cache_tree);
-       QSORT(active_cache, active_nr, cmp_cache_name_compare);
+       cache_tree_free(&istate->cache_tree);
+       QSORT(istate->cache, istate->cache_nr, cmp_cache_name_compare);
        return 0;
 }
 
@@ -226,8 +234,7 @@ int parse_tree_gently(struct tree *item, int quiet_on_missing)
 
 void free_tree_buffer(struct tree *tree)
 {
-       free(tree->buffer);
-       tree->buffer = NULL;
+       FREE_AND_NULL(tree->buffer);
        tree->size = 0;
        tree->object.parsed = 0;
 }
diff --git a/tree.h b/tree.h
index 0d4734b94b67603bc8f71a5273c3414f8785e066..744e6dc2ac883adfa0e079f5f84f45a45e22b59d 100644 (file)
--- a/tree.h
+++ b/tree.h
@@ -34,6 +34,7 @@ extern int read_tree_recursive(struct tree *tree,
                               int stage, const struct pathspec *pathspec,
                               read_tree_fn_t fn, void *context);
 
-extern int read_tree(struct tree *tree, int stage, struct pathspec *pathspec);
+extern int read_tree(struct tree *tree, int stage, struct pathspec *pathspec,
+                    struct index_state *istate);
 
 #endif /* TREE_H */
index d38c37e38cf183cf878a9f35b19544d1da0bc438..dd535bc8497e5d8202a94923fd0a68c3f46907fd 100644 (file)
@@ -1,5 +1,6 @@
 #define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
+#include "config.h"
 #include "dir.h"
 #include "tree.h"
 #include "tree-walk.h"
index 5330c02c1427862be1eea61c8d8e4127909d13fe..7efff2fbfd76380fd448d53173f8295d7c9c9d87 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "pkt-line.h"
 #include "sideband.h"
diff --git a/usage.c b/usage.c
index 2f87ca69a8299485ee013187f99ffbdb2618d7c8..1ea7df9a202339972ee59f35a5ba8852502c915f 100644 (file)
--- a/usage.c
+++ b/usage.c
@@ -44,7 +44,23 @@ static void warn_builtin(const char *warn, va_list params)
 static int die_is_recursing_builtin(void)
 {
        static int dying;
-       return dying++;
+       /*
+        * Just an arbitrary number X where "a < x < b" where "a" is
+        * "maximum number of pthreads we'll ever plausibly spawn" and
+        * "b" is "something less than Inf", since the point is to
+        * prevent infinite recursion.
+        */
+       static const int recursion_limit = 1024;
+
+       dying++;
+       if (dying > recursion_limit) {
+               return 1;
+       } else if (dying == 2) {
+               warning("die() called many times. Recursion error or racy threaded death!");
+               return 0;
+       } else {
+               return 0;
+       }
 }
 
 /* If we are in a dlopen()ed .so write to a global variable would segfault
index 8b732e40bce4968257c2918219f7dfdb0b9ed3a0..2c1502f719a17abaef6c5c56439c560994b45d37 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "userdiff.h"
 #include "attr.h"
 
index 9f81dc1062bc1f7f243afa8c0404ff5100fc0ef8..069ee94a4d79422ea659a7ebe3923662f0626afa 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "string-list.h"
 
 /*
index 2801c6d52bdaa1fb83a0069c8d2217ea129fd6bf..e28ffbeb096a85d67b2e885c48ab096340b5d295 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "repository.h"
 #include "refs.h"
 #include "strbuf.h"
 #include "worktree.h"
@@ -76,7 +77,7 @@ static struct worktree *get_linked_worktree(const char *id)
        if (!id)
                die("Missing linked worktree name");
 
-       strbuf_git_common_path(&path, "worktrees/%s/gitdir", id);
+       strbuf_git_common_path(&path, the_repository, "worktrees/%s/gitdir", id);
        if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0)
                /* invalid gitdir file */
                goto done;
index 4632c7d4c08c3127c4017c98c0983871f0236d93..36630e5d1855a41407e217e610aa1f293288abe1 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -2,6 +2,7 @@
  * Various trivial helper wrappers around standard functions
  */
 #include "cache.h"
+#include "config.h"
 
 static void do_nothing(size_t size)
 {
index bf651f16fae83ffe30676790685799e8f2280082..8d2fb35b08037a0e435573066d6e3f28e7529db4 100644 (file)
@@ -137,6 +137,7 @@ void wt_status_prepare(struct wt_status *s)
        s->untracked.strdup_strings = 1;
        s->ignored.strdup_strings = 1;
        s->show_branch = -1;  /* unspecified */
+       s->show_stash = 0;
        s->display_comment_prefix = 0;
 }
 
@@ -801,6 +802,27 @@ static void wt_longstatus_print_changed(struct wt_status *s)
        wt_longstatus_print_trailer(s);
 }
 
+static int stash_count_refs(struct object_id *ooid, struct object_id *noid,
+                           const char *email, timestamp_t timestamp, int tz,
+                           const char *message, void *cb_data)
+{
+       int *c = cb_data;
+       (*c)++;
+       return 0;
+}
+
+static void wt_longstatus_print_stash_summary(struct wt_status *s)
+{
+       int stash_count = 0;
+
+       for_each_reflog_ent("refs/stash", stash_count_refs, &stash_count);
+       if (stash_count > 0)
+               status_printf_ln(s, GIT_COLOR_NORMAL,
+                                Q_("Your stash currently has %d entry",
+                                   "Your stash currently has %d entries", stash_count),
+                                stash_count);
+}
+
 static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncommitted)
 {
        struct child_process sm_summary = CHILD_PROCESS_INIT;
@@ -1579,7 +1601,10 @@ static void wt_longstatus_print(struct wt_status *s)
 
        if (s->is_initial) {
                status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
-               status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
+               status_printf_ln(s, color(WT_STATUS_HEADER, s),
+                                s->commit_template
+                                ? _("Initial commit")
+                                : _("No commits yet"));
                status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
        }
 
@@ -1642,6 +1667,8 @@ static void wt_longstatus_print(struct wt_status *s)
                } else
                        printf(_("nothing to commit, working tree clean\n"));
        }
+       if(s->show_stash)
+               wt_longstatus_print_stash_summary(s);
 }
 
 static void wt_shortstatus_unmerged(struct string_list_item *it,
@@ -1749,7 +1776,7 @@ static void wt_shortstatus_print_tracking(struct wt_status *s)
 #define LABEL(string) (s->no_gettext ? (string) : _(string))
 
        if (s->is_initial)
-               color_fprintf(s->fp, header_color, LABEL(N_("Initial commit on ")));
+               color_fprintf(s->fp, header_color, LABEL(N_("No commits yet on ")));
 
        if (!strcmp(s->branch, "HEAD")) {
                color_fprintf(s->fp, color(WT_STATUS_NOBRANCH, s), "%s",
index 8a3864783b039d92454cfda1c2ef2457e737cddd..64f4d33ea183c1a6e700f1f6667b83f0e904773e 100644 (file)
@@ -76,7 +76,9 @@ struct wt_status {
        char color_palette[WT_STATUS_MAXSLOT][COLOR_MAXLEN];
        unsigned colopts;
        int null_termination;
+       int commit_template;
        int show_branch;
+       int show_stash;
        int hints;
 
        enum wt_status_format status_format;
index d3f78ca2a718d3e4928aa90067e24d19988514c1..018e03308921e3b44bb75b8bc1e005424ca4fc1b 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "xdiff-interface.h"
 #include "xdiff/xtypes.h"
 #include "xdiff/xdiffi.h"