Merge branches 'bw/ls-files-sans-the-index' and 'bw/config-h' into bw/repo-object
authorJunio C Hamano <gitster@pobox.com>
Wed, 21 Jun 2017 22:20:44 +0000 (15:20 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 24 Jun 2017 01:24:00 +0000 (18:24 -0700)
* bw/ls-files-sans-the-index:
ls-files: factor out tag calculation
ls-files: factor out debug info into a function
ls-files: convert show_files to take an index
ls-files: convert show_ce_entry to take an index
ls-files: convert prune_cache to take an index
ls-files: convert ce_excluded to take an index
ls-files: convert show_ru_info to take an index
ls-files: convert show_other_files to take an index
ls-files: convert show_killed_files to take an index
ls-files: convert write_eolinfo to take an index
ls-files: convert overlay_tree_on_cache to take an index
tree: convert read_tree to take an index parameter
convert: convert renormalize_buffer to take an index
convert: convert convert_to_git to take an index
convert: convert convert_to_git_filter_fd to take an index
convert: convert crlf_to_git to take an index
convert: convert get_cached_convert_stats_ascii to take an index

* bw/config-h:
config: don't implicitly use gitdir or commondir
config: respect commondir
setup: teach discover_git_directory to respect the commondir
config: don't include config.h by default
config: remove git_config_iter
config: create config.h
alias: use the early config machinery to expand aliases
t7006: demonstrate a problem with aliases in subdirectories
t1308: relax the test verifying that empty alias values are disallowed
help: use early config when autocorrecting aliases
config: report correct line number upon error
discover_git_directory(): avoid setting invalid git_dir

206 files changed:
Documentation/RelNotes/2.13.2.txt [new file with mode: 0644]
Documentation/RelNotes/2.14.0.txt
Documentation/config.txt
Documentation/git-rm.txt
Documentation/git-svn.txt
Documentation/rev-list-options.txt
Makefile
advice.c
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/credential.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/pull.c
builtin/push.c
builtin/read-tree.c
builtin/rebase--helper.c
builtin/receive-pack.c
builtin/reflog.c
builtin/remote-ext.c
builtin/remote-fd.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/upload-archive.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.c
compat/fopen.c
compat/mingw.c
compat/precompose_utf8.c
config.c
config.h [new file with mode: 0644]
config.mak.uname
configure.ac
connect.c
contrib/completion/git-completion.bash
convert.c
credential-cache--daemon.c
credential.c
daemon.c
diff-lib.c
diff-no-index.c
diff.c
diff.h
diffcore-rename.c
diffcore.h
dir.c
environment.c
fast-import.c
fetch-pack.c
git-compat-util.h
git.c
gpg-interface.c
graph.c
grep.c
grep.h
help.c
http-backend.c
http-fetch.c
http.c
ident.c
imap-send.c
line-log.c
ll-merge.c
log-tree.c
mailinfo.c
merge-recursive.c
notes-cache.c
notes-merge.c
notes-merge.h
notes-utils.c
notes-utils.h
notes.c
notes.h
pager.c
parse-options.c
patch-ids.c
patch-ids.h
pathspec.c
pretty.c
prompt.c
read-cache.c
refs.c
refs/files-backend.c
remote-curl.c
remote-testsvn.c
remote.c
rerere.c
revision.c
send-pack.c
sequencer.c
server-info.c
setup.c
sha1_file.c
sha1_name.c
sub-process.h
submodule-config.c
submodule.c
submodule.h
t/helper/test-config.c
t/helper/test-submodule-config.c
t/lib-submodule-update.sh
t/perf/perf-lib.sh
t/t0012-help.sh
t/t1013-read-tree-submodule.sh
t/t1300-repo-config.sh
t/t1308-config-set.sh
t/t2013-checkout-submodule.sh
t/t4202-log.sh
t/t4208-log-magic-pathspec.sh
t/t5313-pack-bounds-checks.sh
t/t5512-ls-remote.sh
t/t5526-fetch-submodules.sh
t/t5531-deep-submodule-push.sh
t/t5580-clone-push-unc.sh
t/t7006-pager.sh
t/t7112-reset-submodule.sh
t/t7814-grep-recurse-submodules.sh
t/test-lib.sh
trailer.c
transport.c
tree-diff.c
unpack-trees.c
upload-pack.c
userdiff.c
versioncmp.c
wrapper.c
wt-status.c
xdiff-interface.c
diff --git a/Documentation/RelNotes/2.13.2.txt b/Documentation/RelNotes/2.13.2.txt
new file mode 100644 (file)
index 0000000..c8ba0fa
--- /dev/null
@@ -0,0 +1,37 @@
+Git v2.13.2 Release Notes
+=========================
+
+Fixes since v2.13.1
+-------------------
+
+ * The "collision detecting" SHA-1 implementation shipped with 2.13.1
+   was still broken on some platforms.  Update to the upstream code
+   again to take their fix.
+
+ * "git checkout --recurse-submodules" did not quite work with a
+   submodule that itself has submodules.
+
+ * Introduce the BUG() macro to improve die("BUG: ...").
+
+ * The "run-command" API implementation has been made more robust
+   against dead-locking in a threaded environment.
+
+ * A recent update to t5545-push-options.sh started skipping all the
+   tests in the script when a web server testing is disabled or
+   unavailable, not just the ones that require a web server.  Non HTTP
+   tests have been salvaged to always run in this script.
+
+ * "git clean -d" used to clean directories that has ignored files,
+   even though the command should not lose ignored ones without "-x".
+   "git status --ignored"  did not list ignored and untracked files
+   without "-uall".  These have been corrected.
+
+ * The timestamp of the index file is now taken after the file is
+   closed, to help Windows, on which a stale timestamp is reported by
+   fstat() on a file that is opened for writing and data was written
+   but not yet closed.
+
+ * "git pull --rebase --autostash" didn't auto-stash when the local history
+   fast-forwards to the upstream.
+
+Also contains various documentation updates and code clean-ups.
index e4ca72e50e16bd4c5a04e31cc368d8e4ce4c766a..a71615a6b4275f0705aadeb62ef1763f2a81b062 100644 (file)
@@ -67,6 +67,25 @@ UI, Workflows & Features
  * Make the "indent" heuristics the default in "diff" and diff.indentHeuristics
    configuration variable an escape hatch for those who do no want it.
 
+ * Many commands learned to pay attention to submodule.recurse
+   configuration.
+
+ * The convention for a command line is to follow "git cmdname
+   --options" with revisions followed by an optional "--"
+   disambiguator and then finally pathspecs.  When "--" is not there,
+   we make sure early ones are all interpretable as revs (and do not
+   look like paths) and later ones are the other way around.  A
+   pathspec with "magic" (e.g. ":/p/a/t/h" that matches p/a/t/h from
+   the top-level of the working tree, no matter what subdirectory you
+   are working from) are conservatively judged as "not a path", which
+   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.
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -129,6 +148,26 @@ Performance, Internal Implementation, Development Support etc.
  * The internal logic used in "git blame" has been libified to make it
    easier to use by cgit.
 
+ * Our code often opens a path to an optional file, to work on its
+   contents when we can successfully open it.  We can ignore a failure
+   to open if such an optional file does not exist, but we do want to
+   report a failure in opening for other reasons (e.g. we got an I/O
+   error, or the file is there, but we lack the permission to open).
+
+   The exact errors we need to ignore are ENOENT (obviously) and
+   ENOTDIR (less obvious).  Instead of repeating comparison of errno
+   with these two constants, introduce a helper function to do so.
+
+ * We often try to open a file for reading whose existence is
+   optional, and silently ignore errors from open/fopen; report such
+   errors if they are not due to missing files.
+
+ * When an existing repository is used for t/perf testing, we first
+   create bit-for-bit copy of it, which may grab a transient state of
+   the repository and freeze it into the repository used for testing,
+   which then may cause Git operations to fail.  Single out "the index
+   being locked" case and forcibly drop the lock from the copy.
+
 
 Also contains various documentation updates and code clean-ups.
 
@@ -176,7 +215,6 @@ notes for details).
 
  * "git checkout --recurse-submodules" did not quite work with a
    submodule that itself has submodules.
-   (merge 218c883783 sb/checkout-recurse-submodules later to maint).
 
  * 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
@@ -203,7 +241,6 @@ notes for details).
    checked out with eol=LF even on Windows.
 
  * Introduce the BUG() macro to improve die("BUG: ...").
-   (merge 3d7dd2d3b6 jk/bug-to-abort later to maint).
 
  * Clarify documentation for include.path and includeIf.<condition>.path
    configuration variables.
@@ -249,17 +286,14 @@ notes for details).
 
  * The "run-command" API implementation has been made more robust
    against dead-locking in a threaded environment.
-   (merge e3f43ce765 bw/forking-and-threading later to maint).
 
  * A recent update to t5545-push-options.sh started skipping all the
    tests in the script when a web server testing is disabled or
    unavailable, not just the ones that require a web server.  Non HTTP
    tests have been salvaged to always run in this script.
-   (merge 2e397e4ddf jc/skip-test-in-the-middle later to maint).
 
  * "git send-email" now uses Net::SMTP::SSL, which is obsolete, only
    when needed.  Recent versions of Net::SMTP can do TLS natively.
-   (merge bfbfc9a953 dk/send-email-avoid-net-smtp-ssl-when-able later to maint).
 
  * "foo\bar\baz" in "git fetch foo\bar\baz", even though there is no
    slashes in it, cannot be a nickname for a remote on Windows, as
@@ -269,7 +303,6 @@ notes for details).
    even though the command should not lose ignored ones without "-x".
    "git status --ignored"  did not list ignored and untracked files
    without "-uall".  These have been corrected.
-   (merge 6b1db43109 sl/clean-d-ignored-fix later to maint).
 
  * The result from "git diff" that compares two blobs, e.g. "git diff
    $commit1:$path $commit2:$path", used to be shown with the full
@@ -291,16 +324,19 @@ notes for details).
    closed, to help Windows, on which a stale timestamp is reported by
    fstat() on a file that is opened for writing and data was written
    but not yet closed.
-   (merge 9f41c7a6b3 jh/close-index-before-stat later to maint).
 
  * "git pull --rebase --autostash" didn't auto-stash when the local history
    fast-forwards to the upstream.
-   (merge f15e7cf5cc tb/pull-ff-rebase-autostash later to maint).
+
+ * 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
+   set-up, and the commands that expect RUN_SETUP is done by the Git
+   potty needs to be prepared to show the help text without barfing.
+   (merge d691551192 jk/consistent-h later to maint).
 
  * Other minor doc, test and build updates and code cleanups.
-   (merge c5a9157393 jh/memihash-opt later to maint).
-   (merge 44e2ff09ce ab/t3070-test-dedup later to maint).
-   (merge 9ee4aa95db rf/completion-config-commit later to maint).
-   (merge ef4fe5617e jk/connect-symref-info-leak-fix later to maint).
-   (merge a56eea28c4 jk/drop-free-refspecs later to maint).
-   (merge 0c79cee697 ad/pull-remote-doc later to maint).
+   (merge 8ba74bfd7c jc/diff-tree-stale-comment later to maint).
+   (merge 68602c01fd sb/submodule-rm-absorb later to maint).
index dd4beec39dbe0bb328448c2ff7ca918b97016aa5..f6278a5ae6a1f554ddb8b9861d9067181b928bb5 100644 (file)
@@ -3091,6 +3091,11 @@ submodule.active::
        submodule's path to determine if the submodule is of interest to git
        commands.
 
+submodule.recurse::
+       Specifies if commands recurse into submodules by default. This
+       applies to all commands that have a `--recurse-submodules` option.
+       Defaults to false.
+
 submodule.fetchJobs::
        Specifies how many submodules are fetched/cloned at the same time.
        A positive integer allows up to that number of submodules fetched
index f1efc116ebb88a3bc31898f6a18837f8b951ad09..8c87e8cdd772a42192f54a6a49789c6005eeb87d 100644 (file)
@@ -140,10 +140,11 @@ Only submodules using a gitfile (which means they were cloned
 with a Git version 1.7.8 or newer) will be removed from the work
 tree, as their repository lives inside the .git directory of the
 superproject. If a submodule (or one of those nested inside it)
-still uses a .git directory, `git rm` will fail - no matter if forced
-or not - to protect the submodule's history. If it exists the
-submodule.<name> section in the linkgit:gitmodules[5] file will also
-be removed and that file will be staged (unless --cached or -n are used).
+still uses a .git directory, `git rm` will move the submodules
+git directory into the superprojects git directory to protect
+the submodule's history. If it exists the submodule.<name> section
+in the linkgit:gitmodules[5] file will also be removed and that file
+will be staged (unless --cached or -n are used).
 
 A submodule is considered up-to-date when the HEAD is the same as
 recorded in the index, no tracked files are modified and no untracked
index fba0b4eece46eb56aa926e2957658352e3ba1f10..aa2aeabb60209fabd772907a91c2812b2a305d7d 100644 (file)
@@ -459,6 +459,21 @@ Any other arguments are passed directly to 'git log'
        (URL) may be omitted if you are working from a 'git svn'-aware
        repository (that has been `init`-ed with 'git svn').
        The -r<revision> option is required for this.
++
+The commit message is supplied either directly with the `-m` or `-F`
+option, or indirectly from the tag or commit when the second tree-ish
+denotes such an object, or it is requested by invoking an editor (see
+`--edit` option below).
+
+-m <msg>;;
+--message=<msg>;;
+       Use the given `msg` as the commit message. This option
+       disables the `--edit` option.
+
+-F <filename>;;
+--file=<filename>;;
+       Take the commit message from the given file. This option
+       disables the `--edit` option.
 
 'info'::
        Shows information about a file or directory similar to what
index a46f70c2b16c2c03f47ccb3444cffb491b68ed83..9c44eae55dbeac5fde111acf006bd0a4d586901e 100644 (file)
@@ -91,6 +91,7 @@ endif::git-rev-list[]
        Consider the limiting patterns to be fixed strings (don't interpret
        pattern as a regular expression).
 
+-P::
 --perl-regexp::
        Consider the limiting patterns to be Perl-compatible regular
        expressions.
index 7c621f7f76181eb3d255e8d6eaf28e6e63dbb92f..f4848016380058ffdfc01966bc587ca7306415d9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -29,8 +29,23 @@ all::
 # Perl-compatible regular expressions instead of standard or extended
 # POSIX regular expressions.
 #
-# Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
-# /foo/bar/include and /foo/bar/lib directories.
+# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
+# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
+# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
+# default in future releases.
+#
+# When using USE_LIBPCRE1, define NO_LIBPCRE1_JIT if the PCRE v1
+# library is compiled without --enable-jit. We will auto-detect
+# whether the version of the PCRE v1 library in use has JIT support at
+# all, but we unfortunately can't auto-detect whether JIT support
+# hasn't been compiled in in an otherwise JIT-supporting version. If
+# you have link-time errors about a missing `pcre_jit_exec` define
+# this, or recompile PCRE v1 with --enable-jit.
+#
+# Define LIBPCREDIR=/foo/bar if your PCRE header and library files are
+# in /foo/bar/include and /foo/bar/lib directories. Which version of
+# PCRE this points to determined by the USE_LIBPCRE1 and USE_LIBPCRE2
+# variables.
 #
 # Define HAVE_ALLOCA_H if you have working alloca(3) defined in that header.
 #
@@ -1089,13 +1104,29 @@ ifdef NO_LIBGEN_H
        COMPAT_OBJS += compat/basename.o
 endif
 
-ifdef USE_LIBPCRE
-       BASIC_CFLAGS += -DUSE_LIBPCRE1
-       ifdef LIBPCREDIR
-               BASIC_CFLAGS += -I$(LIBPCREDIR)/include
-               EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
+USE_LIBPCRE1 ?= $(USE_LIBPCRE)
+
+ifneq (,$(USE_LIBPCRE1))
+       ifdef USE_LIBPCRE2
+$(error Only set USE_LIBPCRE1 (or its alias USE_LIBPCRE) or USE_LIBPCRE2, not both!)
        endif
+
+       BASIC_CFLAGS += -DUSE_LIBPCRE1
        EXTLIBS += -lpcre
+
+ifdef NO_LIBPCRE1_JIT
+       BASIC_CFLAGS += -DNO_LIBPCRE1_JIT
+endif
+endif
+
+ifdef USE_LIBPCRE2
+       BASIC_CFLAGS += -DUSE_LIBPCRE2
+       EXTLIBS += -lpcre2-8
+endif
+
+ifdef LIBPCREDIR
+       BASIC_CFLAGS += -I$(LIBPCREDIR)/include
+       EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
 endif
 
 ifdef HAVE_ALLOCA_H
@@ -2249,7 +2280,9 @@ GIT-BUILD-OPTIONS: FORCE
        @echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@+
        @echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@+
        @echo NO_EXPAT=\''$(subst ','\'',$(subst ','\'',$(NO_EXPAT)))'\' >>$@+
-       @echo USE_LIBPCRE1=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE)))'\' >>$@+
+       @echo USE_LIBPCRE1=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE1)))'\' >>$@+
+       @echo USE_LIBPCRE2=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE2)))'\' >>$@+
+       @echo NO_LIBPCRE1_JIT=\''$(subst ','\'',$(subst ','\'',$(NO_LIBPCRE1_JIT)))'\' >>$@+
        @echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
        @echo NO_PTHREADS=\''$(subst ','\'',$(subst ','\'',$(NO_PTHREADS)))'\' >>$@+
        @echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+
index b84ae4960f11af10d01667d01eb0bb27f52ecb14..3fa04fca0b81ce0b4788ad3331ae759de805e0ff 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;
diff --git a/alias.c b/alias.c
index 3b90397a99d9f7ed4a0c1c5a83f5e69c879e752f..de8e6a3f496accd9bd06916411ebb7e10b27d4cb 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
diff --git a/apply.c b/apply.c
index 97afb6f60a28b8b42d36b4d376db6156757f8c80..65063785c1651ed288133788980a1a8d0a410cbd 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"
@@ -3741,7 +3742,7 @@ static int check_to_create(struct apply_state *state,
                        return 0;
 
                return EXISTS_IN_WORKTREE;
-       } else if ((errno != ENOENT) && (errno != ENOTDIR)) {
+       } else if (!is_missing_file_error(errno)) {
                return error_errno("%s", new_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 7e2134471cb4afc1b891208ebe4bebd6ad55571d..6e4b247acd91d30ac5a879183332725d54e756a0 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"
@@ -720,16 +721,13 @@ void git_attr_set_direction(enum git_attr_direction new_direction,
 
 static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
 {
-       FILE *fp = fopen(path, "r");
+       FILE *fp = fopen_or_warn(path, "r");
        struct attr_stack *res;
        char buf[2048];
        int lineno = 0;
 
-       if (!fp) {
-               if (errno != ENOENT && errno != ENOTDIR)
-                       warn_on_inaccessible(path);
+       if (!fp)
                return NULL;
-       }
        res = xcalloc(1, sizeof(*res));
        while (fgets(buf, sizeof(buf), fp)) {
                char *bufp = buf;
index c952df692bef9ba1638e55448050db33ba76d399..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"
@@ -438,10 +439,7 @@ static void read_bisect_paths(struct argv_array *array)
 {
        struct strbuf str = STRBUF_INIT;
        const char *filename = git_path_bisect_names();
-       FILE *fp = fopen(filename, "r");
-
-       if (!fp)
-               die_errno(_("Could not open file '%s'"), filename);
+       FILE *fp = xfopen(filename, "r");
 
        while (strbuf_getline_lf(&str, fp) != EOF) {
                strbuf_trim(&str);
@@ -669,7 +667,7 @@ static int is_expected_rev(const struct object_id *oid)
        if (stat(filename, &st) || !S_ISREG(st.st_mode))
                return 0;
 
-       fp = fopen(filename, "r");
+       fp = fopen_or_warn(filename, "r");
        if (!fp)
                return 0;
 
diff --git a/blame.c b/blame.c
index a6f3d72df8fbc45a14214029491d5c06a73cefa5..6d57ab9715665a8bc6a2ba02015342ad851b6d2f 100644 (file)
--- a/blame.c
+++ b/blame.c
@@ -556,9 +556,9 @@ static struct blame_origin *find_origin(struct commit *parent,
        if (is_null_oid(&origin->commit->object.oid))
                do_diff_cache(&parent->tree->object.oid, &diff_opts);
        else
-               diff_tree_sha1(parent->tree->object.oid.hash,
-                              origin->commit->tree->object.oid.hash,
-                              "", &diff_opts);
+               diff_tree_oid(&parent->tree->object.oid,
+                             &origin->commit->tree->object.oid,
+                             "", &diff_opts);
        diffcore_std(&diff_opts);
 
        if (!diff_queued_diff.nr) {
@@ -625,9 +625,9 @@ static struct blame_origin *find_rename(struct commit *parent,
        if (is_null_oid(&origin->commit->object.oid))
                do_diff_cache(&parent->tree->object.oid, &diff_opts);
        else
-               diff_tree_sha1(parent->tree->object.oid.hash,
-                              origin->commit->tree->object.oid.hash,
-                              "", &diff_opts);
+               diff_tree_oid(&parent->tree->object.oid,
+                             &origin->commit->tree->object.oid,
+                             "", &diff_opts);
        diffcore_std(&diff_opts);
 
        for (i = 0; i < diff_queued_diff.nr; i++) {
@@ -1247,7 +1247,7 @@ static void find_copy_in_parent(struct blame_scoreboard *sb,
        /* Try "find copies harder" on new path if requested;
         * we do not want to use diffcore_rename() actually to
         * match things up; find_copies_harder is set only to
-        * force diff_tree_sha1() to feed all filepairs to diff_queue,
+        * force diff_tree_oid() to feed all filepairs to diff_queue,
         * and this code needs to be after diff_setup_done(), which
         * usually makes find-copies-harder imply copy detection.
         */
@@ -1259,9 +1259,9 @@ static void find_copy_in_parent(struct blame_scoreboard *sb,
        if (is_null_oid(&target->commit->object.oid))
                do_diff_cache(&parent->tree->object.oid, &diff_opts);
        else
-               diff_tree_sha1(parent->tree->object.oid.hash,
-                              target->commit->tree->object.oid.hash,
-                              "", &diff_opts);
+               diff_tree_oid(&parent->tree->object.oid,
+                             &target->commit->tree->object.oid,
+                             "", &diff_opts);
 
        if (!DIFF_OPT_TST(&diff_opts, FIND_COPIES_HARDER))
                diffcore_std(&diff_opts);
index 985316eb76505a60bca0aa303322bef35e7defaa..a8a548ccf2870c99bbdbcdc7036003aa648faa0c 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"
index d9a2491e48f16d9ef7de5c05008f8c7e6a5e64b2..f2415e99f37d48e562913c17d8917bda4f892c09 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"
index 5ee146bfb31df8e3d8edf356f4817e3f53f8ad3b..7c7b916d2328be8e6dc7abb7e08bb9416b21d2e6 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"
@@ -563,7 +564,7 @@ static int copy_notes_for_rebase(const struct am_state *state)
                        goto finish;
                }
 
-               if (copy_note_for_rewrite(c, from_obj.hash, to_obj.hash))
+               if (copy_note_for_rewrite(c, &from_obj, &to_obj))
                        ret = error(_("Failed to copy notes from '%s' to '%s'"),
                                        oid_to_hex(&from_obj), oid_to_hex(&to_obj));
        }
@@ -1275,12 +1276,8 @@ static int parse_mail(struct am_state *state, const char *mail)
                die("BUG: invalid value for state->scissors");
        }
 
-       mi.input = fopen(mail, "r");
-       if (!mi.input)
-               die("could not open input");
-       mi.output = fopen(am_path(state, "info"), "w");
-       if (!mi.output)
-               die("could not open output 'info'");
+       mi.input = xfopen(mail, "r");
+       mi.output = xfopen(am_path(state, "info"), "w");
        if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
                die("could not parse patch");
 
index d7a2df3b47439c5564a716402e815e0da4f0d8a9..bda1a787265e6d44d2ec0bec1e4dee5bf8de9c3b 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "commit.h"
 #include "diff.h"
@@ -481,7 +482,7 @@ static void output(struct blame_scoreboard *sb, int option)
  */
 static int read_ancestry(const char *graft_file)
 {
-       FILE *fp = fopen(graft_file, "r");
+       FILE *fp = fopen_or_warn(graft_file, "r");
        struct strbuf buf = STRBUF_INIT;
        if (!fp)
                return -1;
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..7efbc4019ac59a16ae4f147889e6f489dac1e661 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"
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 a6b2af39d3e881480193a38ff1ca3b65cdc55d94..9661e1bcba31ffa4f7b8a2fb1a9d2060cb8efda7 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "parse-options.h"
 #include "refs.h"
 #include "submodule-config.h"
 #include "submodule.h"
 
-static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
-
 static const char * const checkout_usage[] = {
        N_("git checkout [<options>] <branch>"),
        N_("git checkout [<options>] [<branch>] -- <file>..."),
        NULL,
 };
 
-static int option_parse_recurse_submodules(const struct option *opt,
-                                          const char *arg, int unset)
-{
-       if (unset) {
-               recurse_submodules = RECURSE_SUBMODULES_OFF;
-               return 0;
-       }
-       if (arg)
-               recurse_submodules =
-                       parse_update_recurse_submodules_arg(opt->long_name,
-                                                           arg);
-       else
-               recurse_submodules = RECURSE_SUBMODULES_ON;
-
-       return 0;
-}
-
 struct checkout_opts {
        int patch_mode;
        int quiet;
@@ -876,7 +858,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb)
        }
 
        if (starts_with(var, "submodule."))
-               return parse_submodule_config_option(var, value);
+               return submodule_config(var, value, NULL);
 
        return git_xmerge_config(var, value, NULL);
 }
@@ -1184,9 +1166,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                                N_("second guess 'git checkout <no-such-branch>'")),
                OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
                         N_("do not check if another worktree is holding the given ref")),
-               { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules,
+               { OPTION_CALLBACK, 0, "recurse-submodules", NULL,
                            "checkout", "control recursive updating of submodules",
-                           PARSE_OPT_OPTARG, option_parse_recurse_submodules },
+                           PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
                OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
                OPT_END(),
        };
@@ -1217,12 +1199,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
        }
 
-       if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
-               git_config(submodule_config, NULL);
-               if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT)
-                       set_config_update_recurse_submodules(recurse_submodules);
-       }
-
        if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
                die(_("-b, -B and --orphan are mutually exclusive"));
 
index 142bf668cffe814006fae791f1bdc6b20fe6f366..ed954134d2dd03242a06eef88bcaec71cc41ffe9 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"
index 743f16ae2aad7d71789f2b38287aea13cf29fc26..08b5cc433c6fcad5eea2dfc3321aea28a599d51f 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "parse-options.h"
 #include "fetch-pack.h"
@@ -360,7 +361,7 @@ static void copy_alternates(struct strbuf *src, struct strbuf *dst,
         * to turn entries with paths relative to the original
         * absolute, so that they can be used in the new repository.
         */
-       FILE *in = fopen(src->buf, "r");
+       FILE *in = xfopen(src->buf, "r");
        struct strbuf line = STRBUF_INIT;
 
        while (strbuf_getline(&line, in) != EOF) {
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 78ef319a2418066a34f1f3c47049b7500f3f0f07..021070e693e78fe49a168f842f64aeea73de4a8b 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "cache-tree.h"
 #include "color.h"
@@ -1700,10 +1701,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                if (!reflog_msg)
                        reflog_msg = "commit (merge)";
                pptr = commit_list_append(current_head, pptr);
-               fp = fopen(git_path_merge_head(), "r");
-               if (fp == NULL)
-                       die_errno(_("could not open '%s' for reading"),
-                                 git_path_merge_head());
+               fp = xfopen(git_path_merge_head(), "r");
                while (strbuf_getline_lf(&m, fp) != EOF) {
                        struct commit *parent;
 
@@ -1810,7 +1808,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                cfg = init_copy_notes_for_rewrite("amend");
                if (cfg) {
                        /* we are amending, so current_head is not NULL */
-                       copy_note_for_rewrite(cfg, current_head->object.oid.hash, oid.hash);
+                       copy_note_for_rewrite(cfg, &current_head->object.oid, &oid);
                        finish_copy_notes_for_rewrite(cfg, "Notes added by 'git commit --amend'");
                }
                run_rewrite_hook(&current_head->object.oid, &oid);
index 7f6c25d4d95b37f7785e0b6872d059095548c87f..82db29fae71551a44150c64a4c1187ef4ebd572a 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"
@@ -242,8 +243,8 @@ static int get_value(const char *key_, const char *regex_)
                }
        }
 
-       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 +321,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 +353,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 +442,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 +539,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 +587,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 0412fa00f0c85af6e7d3b4f802d6aeecf0c1ae16..879acfbcda75141d3022e9b285e191977a06ba3d 100644 (file)
@@ -10,9 +10,9 @@ int cmd_credential(int argc, const char **argv, const char *prefix)
        const char *op;
        struct credential c = CREDENTIAL_INIT;
 
-       op = argv[1];
-       if (!op)
+       if (argc != 2 || !strcmp(argv[1], "-h"))
                usage(usage_msg);
+       op = argv[1];
 
        if (credential_read(&c, stdin) < 0)
                die("unable to read credential from stdin");
index 893c8789f4f563c58041040740384322e6ea205b..70eb1446089583cd859ea1f05b260283cd78067f 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "commit.h"
 #include "tag.h"
index a572da9d5152ddf541f71e1aaf8abdb3c98f8ffe..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"
@@ -20,6 +21,9 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
        int result;
        unsigned options = 0;
 
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(diff_files_usage);
+
        git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
        init_revisions(&rev, prefix);
        gitmodules_config();
index f084826a293f96870d0cf6be05e3e346672fc5dc..185e6f9b582fdcf15072038b570463a0cfb1bbf2 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "diff.h"
 #include "commit.h"
 #include "revision.h"
@@ -17,6 +18,9 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
        int i;
        int result;
 
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(diff_cache_usage);
+
        git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
        init_revisions(&rev, prefix);
        gitmodules_config();
index e401112045023e990537a4ffe25c19487b31a30b..31d2cb410738d335d9f6431d6901ea1c0f8b67ff 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "diff.h"
 #include "commit.h"
 #include "log-tree.h"
@@ -7,7 +8,7 @@
 
 static struct rev_info log_tree_opt;
 
-static int diff_tree_commit_sha1(const struct object_id *oid)
+static int diff_tree_commit_oid(const struct object_id *oid)
 {
        struct commit *commit = lookup_commit_reference(oid);
        if (!commit)
@@ -49,8 +50,8 @@ static int stdin_diff_trees(struct tree *tree1, const char *p)
                return -1;
        printf("%s %s\n", oid_to_hex(&tree1->object.oid),
                          oid_to_hex(&tree2->object.oid));
-       diff_tree_sha1(tree1->object.oid.hash, tree2->object.oid.hash,
-                      "", &log_tree_opt.diffopt);
+       diff_tree_oid(&tree1->object.oid, &tree2->object.oid,
+                     "", &log_tree_opt.diffopt);
        log_tree_diff_flush(&log_tree_opt);
        return 0;
 }
@@ -98,13 +99,15 @@ static void diff_tree_tweak_rev(struct rev_info *rev, struct setup_revision_opt
 
 int cmd_diff_tree(int argc, const char **argv, const char *prefix)
 {
-       int nr_sha1;
        char line[1000];
        struct object *tree1, *tree2;
        static struct rev_info *opt = &log_tree_opt;
        struct setup_revision_opt s_r_opt;
        int read_stdin = 0;
 
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(diff_tree_usage);
+
        git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
        init_revisions(opt, prefix);
        gitmodules_config();
@@ -128,19 +131,20 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
        }
 
        /*
-        * NOTE! We expect "a ^b" to be equal to "a..b", so we
-        * reverse the order of the objects if the second one
-        * is marked UNINTERESTING.
+        * NOTE!  We expect "a..b" to expand to "^a b" but it is
+        * perfectly valid for revision range parser to yield "b ^a",
+        * which means the same thing. If we get the latter, i.e. the
+        * second one is marked UNINTERESTING, we recover the original
+        * order the user gave, i.e. "a..b", by swapping the trees.
         */
-       nr_sha1 = opt->pending.nr;
-       switch (nr_sha1) {
+       switch (opt->pending.nr) {
        case 0:
                if (!read_stdin)
                        usage(diff_tree_usage);
                break;
        case 1:
                tree1 = opt->pending.objects[0].item;
-               diff_tree_commit_sha1(&tree1->oid);
+               diff_tree_commit_oid(&tree1->oid);
                break;
        case 2:
                tree1 = opt->pending.objects[0].item;
@@ -148,9 +152,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
                if (tree2->flags & UNINTERESTING) {
                        SWAP(tree2, tree1);
                }
-               diff_tree_sha1(tree1->oid.hash,
-                              tree2->oid.hash,
-                              "", &opt->diffopt);
+               diff_tree_oid(&tree1->oid, &tree2->oid, "", &opt->diffopt);
                log_tree_diff_flush(opt);
                break;
        }
index 0c8f86e40da6537d57f5ed6ca0ecdd005e29c8f5..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"
@@ -56,8 +57,8 @@ static void stuff_change(struct diff_options *opt,
 
        one = alloc_filespec(old_path);
        two = alloc_filespec(new_path);
-       fill_filespec(one, old_oid->hash, old_oid_valid, old_mode);
-       fill_filespec(two, new_oid->hash, new_oid_valid, new_mode);
+       fill_filespec(one, old_oid, old_oid_valid, old_mode);
+       fill_filespec(two, new_oid, new_oid_valid, new_mode);
 
        diff_queue(&diff_queued_diff, one, two);
 }
@@ -174,7 +175,7 @@ static int builtin_diff_tree(struct rev_info *revs,
                swap = 1;
        oid[swap] = &ent0->item->oid;
        oid[1 - swap] = &ent1->item->oid;
-       diff_tree_sha1(oid[0]->hash, oid[1]->hash, "", &revs->diffopt);
+       diff_tree_oid(oid[0], oid[1], "", &revs->diffopt);
        log_tree_diff_flush(revs);
        return 0;
 }
@@ -194,7 +195,7 @@ static int builtin_diff_combined(struct rev_info *revs,
                revs->dense_combined_merges = revs->combine_merges = 1;
        for (i = 1; i < ents; i++)
                oid_array_append(&parents, &ent[i].item->oid);
-       diff_tree_combined(ent[0].item->oid.hash, &parents,
+       diff_tree_combined(&ent[0].item->oid, &parents,
                           revs->dense_combined_merges, revs);
        oid_array_clear(&parents);
        return 0;
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 24e29ad7eab5edc0964a51f32602b062daabb907..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"
@@ -562,12 +563,12 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
            get_object_mark(&commit->parents->item->object) != 0 &&
            !full_tree) {
                parse_commit_or_die(commit->parents->item);
-               diff_tree_sha1(commit->parents->item->tree->object.oid.hash,
-                              commit->tree->object.oid.hash, "", &rev->diffopt);
+               diff_tree_oid(&commit->parents->item->tree->object.oid,
+                             &commit->tree->object.oid, "", &rev->diffopt);
        }
        else
-               diff_root_tree_sha1(commit->tree->object.oid.hash,
-                                   "", &rev->diffopt);
+               diff_root_tree_oid(&commit->tree->object.oid,
+                                  "", &rev->diffopt);
 
        /* Export the referenced blobs, and remember the marks. */
        for (i = 0; i < diff_queued_diff.nr; i++)
@@ -907,9 +908,7 @@ static void export_marks(char *file)
 static void import_marks(char *input_file)
 {
        char line[512];
-       FILE *f = fopen(input_file, "r");
-       if (!f)
-               die_errno("cannot read '%s'", input_file);
+       FILE *f = xfopen(input_file, "r");
 
        while (fgets(line, sizeof(line), f)) {
                uint32_t mark;
index 47708451bc5e124f9c6da4de60cc476a5d2c1f10..16cf8421ce4cc2221e6ed59110928328693481fb 100644 (file)
@@ -2,6 +2,7 @@
  * "git fetch"
  */
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "commit.h"
 #include "builtin.h"
@@ -73,6 +74,13 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
                fetch_prune_config = git_config_bool(k, v);
                return 0;
        }
+
+       if (!strcmp(k, "submodule.recurse")) {
+               int r = git_config_bool(k, v) ?
+                       RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
+               recurse_submodules = r;
+       }
+
        return git_default_config(k, v, cb);
 }
 
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 cb2ba6cd1be46635ca8416a7d3f2b006f964190b..87c675689986413f4c2ace09701adccf6e836942 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "tree.h"
 #include "blob.h"
@@ -280,8 +281,7 @@ static void check_unreachable_object(struct object *obj)
                                free(filename);
                                return;
                        }
-                       if (!(f = fopen(filename, "w")))
-                               die_errno("Could not open '%s'", filename);
+                       f = xfopen(filename, "w");
                        if (obj->type == OBJ_BLOB) {
                                if (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1))
                                        die_errno("Could not write '%s'", filename);
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 7df9c253eebb3053693769d14efe0551393dfd4d..f61a9d938b44424414812c57eecc309bd563f4b3 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2006 Junio C Hamano
  */
 #include "cache.h"
+#include "config.h"
 #include "blob.h"
 #include "tree.h"
 #include "commit.h"
@@ -224,7 +225,8 @@ static void start_threads(struct grep_opt *opt)
                int err;
                struct grep_opt *o = grep_opt_dup(opt);
                o->output = strbuf_out;
-               o->debug = 0;
+               if (i)
+                       o->debug = 0;
                compile_grep_patterns(o);
                err = pthread_create(&threads[i], NULL, run, o);
 
@@ -302,6 +304,9 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)
 #endif
        }
 
+       if (!strcmp(var, "submodule.recurse"))
+               recurse_submodules = git_config_bool(var, value);
+
        return st;
 }
 
@@ -338,7 +343,7 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
 
 #ifndef NO_PTHREADS
        if (num_threads) {
-               add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, oid);
+               add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid);
                strbuf_release(&pathbuf);
                return 0;
        } else
@@ -347,7 +352,7 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
                struct grep_source gs;
                int hit;
 
-               grep_source_init(&gs, GREP_SOURCE_SHA1, pathbuf.buf, path, oid);
+               grep_source_init(&gs, GREP_SOURCE_OID, pathbuf.buf, path, oid);
                strbuf_release(&pathbuf);
                hit = grep_source(opt, &gs);
 
@@ -583,7 +588,7 @@ static int grep_submodule_launch(struct grep_opt *opt,
         * with the object's name: 'tree-name:filename'.  In order to
         * provide uniformity of output we want to pass the name of the
         * parent project's object name to the submodule so the submodule can
-        * prefix its output with the parent's name and not its own SHA1.
+        * prefix its output with the parent's name and not its own OID.
         */
        if (gs->identifier && end_of_base)
                argv_array_pushf(&cp.args, "--parent-basename=%.*s",
@@ -596,12 +601,12 @@ static int grep_submodule_launch(struct grep_opt *opt,
                 * If there is a tree identifier for the submodule, add the
                 * rev after adding the submodule options but before the
                 * pathspecs.  To do this we listen for the '--' and insert the
-                * sha1 before pushing the '--' onto the child process argv
+                * oid before pushing the '--' onto the child process argv
                 * array.
                 */
                if (gs->identifier &&
                    !strcmp("--", submodule_options.argv[i])) {
-                       argv_array_push(&cp.args, sha1_to_hex(gs->identifier));
+                       argv_array_push(&cp.args, oid_to_hex(gs->identifier));
                }
 
                argv_array_push(&cp.args, submodule_options.argv[i]);
@@ -631,11 +636,11 @@ static int grep_submodule_launch(struct grep_opt *opt,
 
 /*
  * Prep grep structures for a submodule grep
- * sha1: the sha1 of the submodule or NULL if using the working tree
+ * oid: the oid of the submodule or NULL if using the working tree
  * filename: name of the submodule including tree name of parent
  * path: location of the submodule
  */
-static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
+static int grep_submodule(struct grep_opt *opt, const struct object_id *oid,
                          const char *filename, const char *path)
 {
        if (!is_submodule_initialized(path))
@@ -645,7 +650,7 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
                 * If searching history, check for the presense of the
                 * submodule's gitdir before skipping the submodule.
                 */
-               if (sha1) {
+               if (oid) {
                        const struct submodule *sub =
                                        submodule_from_path(null_sha1, path);
                        if (sub)
@@ -660,7 +665,7 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
 
 #ifndef NO_PTHREADS
        if (num_threads) {
-               add_work(opt, GREP_SOURCE_SUBMODULE, filename, path, sha1);
+               add_work(opt, GREP_SOURCE_SUBMODULE, filename, path, oid);
                return 0;
        } else
 #endif
@@ -669,7 +674,7 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
                int hit;
 
                grep_source_init(&gs, GREP_SOURCE_SUBMODULE,
-                                filename, path, sha1);
+                                filename, path, oid);
                hit = grep_submodule_launch(opt, &gs);
 
                grep_source_clear(&gs);
@@ -788,7 +793,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                                         check_attr);
                        free(data);
                } else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
-                       hit |= grep_submodule(opt, entry.oid->hash, base->buf,
+                       hit |= grep_submodule(opt, entry.oid, base->buf,
                                              base->buf + tn_len);
                }
 
@@ -1167,8 +1172,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        if (!opt.fixed && opt.ignore_case)
                opt.regflags |= REG_ICASE;
 
-       compile_grep_patterns(&opt);
-
        /*
         * We have to find "--" in a separate pass, because its presence
         * influences how we will parse arguments that come before it.
@@ -1241,12 +1244,23 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                num_threads = GREP_NUM_THREADS_DEFAULT;
        else if (num_threads < 0)
                die(_("invalid number of threads specified (%d)"), num_threads);
+       if (num_threads == 1)
+               num_threads = 0;
 #else
        if (num_threads)
                warning(_("no threads support, ignoring --threads"));
        num_threads = 0;
 #endif
 
+       if (!num_threads)
+               /*
+                * The compiled patterns on the main path are only
+                * used when not using threading. Otherwise
+                * start_threads() below calls compile_grep_patterns()
+                * for each thread.
+                */
+               compile_grep_patterns(&opt);
+
 #ifndef NO_PTHREADS
        if (num_threads) {
                if (!(opt.name_only || opt.unmatch_name_only || opt.count)
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..edc1a91d89b308b1e164c48c1dfb06c8f6ebf0d1 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "delta.h"
 #include "pack.h"
 #include "csum-file.h"
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 e89ec941ce2c97de7f8233a5e7e6f9010fabdb64..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"
@@ -846,8 +847,10 @@ static int open_next_file(struct commit *commit, const char *subject,
        if (output_directory) {
                strbuf_addstr(&filename, output_directory);
                if (filename.len >=
-                   PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len)
+                   PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len) {
+                       strbuf_release(&filename);
                        return error(_("name of output directory is too long"));
+               }
                strbuf_complete(&filename, '/');
        }
 
@@ -861,8 +864,11 @@ static int open_next_file(struct commit *commit, const char *subject,
        if (!quiet)
                printf("%s\n", filename.buf + outdir_offset);
 
-       if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL)
-               return error(_("Cannot open patch file %s"), filename.buf);
+       if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) {
+               error_errno(_("Cannot open patch file %s"), filename.buf);
+               strbuf_release(&filename);
+               return -1;
+       }
 
        strbuf_release(&filename);
        return 0;
@@ -1047,9 +1053,9 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
 
        diff_setup_done(&opts);
 
-       diff_tree_sha1(origin->tree->object.oid.hash,
-                      head->tree->object.oid.hash,
-                      "", &opts);
+       diff_tree_oid(&origin->tree->object.oid,
+                     &head->tree->object.oid,
+                     "", &opts);
        diffcore_std(&opts);
        diff_flush(&opts);
 
@@ -1358,7 +1364,7 @@ static void prepare_bases(struct base_tree_info *bases,
                struct object_id *patch_id;
                if (commit->util)
                        continue;
-               if (commit_patch_id(commit, &diffopt, oid.hash, 0))
+               if (commit_patch_id(commit, &diffopt, &oid, 0))
                        die(_("cannot get patch id"));
                ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id);
                patch_id = bases->patch_id + bases->nr_patch_id;
index cdc1cfdd26a95c54cc23717ce53c20a9d1607c90..b12d0bb61240890b3145baa8f051c83005b97dbe 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "config.h"
 #include "quote.h"
 #include "dir.h"
 #include "builtin.h"
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 a4a098f40f8e3e61c3f8b730a6b22a83c3c23566..900bafdb45d0b28ab5497cfd251535266fc92be5 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "parse-options.h"
 #include "builtin.h"
 #include "lockfile.h"
@@ -415,7 +416,7 @@ static void finish(struct commit *head_commit,
                        DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
                opts.detect_rename = DIFF_DETECT_RENAME;
                diff_setup_done(&opts);
-               diff_tree_sha1(head->hash, new_head->hash, "", &opts);
+               diff_tree_oid(head, new_head, "", &opts);
                diffcore_std(&opts);
                diff_flush(&opts);
        }
@@ -839,9 +840,7 @@ static int suggest_conflicts(void)
        struct strbuf msgbuf = STRBUF_INIT;
 
        filename = git_path_merge_msg();
-       fp = fopen(filename, "a");
-       if (!fp)
-               die_errno(_("Could not open '%s' for writing"), filename);
+       fp = xfopen(filename, "a");
 
        append_conflicts_hint(&msgbuf);
        fputs(msgbuf.buf, fp);
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 7fc7e66e8500b82cbfecc21a1dce77e09de28ab0..e21715f1d0874171bcda2486adb4d27ea5cbbc99 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 7196bff0eb2454eee86f87241706523c0266e66e..77573cf1ea8cb4d998597e265263487e22fde592 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "notes.h"
 #include "blob.h"
@@ -109,11 +110,11 @@ static void free_note_data(struct note_data *d)
        strbuf_release(&d->buf);
 }
 
-static int list_each_note(const unsigned char *object_sha1,
-               const unsigned char *note_sha1, char *note_path,
+static int list_each_note(const struct object_id *object_oid,
+               const struct object_id *note_oid, char *note_path,
                void *cb_data)
 {
-       printf("%s %s\n", sha1_to_hex(note_sha1), sha1_to_hex(object_sha1));
+       printf("%s %s\n", oid_to_hex(note_oid), oid_to_hex(object_oid));
        return 0;
 }
 
@@ -129,10 +130,10 @@ static void copy_obj_to_fd(int fd, const unsigned char *sha1)
        }
 }
 
-static void write_commented_object(int fd, const unsigned char *object)
+static void write_commented_object(int fd, const struct object_id *object)
 {
        const char *show_args[5] =
-               {"show", "--stat", "--no-notes", sha1_to_hex(object), NULL};
+               {"show", "--stat", "--no-notes", oid_to_hex(object), NULL};
        struct child_process show = CHILD_PROCESS_INIT;
        struct strbuf buf = STRBUF_INIT;
        struct strbuf cbuf = STRBUF_INIT;
@@ -145,7 +146,7 @@ static void write_commented_object(int fd, const unsigned char *object)
        show.git_cmd = 1;
        if (start_command(&show))
                die(_("unable to start 'show' for object '%s'"),
-                   sha1_to_hex(object));
+                   oid_to_hex(object));
 
        if (strbuf_read(&buf, show.out, 0) < 0)
                die_errno(_("could not read 'show' output"));
@@ -157,10 +158,10 @@ static void write_commented_object(int fd, const unsigned char *object)
 
        if (finish_command(&show))
                die(_("failed to finish 'show' for object '%s'"),
-                   sha1_to_hex(object));
+                   oid_to_hex(object));
 }
 
-static void prepare_note_data(const unsigned char *object, struct note_data *d,
+static void prepare_note_data(const struct object_id *object, struct note_data *d,
                const unsigned char *old_note)
 {
        if (d->use_editor || !d->given) {
@@ -243,16 +244,16 @@ static int parse_reuse_arg(const struct option *opt, const char *arg, int unset)
 {
        struct note_data *d = opt->value;
        char *buf;
-       unsigned char object[20];
+       struct object_id object;
        enum object_type type;
        unsigned long len;
 
        if (d->buf.len)
                strbuf_addch(&d->buf, '\n');
 
-       if (get_sha1(arg, object))
+       if (get_oid(arg, &object))
                die(_("failed to resolve '%s' as a valid ref."), arg);
-       if (!(buf = read_sha1_file(object, &type, &len))) {
+       if (!(buf = read_sha1_file(object.hash, &type, &len))) {
                free(buf);
                die(_("failed to read object '%s'."), arg);
        }
@@ -292,7 +293,7 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
        }
 
        while (strbuf_getline_lf(&buf, stdin) != EOF) {
-               unsigned char from_obj[20], to_obj[20];
+               struct object_id from_obj, to_obj;
                struct strbuf **split;
                int err;
 
@@ -301,15 +302,15 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
                        die(_("malformed input line: '%s'."), buf.buf);
                strbuf_rtrim(split[0]);
                strbuf_rtrim(split[1]);
-               if (get_sha1(split[0]->buf, from_obj))
+               if (get_oid(split[0]->buf, &from_obj))
                        die(_("failed to resolve '%s' as a valid ref."), split[0]->buf);
-               if (get_sha1(split[1]->buf, to_obj))
+               if (get_oid(split[1]->buf, &to_obj))
                        die(_("failed to resolve '%s' as a valid ref."), split[1]->buf);
 
                if (rewrite_cmd)
-                       err = copy_note_for_rewrite(c, from_obj, to_obj);
+                       err = copy_note_for_rewrite(c, &from_obj, &to_obj);
                else
-                       err = copy_note(t, from_obj, to_obj, force,
+                       err = copy_note(t, &from_obj, &to_obj, force,
                                        combine_notes_overwrite);
 
                if (err) {
@@ -352,8 +353,8 @@ static struct notes_tree *init_notes_check(const char *subcommand,
 static int list(int argc, const char **argv, const char *prefix)
 {
        struct notes_tree *t;
-       unsigned char object[20];
-       const unsigned char *note;
+       struct object_id object;
+       const struct object_id *note;
        int retval = -1;
        struct option options[] = {
                OPT_END()
@@ -370,15 +371,15 @@ static int list(int argc, const char **argv, const char *prefix)
 
        t = init_notes_check("list", 0);
        if (argc) {
-               if (get_sha1(argv[0], object))
+               if (get_oid(argv[0], &object))
                        die(_("failed to resolve '%s' as a valid ref."), argv[0]);
-               note = get_note(t, object);
+               note = get_note(t, &object);
                if (note) {
-                       puts(sha1_to_hex(note));
+                       puts(oid_to_hex(note));
                        retval = 0;
                } else
                        retval = error(_("no note found for object %s."),
-                                      sha1_to_hex(object));
+                                      oid_to_hex(&object));
        } else
                retval = for_each_note(t, 0, list_each_note, NULL);
 
@@ -393,8 +394,8 @@ static int add(int argc, const char **argv, const char *prefix)
        int force = 0, allow_empty = 0;
        const char *object_ref;
        struct notes_tree *t;
-       unsigned char object[20], new_note[20];
-       const unsigned char *note;
+       struct object_id object, new_note;
+       const struct object_id *note;
        struct note_data d = { 0, 0, NULL, STRBUF_INIT };
        struct option options[] = {
                { OPTION_CALLBACK, 'm', "message", &d, N_("message"),
@@ -425,11 +426,11 @@ static int add(int argc, const char **argv, const char *prefix)
 
        object_ref = argc > 1 ? argv[1] : "HEAD";
 
-       if (get_sha1(object_ref, object))
+       if (get_oid(object_ref, &object))
                die(_("failed to resolve '%s' as a valid ref."), object_ref);
 
        t = init_notes_check("add", NOTES_INIT_WRITABLE);
-       note = get_note(t, object);
+       note = get_note(t, &object);
 
        if (note) {
                if (!force) {
@@ -439,7 +440,7 @@ static int add(int argc, const char **argv, const char *prefix)
                                return error(_("Cannot add notes. "
                                        "Found existing notes for object %s. "
                                        "Use '-f' to overwrite existing notes"),
-                                       sha1_to_hex(object));
+                                       oid_to_hex(&object));
                        }
                        /*
                         * Redirect to "edit" subcommand.
@@ -452,19 +453,19 @@ static int add(int argc, const char **argv, const char *prefix)
                        return append_edit(argc, argv, prefix);
                }
                fprintf(stderr, _("Overwriting existing notes for object %s\n"),
-                       sha1_to_hex(object));
+                       oid_to_hex(&object));
        }
 
-       prepare_note_data(object, &d, note);
+       prepare_note_data(&object, &d, note->hash);
        if (d.buf.len || allow_empty) {
-               write_note_data(&d, new_note);
-               if (add_note(t, object, new_note, combine_notes_overwrite))
+               write_note_data(&d, new_note.hash);
+               if (add_note(t, &object, &new_note, combine_notes_overwrite))
                        die("BUG: combine_notes_overwrite failed");
                commit_notes(t, "Notes added by 'git notes add'");
        } else {
                fprintf(stderr, _("Removing note for object %s\n"),
-                       sha1_to_hex(object));
-               remove_note(t, object);
+                       oid_to_hex(&object));
+               remove_note(t, object.hash);
                commit_notes(t, "Notes removed by 'git notes add'");
        }
 
@@ -476,9 +477,9 @@ static int add(int argc, const char **argv, const char *prefix)
 static int copy(int argc, const char **argv, const char *prefix)
 {
        int retval = 0, force = 0, from_stdin = 0;
-       const unsigned char *from_note, *note;
+       const struct object_id *from_note, *note;
        const char *object_ref;
-       unsigned char object[20], from_obj[20];
+       struct object_id object, from_obj;
        struct notes_tree *t;
        const char *rewrite_cmd = NULL;
        struct option options[] = {
@@ -511,37 +512,37 @@ static int copy(int argc, const char **argv, const char *prefix)
                usage_with_options(git_notes_copy_usage, options);
        }
 
-       if (get_sha1(argv[0], from_obj))
+       if (get_oid(argv[0], &from_obj))
                die(_("failed to resolve '%s' as a valid ref."), argv[0]);
 
        object_ref = 1 < argc ? argv[1] : "HEAD";
 
-       if (get_sha1(object_ref, object))
+       if (get_oid(object_ref, &object))
                die(_("failed to resolve '%s' as a valid ref."), object_ref);
 
        t = init_notes_check("copy", NOTES_INIT_WRITABLE);
-       note = get_note(t, object);
+       note = get_note(t, &object);
 
        if (note) {
                if (!force) {
                        retval = error(_("Cannot copy notes. Found existing "
                                       "notes for object %s. Use '-f' to "
                                       "overwrite existing notes"),
-                                      sha1_to_hex(object));
+                                      oid_to_hex(&object));
                        goto out;
                }
                fprintf(stderr, _("Overwriting existing notes for object %s\n"),
-                       sha1_to_hex(object));
+                       oid_to_hex(&object));
        }
 
-       from_note = get_note(t, from_obj);
+       from_note = get_note(t, &from_obj);
        if (!from_note) {
                retval = error(_("missing notes on source object %s. Cannot "
-                              "copy."), sha1_to_hex(from_obj));
+                              "copy."), oid_to_hex(&from_obj));
                goto out;
        }
 
-       if (add_note(t, object, from_note, combine_notes_overwrite))
+       if (add_note(t, &object, from_note, combine_notes_overwrite))
                die("BUG: combine_notes_overwrite failed");
        commit_notes(t, "Notes added by 'git notes copy'");
 out:
@@ -554,8 +555,8 @@ static int append_edit(int argc, const char **argv, const char *prefix)
        int allow_empty = 0;
        const char *object_ref;
        struct notes_tree *t;
-       unsigned char object[20], new_note[20];
-       const unsigned char *note;
+       struct object_id object, new_note;
+       const struct object_id *note;
        char *logmsg;
        const char * const *usage;
        struct note_data d = { 0, 0, NULL, STRBUF_INIT };
@@ -594,19 +595,19 @@ static int append_edit(int argc, const char **argv, const char *prefix)
 
        object_ref = 1 < argc ? argv[1] : "HEAD";
 
-       if (get_sha1(object_ref, object))
+       if (get_oid(object_ref, &object))
                die(_("failed to resolve '%s' as a valid ref."), object_ref);
 
        t = init_notes_check(argv[0], NOTES_INIT_WRITABLE);
-       note = get_note(t, object);
+       note = get_note(t, &object);
 
-       prepare_note_data(object, &d, edit ? note : NULL);
+       prepare_note_data(&object, &d, edit && note ? note->hash : NULL);
 
        if (note && !edit) {
                /* Append buf to previous note contents */
                unsigned long size;
                enum object_type type;
-               char *prev_buf = read_sha1_file(note, &type, &size);
+               char *prev_buf = read_sha1_file(note->hash, &type, &size);
 
                strbuf_grow(&d.buf, size + 1);
                if (d.buf.len && prev_buf && size)
@@ -617,14 +618,14 @@ static int append_edit(int argc, const char **argv, const char *prefix)
        }
 
        if (d.buf.len || allow_empty) {
-               write_note_data(&d, new_note);
-               if (add_note(t, object, new_note, combine_notes_overwrite))
+               write_note_data(&d, new_note.hash);
+               if (add_note(t, &object, &new_note, combine_notes_overwrite))
                        die("BUG: combine_notes_overwrite failed");
                logmsg = xstrfmt("Notes added by 'git notes %s'", argv[0]);
        } else {
                fprintf(stderr, _("Removing note for object %s\n"),
-                       sha1_to_hex(object));
-               remove_note(t, object);
+                       oid_to_hex(&object));
+               remove_note(t, object.hash);
                logmsg = xstrfmt("Notes removed by 'git notes %s'", argv[0]);
        }
        commit_notes(t, logmsg);
@@ -639,8 +640,8 @@ static int show(int argc, const char **argv, const char *prefix)
 {
        const char *object_ref;
        struct notes_tree *t;
-       unsigned char object[20];
-       const unsigned char *note;
+       struct object_id object;
+       const struct object_id *note;
        int retval;
        struct option options[] = {
                OPT_END()
@@ -656,17 +657,17 @@ static int show(int argc, const char **argv, const char *prefix)
 
        object_ref = argc ? argv[0] : "HEAD";
 
-       if (get_sha1(object_ref, object))
+       if (get_oid(object_ref, &object))
                die(_("failed to resolve '%s' as a valid ref."), object_ref);
 
        t = init_notes_check("show", 0);
-       note = get_note(t, object);
+       note = get_note(t, &object);
 
        if (!note)
                retval = error(_("no note found for object %s."),
-                              sha1_to_hex(object));
+                              oid_to_hex(&object));
        else {
-               const char *show_args[3] = {"show", sha1_to_hex(note), NULL};
+               const char *show_args[3] = {"show", oid_to_hex(note), NULL};
                retval = execv_git_cmd(show_args);
        }
        free_notes(t);
@@ -726,7 +727,7 @@ static int merge_commit(struct notes_merge_options *o)
        if (!o->local_ref)
                die(_("failed to resolve NOTES_MERGE_REF"));
 
-       if (notes_merge_commit(o, t, partial, oid.hash))
+       if (notes_merge_commit(o, t, partial, &oid))
                die(_("failed to finalize notes merge"));
 
        /* Reuse existing commit message in reflog message */
@@ -762,7 +763,7 @@ static int git_config_get_notes_strategy(const char *key,
 static int merge(int argc, const char **argv, const char *prefix)
 {
        struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT;
-       unsigned char result_sha1[20];
+       struct object_id result_oid;
        struct notes_tree *t;
        struct notes_merge_options o;
        int do_merge = 0, do_commit = 0, do_abort = 0;
@@ -844,16 +845,16 @@ static int merge(int argc, const char **argv, const char *prefix)
                    remote_ref.buf, default_notes_ref());
        strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */
 
-       result = notes_merge(&o, t, result_sha1);
+       result = notes_merge(&o, t, &result_oid);
 
-       if (result >= 0) /* Merge resulted (trivially) in result_sha1 */
+       if (result >= 0) /* Merge resulted (trivially) in result_oid */
                /* Update default notes ref with new commit */
-               update_ref(msg.buf, default_notes_ref(), result_sha1, NULL,
+               update_ref(msg.buf, default_notes_ref(), result_oid.hash, NULL,
                           0, UPDATE_REFS_DIE_ON_ERR);
        else { /* Merge has unresolved conflicts */
                const struct worktree *wt;
                /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */
-               update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL,
+               update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_oid.hash, NULL,
                           0, UPDATE_REFS_DIE_ON_ERR);
                /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */
                wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref());
@@ -880,10 +881,10 @@ static int merge(int argc, const char **argv, const char *prefix)
 static int remove_one_note(struct notes_tree *t, const char *name, unsigned flag)
 {
        int status;
-       unsigned char sha1[20];
-       if (get_sha1(name, sha1))
+       struct object_id oid;
+       if (get_oid(name, &oid))
                return error(_("Failed to resolve '%s' as a valid ref."), name);
-       status = remove_note(t, sha1);
+       status = remove_note(t, oid.hash);
        if (status)
                fprintf(stderr, _("Object %s has no note\n"), name);
        else
index f672225def033595602bc4ff91ee26edd9804944..d5e96ed2d0ce0d74a40961f6729896722dacf9a2 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "attr.h"
 #include "object.h"
 #include "blob.h"
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 da8b60fc85e93da880fb955992b8b753715fafda..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"
@@ -337,8 +338,7 @@ static void get_merge_heads(struct oid_array *merge_heads)
        struct strbuf sb = STRBUF_INIT;
        struct object_id oid;
 
-       if (!(fp = fopen(filename, "r")))
-               die_errno(_("could not open '%s' for reading"), filename);
+       fp = xfopen(filename, "r");
        while (strbuf_getline_lf(&sb, fp) != EOF) {
                if (get_oid_hex(sb.buf, &oid))
                        continue;  /* invalid line: does not start with SHA1 */
index a597759d8fac205f41c406d0a0e32f9240941190..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"
@@ -498,6 +499,10 @@ static int git_push_config(const char *k, const char *v, void *cb)
                const char *value;
                if (!git_config_get_value("push.recursesubmodules", &value))
                        recurse_submodules = parse_push_recurse_submodules_arg(k, value);
+       } else if (!strcmp(k, "submodule.recurse")) {
+               int val = git_config_bool(k, v) ?
+                       RECURSE_SUBMODULES_ON_DEMAND : RECURSE_SUBMODULES_OFF;
+               recurse_submodules = val;
        }
 
        return git_default_config(k, v, NULL);
index 78d3193659e06b4969324153689f219f1cd1c1b3..d5f618d086365520fcf36ed8db110ba701ba37d3 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "object.h"
 #include "tree.h"
@@ -21,7 +22,6 @@
 static int nr_trees;
 static int read_empty;
 static struct tree *trees[MAX_UNPACK_TREES];
-static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
 
 static int list_tree(struct object_id *oid)
 {
@@ -99,21 +99,12 @@ static int debug_merge(const struct cache_entry * const *stages,
        return 0;
 }
 
-static int option_parse_recurse_submodules(const struct option *opt,
-                                          const char *arg, int unset)
+static int git_read_tree_config(const char *var, const char *value, void *cb)
 {
-       if (unset) {
-               recurse_submodules = RECURSE_SUBMODULES_OFF;
-               return 0;
-       }
-       if (arg)
-               recurse_submodules =
-                       parse_update_recurse_submodules_arg(opt->long_name,
-                                                           arg);
-       else
-               recurse_submodules = RECURSE_SUBMODULES_ON;
+       if (!strcmp(var, "submodule.recurse"))
+               return git_default_submodule_config(var, value, cb);
 
-       return 0;
+       return git_default_config(var, value, cb);
 }
 
 static struct lock_file lock_file;
@@ -157,9 +148,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
                         N_("skip applying sparse checkout filter")),
                OPT_BOOL(0, "debug-unpack", &opts.debug_unpack,
                         N_("debug unpack-trees")),
-               { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules,
+               { OPTION_CALLBACK, 0, "recurse-submodules", NULL,
                            "checkout", "control recursive updating of submodules",
-                           PARSE_OPT_OPTARG, option_parse_recurse_submodules },
+                           PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
                OPT_END()
        };
 
@@ -168,18 +159,14 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
        opts.src_index = &the_index;
        opts.dst_index = &the_index;
 
-       git_config(git_default_config, NULL);
+       git_config(git_read_tree_config, NULL);
 
        argc = parse_options(argc, argv, unused_prefix, read_tree_options,
                             read_tree_usage, 0);
 
-       hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
+       load_submodule_cache();
 
-       if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) {
-               gitmodules_config();
-               git_config(submodule_config, NULL);
-               set_config_update_recurse_submodules(RECURSE_SUBMODULES_ON);
-       }
+       hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
 
        prefix_set = opts.prefix ? 1 : 0;
        if (1 < opts.merge + opts.reset + prefix_set)
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 920c16dac025b0f5650b0f91511c22359d5bda2d..44cdc2dbd0cbf64be1672428e930223425ed7b04 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "commit.h"
 #include "refs.h"
index 11b48bfb41193387d53588c879ee50431f77b9cd..bfb21ba7d217bafaf3527af007cd4ac4658d36c5 100644 (file)
@@ -3,6 +3,9 @@
 #include "run-command.h"
 #include "pkt-line.h"
 
+static const char usage_msg[] =
+       "git remote-ext <remote> <url>";
+
 /*
  * URL syntax:
  *     'command [arg1 [arg2 [...]]]'   Invoke command with given arguments.
@@ -193,7 +196,7 @@ static int command_loop(const char *child)
 int cmd_remote_ext(int argc, const char **argv, const char *prefix)
 {
        if (argc != 3)
-               die("Expected two arguments");
+               usage(usage_msg);
 
        return command_loop(argv[2]);
 }
index 08d7121b6d118042a45086d2902769d282c062f8..91dfe07e06a1b9603dfd7a0d04f4b7866841d63f 100644 (file)
@@ -1,6 +1,9 @@
 #include "builtin.h"
 #include "transport.h"
 
+static const char usage_msg[] =
+       "git remote-fd <remote> <url>";
+
 /*
  * URL syntax:
  *     'fd::<inoutfd>[/<anything>]'            Read/write socket pair
@@ -57,7 +60,7 @@ int cmd_remote_fd(int argc, const char **argv, const char *prefix)
        char *end;
 
        if (argc != 3)
-               die("Expected two arguments");
+               usage(usage_msg);
 
        input_fd = (int)strtoul(argv[2], &end, 10);
 
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 c921bc976f2299adc39277a21a74abbcc0c100f7..80a15cf35f3fa5a1a7c038924a84e34fdc15aa0b 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 430602d102133d125009e8c8068ce5547c24cab7..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"
 #include "submodule.h"
 #include "submodule-config.h"
 
-static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
-
-static int option_parse_recurse_submodules(const struct option *opt,
-                                          const char *arg, int unset)
-{
-       if (unset) {
-               recurse_submodules = RECURSE_SUBMODULES_OFF;
-               return 0;
-       }
-       if (arg)
-               recurse_submodules =
-                       parse_update_recurse_submodules_arg(opt->long_name,
-                                                           arg);
-       else
-               recurse_submodules = RECURSE_SUBMODULES_ON;
-
-       return 0;
-}
-
 static const char * const git_reset_usage[] = {
        N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"),
        N_("git reset [-q] [<tree-ish>] [--] <paths>..."),
@@ -284,6 +266,14 @@ static int reset_refs(const char *rev, const struct object_id *oid)
        return update_ref_status;
 }
 
+static int git_reset_config(const char *var, const char *value, void *cb)
+{
+       if (!strcmp(var, "submodule.recurse"))
+               return git_default_submodule_config(var, value, cb);
+
+       return git_default_config(var, value, cb);
+}
+
 int cmd_reset(int argc, const char **argv, const char *prefix)
 {
        int reset_type = NONE, update_ref_status = 0, quiet = 0;
@@ -303,26 +293,22 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                                N_("reset HEAD, index and working tree"), MERGE),
                OPT_SET_INT(0, "keep", &reset_type,
                                N_("reset HEAD but keep local changes"), KEEP),
-               { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules,
+               { OPTION_CALLBACK, 0, "recurse-submodules", NULL,
                            "reset", "control recursive updating of submodules",
-                           PARSE_OPT_OPTARG, option_parse_recurse_submodules },
+                           PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
                OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
                OPT_BOOL('N', "intent-to-add", &intent_to_add,
                                N_("record only the fact that removed paths will be added later")),
                OPT_END()
        };
 
-       git_config(git_default_config, NULL);
+       git_config(git_reset_config, NULL);
 
        argc = parse_options(argc, argv, prefix, options, git_reset_usage,
                                                PARSE_OPT_KEEP_DASHDASH);
        parse_args(&pathspec, argv, prefix, patch_mode, &rev);
 
-       if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) {
-               gitmodules_config();
-               git_config(submodule_config, NULL);
-               set_config_update_recurse_submodules(RECURSE_SUBMODULES_ON);
-       }
+       load_submodule_cache();
 
        unborn = !strcmp(rev, "HEAD") && get_sha1("HEAD", oid.hash);
        if (unborn) {
index 718c6059c9f570d94b0bdba46d33ed1b065a34f7..95d84d5cda1bdb6a699bc74ad57f7f1910946440 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "diff.h"
 #include "revision.h"
@@ -277,6 +278,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
        int use_bitmap_index = 0;
        const char *show_progress = NULL;
 
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(rev_list_usage);
+
        git_config(git_default_config, NULL);
        init_revisions(&revs, prefix);
        revs.abbrev = DEFAULT_ABBREV;
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 7c323d01235bf8bbb341004c843761dad99590d2..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"
@@ -129,7 +130,7 @@ static int check_local_mod(struct object_id *head, int index_only)
                ce = active_cache[pos];
 
                if (lstat(ce->name, &st) < 0) {
-                       if (errno != ENOENT && errno != ENOTDIR)
+                       if (!is_missing_file_error(errno))
                                warning_errno(_("failed to stat '%s'"), ce->name);
                        /* It already vanished from the working tree */
                        continue;
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 4a6cc6f490f4e7b8a98adb362213535b6a9ae97d..e4cf1b5bb25e14b54e29d0b467e94a374ec9c9d5 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 8cc648d85b586752d39079e75cf81a4ee685b622..8517032b3e08ded36075ded55dac8ae219cfbc59 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "parse-options.h"
 #include "quote.h"
 #include "pathspec.h"
@@ -1221,9 +1222,8 @@ static struct cmd_struct commands[] = {
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 {
        int i;
-       if (argc < 2)
-               die(_("submodule--helper subcommand must be "
-                     "called with a subcommand"));
+       if (argc < 2 || !strcmp(argv[1], "-h"))
+               usage("git submodule--helper <command>");
 
        for (i = 0; i < ARRAY_SIZE(commands); i++) {
                if (!strcmp(argv[1], commands[i].cmd)) {
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..193f8b9d57f0759c38004fd1d99f660919ac30e3 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "object.h"
 #include "delta.h"
 #include "pack.h"
index ebfc09faa0d604218af8f5815af5e5fee5915158..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"
@@ -257,7 +258,7 @@ static int remove_one_path(const char *path)
  */
 static int process_lstat_error(const char *path, int err)
 {
-       if (err == ENOENT || err == ENOTDIR)
+       if (is_missing_file_error(err))
                return remove_one_path(path);
        return error("lstat(\"%s\"): %s", path, strerror(err));
 }
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 cde06977b78b1475925e4b6722b5ecdd834847d5..84532ae9a93e7fb526a6fd28901875b3a10f3ffa 100644 (file)
@@ -22,7 +22,7 @@ int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
        struct argv_array sent_argv = ARGV_ARRAY_INIT;
        const char *arg_cmd = "argument ";
 
-       if (argc != 2)
+       if (argc != 2 || !strcmp(argv[1], "-h"))
                usage(upload_archive_usage);
 
        if (!enter_repo(argv[1], 0))
@@ -76,6 +76,9 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
 {
        struct child_process writer = { argv };
 
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(upload_archive_usage);
+
        /*
         * Set up sideband subprocess.
         *
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..0c5476ee9de464cb0fae22c49775bc10efb0731b 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "builtin.h"
 #include "dir.h"
 #include "parse-options.h"
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 5a0e0a9e5d59a46b06058778c1f078a55e64edea..96055c222929e4ba307f3162b58740eccf165f2c 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -525,12 +525,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.
- */
-extern const char *discover_git_directory(struct strbuf *gitdir);
+ * 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 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);
@@ -1026,6 +1029,13 @@ static inline void oidcpy(struct object_id *dst, const struct object_id *src)
        hashcpy(dst->hash, src->hash);
 }
 
+static inline struct object_id *oiddup(const struct object_id *src)
+{
+       struct object_id *dst = xmalloc(sizeof(struct object_id));
+       oidcpy(dst, src);
+       return dst;
+}
+
 static inline void hashclr(unsigned char *hash)
 {
        memset(hash, 0, GIT_SHA1_RAWSZ);
@@ -1872,188 +1882,9 @@ extern int packed_object_info(struct packed_git *pack, off_t offset, struct obje
 /* 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.
@@ -2061,16 +1892,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);
 
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 74f723af3d08937a852a572c437605408dc0e30e..9e163d5adabd93fd48a6b563c5f31c32740e01c7 100644 (file)
@@ -302,7 +302,7 @@ static char *grab_blob(const struct object_id *oid, unsigned int mode,
                return xcalloc(1, 1);
        } else if (textconv) {
                struct diff_filespec *df = alloc_filespec(path);
-               fill_filespec(df, oid->hash, 1, mode);
+               fill_filespec(df, oid, 1, mode);
                *size = fill_textconv(textconv, df, &blob);
                free_filespec(df);
        } else {
@@ -1022,7 +1022,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
                                                   &result_size, NULL, NULL);
                } else if (textconv) {
                        struct diff_filespec *df = alloc_filespec(elem->path);
-                       fill_filespec(df, null_sha1, 0, st.st_mode);
+                       fill_filespec(df, &null_oid, 0, st.st_mode);
                        result_size = fill_textconv(textconv, df, &result);
                        free_filespec(df);
                } else if (0 <= (fd = open(elem->path, O_RDONLY))) {
@@ -1311,7 +1311,7 @@ static const char *path_path(void *obj)
 
 
 /* find set of paths that every parent touches */
-static struct combine_diff_path *find_paths_generic(const unsigned char *sha1,
+static struct combine_diff_path *find_paths_generic(const struct object_id *oid,
        const struct oid_array *parents, struct diff_options *opt)
 {
        struct combine_diff_path *paths = NULL;
@@ -1336,7 +1336,7 @@ static struct combine_diff_path *find_paths_generic(const unsigned char *sha1,
                        opt->output_format = stat_opt;
                else
                        opt->output_format = DIFF_FORMAT_NO_OUTPUT;
-               diff_tree_sha1(parents->oid[i].hash, sha1, "", opt);
+               diff_tree_oid(&parents->oid[i], oid, "", opt);
                diffcore_std(opt);
                paths = intersect_paths(paths, i, num_parent);
 
@@ -1360,31 +1360,31 @@ static struct combine_diff_path *find_paths_generic(const unsigned char *sha1,
  * rename/copy detection, etc, comparing all trees simultaneously (= faster).
  */
 static struct combine_diff_path *find_paths_multitree(
-       const unsigned char *sha1, const struct oid_array *parents,
+       const struct object_id *oid, const struct oid_array *parents,
        struct diff_options *opt)
 {
        int i, nparent = parents->nr;
-       const unsigned char **parents_sha1;
+       const struct object_id **parents_oid;
        struct combine_diff_path paths_head;
        struct strbuf base;
 
-       ALLOC_ARRAY(parents_sha1, nparent);
+       ALLOC_ARRAY(parents_oid, nparent);
        for (i = 0; i < nparent; i++)
-               parents_sha1[i] = parents->oid[i].hash;
+               parents_oid[i] = &parents->oid[i];
 
        /* fake list head, so worker can assume it is non-NULL */
        paths_head.next = NULL;
 
        strbuf_init(&base, PATH_MAX);
-       diff_tree_paths(&paths_head, sha1, parents_sha1, nparent, &base, opt);
+       diff_tree_paths(&paths_head, oid, parents_oid, nparent, &base, opt);
 
        strbuf_release(&base);
-       free(parents_sha1);
+       free(parents_oid);
        return paths_head.next;
 }
 
 
-void diff_tree_combined(const unsigned char *sha1,
+void diff_tree_combined(const struct object_id *oid,
                        const struct oid_array *parents,
                        int dense,
                        struct rev_info *rev)
@@ -1448,11 +1448,11 @@ void diff_tree_combined(const unsigned char *sha1,
                 * diff(sha1,parent_i) for all i to do the job, specifically
                 * for parent0.
                 */
-               paths = find_paths_generic(sha1, parents, &diffopts);
+               paths = find_paths_generic(oid, parents, &diffopts);
        }
        else {
                int stat_opt;
-               paths = find_paths_multitree(sha1, parents, &diffopts);
+               paths = find_paths_multitree(oid, parents, &diffopts);
 
                /*
                 * show stat against the first parent even
@@ -1463,7 +1463,7 @@ void diff_tree_combined(const unsigned char *sha1,
                if (stat_opt) {
                        diffopts.output_format = stat_opt;
 
-                       diff_tree_sha1(parents->oid[0].hash, sha1, "", &diffopts);
+                       diff_tree_oid(&parents->oid[0], oid, "", &diffopts);
                        diffcore_std(&diffopts);
                        if (opt->orderfile)
                                diffcore_order(opt->orderfile);
@@ -1539,6 +1539,6 @@ void diff_tree_combined_merge(const struct commit *commit, int dense,
                oid_array_append(&parents, &parent->item->object.oid);
                parent = parent->next;
        }
-       diff_tree_combined(commit->object.oid.hash, &parents, dense, rev);
+       diff_tree_combined(&commit->object.oid, &parents, dense, rev);
        oid_array_clear(&parents);
 }
index 713f09feb04116fc1529cbca1ca9cbd38e4e4379..99846d9bf467be8e737341795054588475c65855 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -168,7 +168,7 @@ struct commit_graft *read_graft_line(char *buf, int len)
 
 static int read_graft_file(const char *graft_file)
 {
-       FILE *fp = fopen(graft_file, "r");
+       FILE *fp = fopen_or_warn(graft_file, "r");
        struct strbuf buf = STRBUF_INIT;
        if (!fp)
                return -1;
index b5ca142fedf2ac0e0cedde1011ab385f65010fdf..107b3e8182fd4ab13006404cba05f7b52f6c9c54 100644 (file)
@@ -1,14 +1,14 @@
 /*
  *  The order of the following two lines is important.
  *
- *  FREAD_READS_DIRECTORIES is undefined before including git-compat-util.h
+ *  SUPPRESS_FOPEN_REDEFINITION is defined before including git-compat-util.h
  *  to avoid the redefinition of fopen within git-compat-util.h. This is
  *  necessary since fopen is a macro on some platforms which may be set
  *  based on compiler options. For example, on AIX fopen is set to fopen64
  *  when _LARGE_FILES is defined. The previous technique of merely undefining
  *  fopen after including git-compat-util.h is inadequate in this case.
  */
-#undef FREAD_READS_DIRECTORIES
+#define SUPPRESS_FOPEN_REDEFINITION
 #include "../git-compat-util.h"
 
 FILE *git_fopen(const char *path, const char *mode)
index c6134f7c810072106026577d8ee306df9311ef24..8b6fa0db446aee9888ff6484560131143c7e22e5 100644 (file)
@@ -423,6 +423,8 @@ FILE *mingw_fopen (const char *filename, const char *otype)
                return NULL;
        }
        file = _wfopen(wfilename, wotype);
+       if (!file && GetLastError() == ERROR_INVALID_NAME)
+               errno = ENOENT;
        if (file && hide && set_hidden_flag(wfilename, 1))
                warning("could not mark '%s' as hidden.", filename);
        return file;
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 146cb3452adab3115f15d30c2b0f9f5480344279..6f0f8b30f39ba3a32d1a1795bdf12d78c5ea97f9 100644 (file)
--- a/config.c
+++ b/config.c
@@ -6,6 +6,7 @@
  *
  */
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "exec_cmd.h"
 #include "strbuf.h"
@@ -218,8 +219,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;
 
@@ -604,7 +603,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;
 }
 
@@ -1438,7 +1438,7 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
        int ret = -1;
        FILE *f;
 
-       f = fopen(filename, "r");
+       f = fopen_or_warn(filename, "r");
        if (f) {
                flockfile(f);
                ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename, filename, f, data);
@@ -1545,10 +1545,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 +1577,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;
 
@@ -1612,9 +1610,14 @@ 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)
+       if (have_git_dir()) {
+               opts.commondir = get_git_common_dir();
+               opts.git_dir = get_git_dir();
+       }
+
+       if (config_with_options(fn, data, NULL, &opts) < 0)
                /*
-                * git_config_with_options() normally returns only
+                * 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
@@ -1653,11 +1656,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,12 +1672,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;
+       } else if (!discover_git_directory(&commondir, &gitdir)) {
+               opts.commondir = commondir.buf;
+               opts.git_dir = gitdir.buf;
+       }
 
-       git_config_with_options(cb, data, NULL, &opts);
+       config_with_options(cb, data, NULL, &opts);
 
-       strbuf_release(&buf);
+       strbuf_release(&commondir);
+       strbuf_release(&gitdir);
 }
 
 static void git_config_check_init(void);
@@ -2656,6 +2664,9 @@ int git_config_rename_section_in_file(const char *config_filename,
        }
 
        if (!(config_file = fopen(config_filename, "rb"))) {
+               ret = warn_on_fopen_errors(config_filename);
+               if (ret)
+                       goto out;
                /* no config file means nothing to rename, no error */
                goto commit_and_out;
        }
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..9e038cc
--- /dev/null
+++ b/config.h
@@ -0,0 +1,194 @@
+#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);
+
+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 192629f1431072f242f10a8528f1853b8bbaddeb..adfb90b6018a87a6fb3455635590aec374fd170b 100644 (file)
@@ -36,6 +36,7 @@ ifeq ($(uname_S),Linux)
        NEEDS_LIBRT = YesPlease
        HAVE_GETDELIM = YesPlease
        SANE_TEXT_GREP=-a
+       FREAD_READS_DIRECTORIES = UnfortunatelyYes
 endif
 ifeq ($(uname_S),GNU/kFreeBSD)
        HAVE_ALLOCA_H = YesPlease
@@ -43,6 +44,7 @@ ifeq ($(uname_S),GNU/kFreeBSD)
        HAVE_PATHS_H = YesPlease
        DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
        LIBC_CONTAINS_LIBINTL = YesPlease
+       FREAD_READS_DIRECTORIES = UnfortunatelyYes
 endif
 ifeq ($(uname_S),UnixWare)
        CC = cc
@@ -108,6 +110,7 @@ ifeq ($(uname_S),Darwin)
        BASIC_CFLAGS += -DPRECOMPOSE_UNICODE
        BASIC_CFLAGS += -DPROTECT_HFS_DEFAULT=1
        HAVE_BSD_SYSCTL = YesPlease
+       FREAD_READS_DIRECTORIES = UnfortunatelyYes
 endif
 ifeq ($(uname_S),SunOS)
        NEEDS_SOCKET = YesPlease
@@ -201,6 +204,7 @@ ifeq ($(uname_S),FreeBSD)
        GMTIME_UNRELIABLE_ERRORS = UnfortunatelyYes
        HAVE_BSD_SYSCTL = YesPlease
        PAGER_ENV = LESS=FRX LV=-c MORE=FRX
+       FREAD_READS_DIRECTORIES = UnfortunatelyYes
 endif
 ifeq ($(uname_S),OpenBSD)
        NO_STRCASESTR = YesPlease
@@ -551,6 +555,7 @@ else
                NO_GETTEXT =
                USE_GETTEXT_SCHEME = fallthrough
                USE_LIBPCRE= YesPlease
+               NO_LIBPCRE1_JIT = UnfortunatelyYes
                NO_CURL =
                USE_NED_ALLOCATOR = YesPlease
        else
index deeb968daa07355b729d178644c843c7a0ed62c5..11d083fbe0efa23eee5e56ccdce3b49effd946be 100644 (file)
@@ -255,21 +255,61 @@ GIT_PARSE_WITH([openssl]))
 # Perl-compatible regular expressions instead of standard or extended
 # POSIX regular expressions.
 #
-# Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
+# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
+# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
+# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
+# default in future releases.
+#
+# Define LIBPCREDIR=/foo/bar if your PCRE header and library files are in
 # /foo/bar/include and /foo/bar/lib directories.
 #
 AC_ARG_WITH(libpcre,
-AS_HELP_STRING([--with-libpcre],[support Perl-compatible regexes (default is NO)])
+AS_HELP_STRING([--with-libpcre],[synonym for --with-libpcre1]),
+    if test "$withval" = "no"; then
+       USE_LIBPCRE1=
+    elif test "$withval" = "yes"; then
+       USE_LIBPCRE1=YesPlease
+    else
+       USE_LIBPCRE1=YesPlease
+       LIBPCREDIR=$withval
+       AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
+        dnl USE_LIBPCRE1 can still be modified below, so don't substitute
+        dnl it yet.
+       GIT_CONF_SUBST([LIBPCREDIR])
+    fi)
+
+AC_ARG_WITH(libpcre1,
+AS_HELP_STRING([--with-libpcre1],[support Perl-compatible regexes via libpcre1 (default is NO)])
+AS_HELP_STRING([],           [ARG can be also prefix for libpcre library and headers]),
+    if test "$withval" = "no"; then
+       USE_LIBPCRE1=
+    elif test "$withval" = "yes"; then
+       USE_LIBPCRE1=YesPlease
+    else
+       USE_LIBPCRE1=YesPlease
+       LIBPCREDIR=$withval
+       AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
+        dnl USE_LIBPCRE1 can still be modified below, so don't substitute
+        dnl it yet.
+       GIT_CONF_SUBST([LIBPCREDIR])
+    fi)
+
+AC_ARG_WITH(libpcre2,
+AS_HELP_STRING([--with-libpcre2],[support Perl-compatible regexes via libpcre2 (default is NO)])
 AS_HELP_STRING([],           [ARG can be also prefix for libpcre library and headers]),
+    if test -n "$USE_LIBPCRE1"; then
+        AC_MSG_ERROR([Only supply one of --with-libpcre1 or --with-libpcre2!])
+    fi
+
     if test "$withval" = "no"; then
-       USE_LIBPCRE=
+       USE_LIBPCRE2=
     elif test "$withval" = "yes"; then
-       USE_LIBPCRE=YesPlease
+       USE_LIBPCRE2=YesPlease
     else
-       USE_LIBPCRE=YesPlease
+       USE_LIBPCRE2=YesPlease
        LIBPCREDIR=$withval
        AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
-        dnl USE_LIBPCRE can still be modified below, so don't substitute
+        dnl USE_LIBPCRE2 can still be modified below, so don't substitute
         dnl it yet.
        GIT_CONF_SUBST([LIBPCREDIR])
     fi)
@@ -501,13 +541,11 @@ GIT_CONF_SUBST([NEEDS_SSL_WITH_CRYPTO])
 GIT_CONF_SUBST([NO_OPENSSL])
 
 #
-# Define USE_LIBPCRE if you have and want to use libpcre. Various
-# commands such as log and grep offer runtime options to use
-# Perl-compatible regular expressions instead of standard or extended
-# POSIX regular expressions.
+# Handle the USE_LIBPCRE1 and USE_LIBPCRE2 options potentially set
+# above.
 #
 
-if test -n "$USE_LIBPCRE"; then
+if test -n "$USE_LIBPCRE1"; then
 
 GIT_STASH_FLAGS($LIBPCREDIR)
 
@@ -517,7 +555,22 @@ AC_CHECK_LIB([pcre], [pcre_version],
 
 GIT_UNSTASH_FLAGS($LIBPCREDIR)
 
-GIT_CONF_SUBST([USE_LIBPCRE])
+GIT_CONF_SUBST([USE_LIBPCRE1])
+
+fi
+
+
+if test -n "$USE_LIBPCRE2"; then
+
+GIT_STASH_FLAGS($LIBPCREDIR)
+
+AC_CHECK_LIB([pcre2-8], [pcre2_config_8],
+[USE_LIBPCRE2=YesPlease],
+[USE_LIBPCRE2=])
+
+GIT_UNSTASH_FLAGS($LIBPCREDIR)
+
+GIT_CONF_SUBST([USE_LIBPCRE2])
 
 fi
 
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 15b40f877489ff43714e9cfce87f06543891b8f6..48a2f26622d992b89462edb3658b5cdccee806bc 100644 (file)
@@ -2336,14 +2336,23 @@ _git_config ()
        esac
        __gitcomp "
                add.ignoreErrors
+               advice.amWorkDir
                advice.commitBeforeMerge
                advice.detachedHead
                advice.implicitIdentity
-               advice.pushNonFastForward
+               advice.pushAlreadyExists
+               advice.pushFetchFirst
+               advice.pushNeedsForce
+               advice.pushNonFFCurrent
+               advice.pushNonFFMatching
+               advice.pushUpdateRejected
                advice.resolveConflict
+               advice.rmHints
                advice.statusHints
+               advice.statusUoption
                alias.
                am.keepcr
+               am.threeWay
                apply.ignorewhitespace
                apply.whitespace
                branch.autosetupmerge
@@ -2406,6 +2415,8 @@ _git_config ()
                core.autocrlf
                core.bare
                core.bigFileThreshold
+               core.checkStat
+               core.commentChar
                core.compression
                core.createObject
                core.deltaBaseCacheLimit
@@ -2415,6 +2426,8 @@ _git_config ()
                core.fileMode
                core.fsyncobjectfiles
                core.gitProxy
+               core.hideDotFiles
+               core.hooksPath
                core.ignoreStat
                core.ignorecase
                core.logAllRefUpdates
@@ -2422,20 +2435,30 @@ _git_config ()
                core.notesRef
                core.packedGitLimit
                core.packedGitWindowSize
+               core.packedRefsTimeout
                core.pager
+               core.precomposeUnicode
                core.preferSymlinkRefs
                core.preloadindex
+               core.protectHFS
+               core.protectNTFS
                core.quotepath
                core.repositoryFormatVersion
                core.safecrlf
                core.sharedRepository
                core.sparseCheckout
+               core.splitIndex
+               core.sshCommand
                core.symlinks
                core.trustctime
                core.untrackedCache
                core.warnAmbiguousRefs
                core.whitespace
                core.worktree
+               credential.helper
+               credential.useHttpPath
+               credential.username
+               credentialCache.ignoreSIGHUP
                diff.autorefreshindex
                diff.external
                diff.ignoreSubmodules
@@ -2467,15 +2490,19 @@ _git_config ()
                format.thread
                format.to
                gc.
+               gc.aggressiveDepth
                gc.aggressiveWindow
                gc.auto
+               gc.autoDetach
                gc.autopacklimit
+               gc.logExpiry
                gc.packrefs
                gc.pruneexpire
                gc.reflogexpire
                gc.reflogexpireunreachable
                gc.rerereresolved
                gc.rerereunresolved
+               gc.worktreePruneExpire
                gitcvs.allbinary
                gitcvs.commitmsgannotation
                gitcvs.dbTableNamePrefix
index 4097f521f240240fde1a3bfa8519515fdaac75f6..7d2a519dafe5dcf892df10c51e1bfb83bc8a2091 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -1,5 +1,6 @@
 #define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
+#include "config.h"
 #include "attr.h"
 #include "run-command.h"
 #include "quote.h"
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..67a523353b105764783b683a23b51d7d6a3bfda3 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "credential.h"
 #include "string-list.h"
 #include "run-command.h"
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"
index 2982bf055acb6049a8cd6007244d60d985b7e619..0c0e20f7c004119cd86bc377722eca6d318cdf5d 100644 (file)
@@ -29,7 +29,7 @@
 static int check_removed(const struct cache_entry *ce, struct stat *st)
 {
        if (lstat(ce->name, st) < 0) {
-               if (errno != ENOENT && errno != ENOTDIR)
+               if (!is_missing_file_error(errno))
                        return -1;
                return 1;
        }
@@ -101,7 +101,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                struct cache_entry *ce = active_cache[i];
                int changed;
                unsigned dirty_submodule = 0;
-               const unsigned char *old_sha1, *new_sha1;
+               const struct object_id *old_oid, *new_oid;
 
                if (diff_can_quit_early(&revs->diffopt))
                        break;
@@ -210,14 +210,14 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                                        continue;
                                }
                                diff_addremove(&revs->diffopt, '-', ce->ce_mode,
-                                              ce->oid.hash,
+                                              &ce->oid,
                                               !is_null_oid(&ce->oid),
                                               ce->name, 0);
                                continue;
                        } else if (revs->diffopt.ita_invisible_in_index &&
                                   ce_intent_to_add(ce)) {
                                diff_addremove(&revs->diffopt, '+', ce->ce_mode,
-                                              EMPTY_BLOB_SHA1_BIN, 0,
+                                              &empty_tree_oid, 0,
                                               ce->name, 0);
                                continue;
                        }
@@ -233,12 +233,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                                continue;
                }
                oldmode = ce->ce_mode;
-               old_sha1 = ce->oid.hash;
-               new_sha1 = changed ? null_sha1 : ce->oid.hash;
+               old_oid = &ce->oid;
+               new_oid = changed ? &null_oid : &ce->oid;
                diff_change(&revs->diffopt, oldmode, newmode,
-                           old_sha1, new_sha1,
-                           !is_null_sha1(old_sha1),
-                           !is_null_sha1(new_sha1),
+                           old_oid, new_oid,
+                           !is_null_oid(old_oid),
+                           !is_null_oid(new_oid),
                            ce->name, 0, dirty_submodule);
 
        }
@@ -255,21 +255,21 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 static void diff_index_show_file(struct rev_info *revs,
                                 const char *prefix,
                                 const struct cache_entry *ce,
-                                const unsigned char *sha1, int sha1_valid,
+                                const struct object_id *oid, int oid_valid,
                                 unsigned int mode,
                                 unsigned dirty_submodule)
 {
        diff_addremove(&revs->diffopt, prefix[0], mode,
-                      sha1, sha1_valid, ce->name, dirty_submodule);
+                      oid, oid_valid, ce->name, dirty_submodule);
 }
 
 static int get_stat_data(const struct cache_entry *ce,
-                        const unsigned char **sha1p,
+                        const struct object_id **oidp,
                         unsigned int *modep,
                         int cached, int match_missing,
                         unsigned *dirty_submodule, struct diff_options *diffopt)
 {
-       const unsigned char *sha1 = ce->oid.hash;
+       const struct object_id *oid = &ce->oid;
        unsigned int mode = ce->ce_mode;
 
        if (!cached && !ce_uptodate(ce)) {
@@ -280,7 +280,7 @@ static int get_stat_data(const struct cache_entry *ce,
                        return -1;
                else if (changed) {
                        if (match_missing) {
-                               *sha1p = sha1;
+                               *oidp = oid;
                                *modep = mode;
                                return 0;
                        }
@@ -290,11 +290,11 @@ static int get_stat_data(const struct cache_entry *ce,
                                                    0, dirty_submodule);
                if (changed) {
                        mode = ce_mode_from_stat(ce, st.st_mode);
-                       sha1 = null_sha1;
+                       oid = &null_oid;
                }
        }
 
-       *sha1p = sha1;
+       *oidp = oid;
        *modep = mode;
        return 0;
 }
@@ -303,7 +303,7 @@ static void show_new_file(struct rev_info *revs,
                          const struct cache_entry *new,
                          int cached, int match_missing)
 {
-       const unsigned char *sha1;
+       const struct object_id *oid;
        unsigned int mode;
        unsigned dirty_submodule = 0;
 
@@ -311,11 +311,11 @@ static void show_new_file(struct rev_info *revs,
         * New file in the index: it might actually be different in
         * the working tree.
         */
-       if (get_stat_data(new, &sha1, &mode, cached, match_missing,
+       if (get_stat_data(new, &oid, &mode, cached, match_missing,
            &dirty_submodule, &revs->diffopt) < 0)
                return;
 
-       diff_index_show_file(revs, "+", new, sha1, !is_null_sha1(sha1), mode, dirty_submodule);
+       diff_index_show_file(revs, "+", new, oid, !is_null_oid(oid), mode, dirty_submodule);
 }
 
 static int show_modified(struct rev_info *revs,
@@ -325,20 +325,20 @@ static int show_modified(struct rev_info *revs,
                         int cached, int match_missing)
 {
        unsigned int mode, oldmode;
-       const unsigned char *sha1;
+       const struct object_id *oid;
        unsigned dirty_submodule = 0;
 
-       if (get_stat_data(new, &sha1, &mode, cached, match_missing,
+       if (get_stat_data(new, &oid, &mode, cached, match_missing,
                          &dirty_submodule, &revs->diffopt) < 0) {
                if (report_missing)
                        diff_index_show_file(revs, "-", old,
-                                            old->oid.hash, 1, old->ce_mode,
+                                            &old->oid, 1, old->ce_mode,
                                             0);
                return -1;
        }
 
        if (revs->combine_merges && !cached &&
-           (hashcmp(sha1, old->oid.hash) || oidcmp(&old->oid, &new->oid))) {
+           (oidcmp(oid, &old->oid) || oidcmp(&old->oid, &new->oid))) {
                struct combine_diff_path *p;
                int pathlen = ce_namelen(new);
 
@@ -362,12 +362,12 @@ static int show_modified(struct rev_info *revs,
        }
 
        oldmode = old->ce_mode;
-       if (mode == oldmode && !hashcmp(sha1, old->oid.hash) && !dirty_submodule &&
+       if (mode == oldmode && !oidcmp(oid, &old->oid) && !dirty_submodule &&
            !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
                return 0;
 
        diff_change(&revs->diffopt, oldmode, mode,
-                   old->oid.hash, sha1, 1, !is_null_sha1(sha1),
+                   &old->oid, oid, 1, !is_null_oid(oid),
                    old->name, 0, dirty_submodule);
        return 0;
 }
@@ -409,7 +409,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
                struct diff_filepair *pair;
                pair = diff_unmerge(&revs->diffopt, idx->name);
                if (tree)
-                       fill_filespec(pair->one, tree->oid.hash, 1,
+                       fill_filespec(pair->one, &tree->oid, 1,
                                      tree->ce_mode);
                return;
        }
@@ -426,7 +426,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
         * Something removed from the tree?
         */
        if (!idx) {
-               diff_index_show_file(revs, "-", tree, tree->oid.hash, 1,
+               diff_index_show_file(revs, "-", tree, &tree->oid, 1,
                                     tree->ce_mode, 0);
                return;
        }
index 79229382b06cefc98aa8926065f0fb999ad1da2e..80ff17d460ed67fa4b38f8a8dfce7504b27bbb64 100644 (file)
@@ -82,7 +82,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode)
        if (!name)
                name = "/dev/null";
        s = alloc_filespec(name);
-       fill_filespec(s, null_sha1, 0, mode);
+       fill_filespec(s, &null_oid, 0, mode);
        if (name == file_from_standard_input)
                populate_from_stdin(s);
        return s;
diff --git a/diff.c b/diff.c
index 976a6f91b189914570d1c688525a9ca5e3ef6505..41295d4ea9ff5564fa73d45aaa3afaab20103d87 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"
@@ -2702,13 +2703,13 @@ void free_filespec(struct diff_filespec *spec)
        }
 }
 
-void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
-                  int sha1_valid, unsigned short mode)
+void fill_filespec(struct diff_filespec *spec, const struct object_id *oid,
+                  int oid_valid, unsigned short mode)
 {
        if (mode) {
                spec->mode = canon_mode(mode);
-               hashcpy(spec->oid.hash, sha1);
-               spec->oid_valid = sha1_valid;
+               oidcpy(&spec->oid, oid);
+               spec->oid_valid = oid_valid;
        }
 }
 
@@ -2717,7 +2718,7 @@ void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
  * the work tree has that object contents, return true, so that
  * prepare_temp_file() does not have to inflate and extract.
  */
-static int reuse_worktree_file(const char *name, const unsigned char *sha1, int want_file)
+static int reuse_worktree_file(const char *name, const struct object_id *oid, int want_file)
 {
        const struct cache_entry *ce;
        struct stat st;
@@ -2748,7 +2749,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
         * objects however would tend to be slower as they need
         * to be individually opened and inflated.
         */
-       if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1))
+       if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(oid->hash))
                return 0;
 
        /*
@@ -2768,7 +2769,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
         * This is not the sha1 we are looking for, or
         * unreusable because it is not a regular file.
         */
-       if (hashcmp(sha1, ce->oid.hash) || !S_ISREG(ce->ce_mode))
+       if (oidcmp(oid, &ce->oid) || !S_ISREG(ce->ce_mode))
                return 0;
 
        /*
@@ -2842,7 +2843,7 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
                return diff_populate_gitlink(s, size_only);
 
        if (!s->oid_valid ||
-           reuse_worktree_file(s->path, s->oid.hash, 0)) {
+           reuse_worktree_file(s->path, &s->oid, 0)) {
                struct strbuf buf = STRBUF_INIT;
                struct stat st;
                int fd;
@@ -3008,7 +3009,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
 
        if (!S_ISGITLINK(one->mode) &&
            (!one->oid_valid ||
-            reuse_worktree_file(name, one->oid.hash, 1))) {
+            reuse_worktree_file(name, &one->oid, 1))) {
                struct stat st;
                if (lstat(name, &st) < 0) {
                        if (errno == ENOENT)
@@ -3030,13 +3031,13 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
                        /* we can borrow from the file in the work tree */
                        temp->name = name;
                        if (!one->oid_valid)
-                               sha1_to_hex_r(temp->hex, null_sha1);
+                               oid_to_hex_r(temp->hex, &null_oid);
                        else
                                oid_to_hex_r(temp->hex, &one->oid);
                        /* Even though we may sometimes borrow the
                         * contents from the work tree, we always want
                         * one->mode.  mode is trustworthy even when
-                        * !(one->sha1_valid), as long as
+                        * !(one->oid_valid), as long as
                         * DIFF_FILE_VALID(one).
                         */
                        xsnprintf(temp->mode, sizeof(temp->mode), "%06o", one->mode);
@@ -3239,7 +3240,7 @@ static void run_diff_cmd(const char *pgm,
                fprintf(o->file, "* Unmerged path %s\n", name);
 }
 
-static void diff_fill_sha1_info(struct diff_filespec *one)
+static void diff_fill_oid_info(struct diff_filespec *one)
 {
        if (DIFF_FILE_VALID(one)) {
                if (!one->oid_valid) {
@@ -3298,8 +3299,8 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
                return;
        }
 
-       diff_fill_sha1_info(one);
-       diff_fill_sha1_info(two);
+       diff_fill_oid_info(one);
+       diff_fill_oid_info(two);
 
        if (!pgm &&
            DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
@@ -3344,8 +3345,8 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
        if (o->prefix_length)
                strip_prefix(o->prefix_length, &name, &other);
 
-       diff_fill_sha1_info(p->one);
-       diff_fill_sha1_info(p->two);
+       diff_fill_oid_info(p->one);
+       diff_fill_oid_info(p->two);
 
        builtin_diffstat(name, other, p->one, p->two, diffstat, o, p);
 }
@@ -3368,8 +3369,8 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
        if (o->prefix_length)
                strip_prefix(o->prefix_length, &name, &other);
 
-       diff_fill_sha1_info(p->one);
-       diff_fill_sha1_info(p->two);
+       diff_fill_oid_info(p->one);
+       diff_fill_oid_info(p->two);
 
        builtin_checkdiff(name, other, attr_path, p->one, p->two, o);
 }
@@ -4071,9 +4072,7 @@ int diff_opt_parse(struct diff_options *options,
                DIFF_OPT_CLR(options, FUNCCONTEXT);
        else if ((argcount = parse_long_opt("output", av, &optarg))) {
                char *path = prefix_filename(prefix, optarg);
-               options->file = fopen(path, "w");
-               if (!options->file)
-                       die_errno("Could not open '%s'", path);
+               options->file = xfopen(path, "w");
                options->close_file = 1;
                if (options->use_color != GIT_COLOR_ALWAYS)
                        options->use_color = GIT_COLOR_NEVER;
@@ -4584,7 +4583,7 @@ static void patch_id_add_mode(git_SHA_CTX *ctx, unsigned mode)
 }
 
 /* returns 0 upon success, and writes result into sha1 */
-static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only)
+static int diff_get_patch_id(struct diff_options *options, struct object_id *oid, int diff_header_only)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
        int i;
@@ -4616,8 +4615,8 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1,
                if (DIFF_PAIR_UNMERGED(p))
                        continue;
 
-               diff_fill_sha1_info(p->one);
-               diff_fill_sha1_info(p->two);
+               diff_fill_oid_info(p->one);
+               diff_fill_oid_info(p->two);
 
                len1 = remove_space(p->one->path, strlen(p->one->path));
                len2 = remove_space(p->two->path, strlen(p->two->path));
@@ -4656,9 +4655,9 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1,
                if (diff_filespec_is_binary(p->one) ||
                    diff_filespec_is_binary(p->two)) {
                        git_SHA1_Update(&ctx, oid_to_hex(&p->one->oid),
-                                       40);
+                                       GIT_SHA1_HEXSZ);
                        git_SHA1_Update(&ctx, oid_to_hex(&p->two->oid),
-                                       40);
+                                       GIT_SHA1_HEXSZ);
                        continue;
                }
 
@@ -4671,15 +4670,15 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1,
                                     p->one->path);
        }
 
-       git_SHA1_Final(sha1, &ctx);
+       git_SHA1_Final(oid->hash, &ctx);
        return 0;
 }
 
-int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only)
+int diff_flush_patch_id(struct diff_options *options, struct object_id *oid, int diff_header_only)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
        int i;
-       int result = diff_get_patch_id(options, sha1, diff_header_only);
+       int result = diff_get_patch_id(options, oid, diff_header_only);
 
        for (i = 0; i < q->nr; i++)
                diff_free_filepair(q->queue[i]);
@@ -4807,9 +4806,7 @@ void diff_flush(struct diff_options *options)
                 */
                if (options->close_file)
                        fclose(options->file);
-               options->file = fopen("/dev/null", "w");
-               if (!options->file)
-                       die_errno("Could not open /dev/null");
+               options->file = xfopen("/dev/null", "w");
                options->close_file = 1;
                for (i = 0; i < q->nr; i++) {
                        struct diff_filepair *p = q->queue[i];
@@ -5081,8 +5078,8 @@ static int is_submodule_ignored(const char *path, struct diff_options *options)
 
 void diff_addremove(struct diff_options *options,
                    int addremove, unsigned mode,
-                   const unsigned char *sha1,
-                   int sha1_valid,
+                   const struct object_id *oid,
+                   int oid_valid,
                    const char *concatpath, unsigned dirty_submodule)
 {
        struct diff_filespec *one, *two;
@@ -5114,9 +5111,9 @@ void diff_addremove(struct diff_options *options,
        two = alloc_filespec(concatpath);
 
        if (addremove != '+')
-               fill_filespec(one, sha1, sha1_valid, mode);
+               fill_filespec(one, oid, oid_valid, mode);
        if (addremove != '-') {
-               fill_filespec(two, sha1, sha1_valid, mode);
+               fill_filespec(two, oid, oid_valid, mode);
                two->dirty_submodule = dirty_submodule;
        }
 
@@ -5127,9 +5124,9 @@ void diff_addremove(struct diff_options *options,
 
 void diff_change(struct diff_options *options,
                 unsigned old_mode, unsigned new_mode,
-                const unsigned char *old_sha1,
-                const unsigned char *new_sha1,
-                int old_sha1_valid, int new_sha1_valid,
+                const struct object_id *old_oid,
+                const struct object_id *new_oid,
+                int old_oid_valid, int new_oid_valid,
                 const char *concatpath,
                 unsigned old_dirty_submodule, unsigned new_dirty_submodule)
 {
@@ -5142,8 +5139,8 @@ void diff_change(struct diff_options *options,
 
        if (DIFF_OPT_TST(options, REVERSE_DIFF)) {
                SWAP(old_mode, new_mode);
-               SWAP(old_sha1, new_sha1);
-               SWAP(old_sha1_valid, new_sha1_valid);
+               SWAP(old_oid, new_oid);
+               SWAP(old_oid_valid, new_oid_valid);
                SWAP(old_dirty_submodule, new_dirty_submodule);
        }
 
@@ -5153,8 +5150,8 @@ void diff_change(struct diff_options *options,
 
        one = alloc_filespec(concatpath);
        two = alloc_filespec(concatpath);
-       fill_filespec(one, old_sha1, old_sha1_valid, old_mode);
-       fill_filespec(two, new_sha1, new_sha1_valid, new_mode);
+       fill_filespec(one, old_oid, old_oid_valid, old_mode);
+       fill_filespec(two, new_oid, new_oid_valid, new_mode);
        one->dirty_submodule = old_dirty_submodule;
        two->dirty_submodule = new_dirty_submodule;
        p = diff_queue(&diff_queued_diff, one, two);
@@ -5281,7 +5278,7 @@ int textconv_object(const char *path,
        struct userdiff_driver *textconv;
 
        df = alloc_filespec(path);
-       fill_filespec(df, oid->hash, oid_valid, mode);
+       fill_filespec(df, oid, oid_valid, mode);
        textconv = get_textconv(df);
        if (!textconv) {
                free_filespec(df);
diff --git a/diff.h b/diff.h
index 67537f17ed4ae1e64a60a4bdaaa97625cb3ffd15..2d442e296f9821ea4085188602b9ea4a4ba159a6 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -23,16 +23,16 @@ typedef int (*pathchange_fn_t)(struct diff_options *options,
 
 typedef void (*change_fn_t)(struct diff_options *options,
                 unsigned old_mode, unsigned new_mode,
-                const unsigned char *old_sha1,
-                const unsigned char *new_sha1,
-                int old_sha1_valid, int new_sha1_valid,
+                const struct object_id *old_oid,
+                const struct object_id *new_oid,
+                int old_oid_valid, int new_oid_valid,
                 const char *fullpath,
                 unsigned old_dirty_submodule, unsigned new_dirty_submodule);
 
 typedef void (*add_remove_fn_t)(struct diff_options *options,
                    int addremove, unsigned mode,
-                   const unsigned char *sha1,
-                   int sha1_valid,
+                   const struct object_id *oid,
+                   int oid_valid,
                    const char *fullpath, unsigned dirty_submodule);
 
 typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
@@ -210,13 +210,14 @@ const char *diff_line_prefix(struct diff_options *);
 extern const char mime_boundary_leader[];
 
 extern struct combine_diff_path *diff_tree_paths(
-       struct combine_diff_path *p, const unsigned char *sha1,
-       const unsigned char **parent_sha1, int nparent,
+       struct combine_diff_path *p, const struct object_id *oid,
+       const struct object_id **parents_oid, int nparent,
        struct strbuf *base, struct diff_options *opt);
-extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
-                         const char *base, struct diff_options *opt);
-extern int diff_root_tree_sha1(const unsigned char *new, const char *base,
-                               struct diff_options *opt);
+extern int diff_tree_oid(const struct object_id *old_oid,
+                        const struct object_id *new_oid,
+                        const char *base, struct diff_options *opt);
+extern int diff_root_tree_oid(const struct object_id *new_oid, const char *base,
+                             struct diff_options *opt);
 
 struct combine_diff_path {
        struct combine_diff_path *next;
@@ -236,7 +237,7 @@ struct combine_diff_path {
 extern void show_combined_diff(struct combine_diff_path *elem, int num_parent,
                              int dense, struct rev_info *);
 
-extern void diff_tree_combined(const unsigned char *sha1, const struct oid_array *parents, int dense, struct rev_info *rev);
+extern void diff_tree_combined(const struct object_id *oid, const struct oid_array *parents, int dense, struct rev_info *rev);
 
 extern void diff_tree_combined_merge(const struct commit *commit, int dense, struct rev_info *rev);
 
@@ -247,16 +248,15 @@ extern int diff_can_quit_early(struct diff_options *);
 extern void diff_addremove(struct diff_options *,
                           int addremove,
                           unsigned mode,
-                          const unsigned char *sha1,
-                          int sha1_valid,
+                          const struct object_id *oid,
+                          int oid_valid,
                           const char *fullpath, unsigned dirty_submodule);
 
 extern void diff_change(struct diff_options *,
                        unsigned mode1, unsigned mode2,
-                       const unsigned char *sha1,
-                       const unsigned char *sha2,
-                       int sha1_valid,
-                       int sha2_valid,
+                       const struct object_id *old_oid,
+                       const struct object_id *new_oid,
+                       int old_oid_valid, int new_oid_valid,
                        const char *fullpath,
                        unsigned dirty_submodule1, unsigned dirty_submodule2);
 
@@ -355,7 +355,7 @@ extern int run_diff_files(struct rev_info *revs, unsigned int option);
 extern int run_diff_index(struct rev_info *revs, int cached);
 
 extern int do_diff_cache(const struct object_id *, struct diff_options *);
-extern int diff_flush_patch_id(struct diff_options *, unsigned char *, int);
+extern int diff_flush_patch_id(struct diff_options *, struct object_id *, int);
 
 extern int diff_result_code(struct diff_options *, int);
 
index f7444c86bde3909c8fca23f71c4852514eb26b88..03d1e8d40bb78d03c6b7257b05275de739693671 100644 (file)
@@ -60,7 +60,7 @@ static int add_rename_dst(struct diff_filespec *two)
                memmove(rename_dst + first + 1, rename_dst + first,
                        (rename_dst_nr - first - 1) * sizeof(*rename_dst));
        rename_dst[first].two = alloc_filespec(two->path);
-       fill_filespec(rename_dst[first].two, two->oid.hash, two->oid_valid,
+       fill_filespec(rename_dst[first].two, &two->oid, two->oid_valid,
                      two->mode);
        rename_dst[first].pair = NULL;
        return 0;
@@ -464,7 +464,7 @@ void diffcore_rename(struct diff_options *options)
                                 strcmp(options->single_follow, p->two->path))
                                continue; /* not interested */
                        else if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&
-                                is_empty_blob_sha1(p->two->oid.hash))
+                                is_empty_blob_oid(&p->two->oid))
                                continue;
                        else if (add_rename_dst(p->two) < 0) {
                                warning("skipping rename detection, detected"
@@ -474,7 +474,7 @@ void diffcore_rename(struct diff_options *options)
                        }
                }
                else if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&
-                        is_empty_blob_sha1(p->one->oid.hash))
+                        is_empty_blob_oid(&p->one->oid))
                        continue;
                else if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) {
                        /*
index 623024135478088028cd42b8c6a744ebb04bf0a7..a30da161dafcf0d3951e3208000c54388803c8f0 100644 (file)
@@ -52,7 +52,7 @@ struct diff_filespec {
 
 extern struct diff_filespec *alloc_filespec(const char *);
 extern void free_filespec(struct diff_filespec *);
-extern void fill_filespec(struct diff_filespec *, const unsigned char *,
+extern void fill_filespec(struct diff_filespec *, const struct object_id *,
                          int, unsigned short);
 
 #define CHECK_SIZE_ONLY 1
diff --git a/dir.c b/dir.c
index f673b86f31eb841ce0ecc34f49ab9ece2dd4d128..34445374ba60b5a2e8d1c2b6e96ba7dbdb18eb4c 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"
@@ -752,9 +753,9 @@ static int add_excludes(const char *fname, const char *base, int baselen,
 
        fd = open(fname, O_RDONLY);
        if (fd < 0 || fstat(fd, &st) < 0) {
-               if (errno != ENOENT)
-                       warn_on_inaccessible(fname);
-               if (0 <= fd)
+               if (fd < 0)
+                       warn_on_fopen_errors(fname);
+               else
                        close(fd);
                if (!istate ||
                    (buf = read_skip_worktree_file_from_index(istate, fname, &size, sha1_stat)) == NULL)
@@ -2337,7 +2338,7 @@ int remove_path(const char *name)
 {
        char *slash;
 
-       if (unlink(name) && errno != ENOENT && errno != ENOTDIR)
+       if (unlink(name) && !is_missing_file_error(errno))
                return -1;
 
        slash = strrchr(name, '/');
index aa478e71de9d9c233593de050d6823e96be77b88..d40b21fb72168f32f1aaeac553347859e32f90c0 100644 (file)
@@ -8,6 +8,7 @@
  * are.
  */
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "fmt-merge-msg.h"
 #include "commit.h"
index e69d219682e7929b6e8441ba620e708704471ff3..94a1b06149479a11f3aa222cc7b0dba4cb94b1f0 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"
@@ -3285,9 +3286,7 @@ static void option_export_pack_edges(const char *edges)
 {
        if (pack_edges)
                fclose(pack_edges);
-       pack_edges = fopen(edges, "a");
-       if (!pack_edges)
-               die_errno("Cannot open '%s'", edges);
+       pack_edges = xfopen(edges, "a");
 }
 
 static int parse_one_option(const char *option)
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 4b7dcf21adbe7064963cf446bde7018629ea2c10..51ba4e6b3b7822915e3867722ec0b54b314111f7 100644 (file)
@@ -693,10 +693,12 @@ char *gitstrdup(const char *s);
 #endif
 
 #ifdef FREAD_READS_DIRECTORIES
-#ifdef fopen
-#undef fopen
-#endif
-#define fopen(a,b) git_fopen(a,b)
+# if !defined(SUPPRESS_FOPEN_REDEFINITION)
+#  ifdef fopen
+#   undef fopen
+#  endif
+#  define fopen(a,b) git_fopen(a,b)
+# endif
 extern FILE *git_fopen(const char*, const char*);
 #endif
 
@@ -804,6 +806,7 @@ extern int xmkstemp(char *template);
 extern int xmkstemp_mode(char *template, int mode);
 extern char *xgetcwd(void);
 extern FILE *fopen_for_writing(const char *path);
+extern FILE *fopen_or_warn(const char *path, const char *mode);
 
 #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)))
@@ -1110,8 +1113,8 @@ int remove_or_warn(unsigned int mode, const char *path);
 int access_or_warn(const char *path, int mode, unsigned flag);
 int access_or_die(const char *path, int mode, unsigned flag);
 
-/* Warn on an inaccessible file that ought to be accessible */
-void warn_on_inaccessible(const char *path);
+/* Warn on an inaccessible file if errno indicates this is an error */
+int warn_on_fopen_errors(const char *path);
 
 #ifdef GMTIME_UNRELIABLE_ERRORS
 struct tm *git_gmtime(const time_t *);
@@ -1134,6 +1137,21 @@ struct tm *git_gmtime_r(const time_t *, struct tm *);
 #define getc_unlocked(fh) getc(fh)
 #endif
 
+/*
+ * Our code often opens a path to an optional file, to work on its
+ * contents when we can successfully open it.  We can ignore a failure
+ * to open if such an optional file does not exist, but we do want to
+ * report a failure in opening for other reasons (e.g. we got an I/O
+ * error, or the file is there, but we lack the permission to open).
+ *
+ * Call this function after seeing an error from open() or fopen() to
+ * see if the errno indicates a missing file that we can safely ignore.
+ */
+static inline int is_missing_file_error(int errno_)
+{
+       return (errno_ == ENOENT || errno_ == ENOTDIR);
+}
+
 extern int cmd_main(int, const char **);
 
 #endif
diff --git a/git.c b/git.c
index 8ff44f081d43176474b267de5451f2c2e88089d0..5be27b07e5146e89ce6497566ec602a3f58bc313 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,50 +17,8 @@ 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 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 list_builtins(void);
 
 static void commit_pager_choice(void) {
        switch (use_pager) {
@@ -232,6 +191,9 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
                        }
                        (*argv)++;
                        (*argc)--;
+               } else if (!strcmp(cmd, "--list-builtins")) {
+                       list_builtins();
+                       exit(0);
                } else {
                        fprintf(stderr, "Unknown option: %s\n", cmd);
                        usage(git_usage_string);
@@ -250,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);
@@ -308,8 +269,6 @@ static int handle_alias(int *argcp, const char ***argv)
                ret = 1;
        }
 
-       restore_env(0);
-
        errno = saved_errno;
 
        return ret;
@@ -529,6 +488,13 @@ int is_builtin(const char *s)
        return !!get_builtin(s);
 }
 
+static void list_builtins(void)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(commands); i++)
+               printf("%s\n", commands[i].cmd);
+}
+
 #ifdef STRIP_EXTENSION
 static void strip_extension(const char **argv)
 {
index e44cc27da15f03629989ee0083664d0af09c55b3..8ab32df457d8947156bec1a838de39b60d9d545a 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "run-command.h"
 #include "strbuf.h"
 #include "gpg-interface.h"
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 d03d424e5cf8d32d91e3082555d8add674e01486..30d317a122eb5adc2c6d63eddaa12ca14cafba78 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"
@@ -179,22 +180,37 @@ static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, st
        case GREP_PATTERN_TYPE_BRE:
                opt->fixed = 0;
                opt->pcre1 = 0;
+               opt->pcre2 = 0;
                break;
 
        case GREP_PATTERN_TYPE_ERE:
                opt->fixed = 0;
                opt->pcre1 = 0;
+               opt->pcre2 = 0;
                opt->regflags |= REG_EXTENDED;
                break;
 
        case GREP_PATTERN_TYPE_FIXED:
                opt->fixed = 1;
                opt->pcre1 = 0;
+               opt->pcre2 = 0;
                break;
 
        case GREP_PATTERN_TYPE_PCRE:
                opt->fixed = 0;
+#ifdef USE_LIBPCRE2
+               opt->pcre1 = 0;
+               opt->pcre2 = 1;
+#else
+               /*
+                * It's important that pcre1 always be assigned to
+                * even when there's no USE_LIBPCRE* defined. We still
+                * call the PCRE stub function, it just dies with
+                * "cannot use Perl-compatible regexes[...]".
+                */
                opt->pcre1 = 1;
+               opt->pcre2 = 0;
+#endif
                break;
        }
 }
@@ -365,9 +381,22 @@ static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
        if (!p->pcre1_regexp)
                compile_regexp_failed(p, error);
 
-       p->pcre1_extra_info = pcre_study(p->pcre1_regexp, 0, &error);
+       p->pcre1_extra_info = pcre_study(p->pcre1_regexp, PCRE_STUDY_JIT_COMPILE, &error);
        if (!p->pcre1_extra_info && error)
                die("%s", error);
+
+#ifdef GIT_PCRE1_USE_JIT
+       pcre_config(PCRE_CONFIG_JIT, &p->pcre1_jit_on);
+       if (p->pcre1_jit_on == 1) {
+               p->pcre1_jit_stack = pcre_jit_stack_alloc(1, 1024 * 1024);
+               if (!p->pcre1_jit_stack)
+                       die("Couldn't allocate PCRE JIT stack");
+               pcre_assign_jit_stack(p->pcre1_extra_info, NULL, p->pcre1_jit_stack);
+       } else if (p->pcre1_jit_on != 0) {
+               die("BUG: The pcre1_jit_on variable should be 0 or 1, not %d",
+                   p->pcre1_jit_on);
+       }
+#endif
 }
 
 static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
@@ -378,8 +407,19 @@ static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
        if (eflags & REG_NOTBOL)
                flags |= PCRE_NOTBOL;
 
-       ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line, eol - line,
-                       0, flags, ovector, ARRAY_SIZE(ovector));
+#ifdef GIT_PCRE1_USE_JIT
+       if (p->pcre1_jit_on) {
+               ret = pcre_jit_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
+                                   eol - line, 0, flags, ovector,
+                                   ARRAY_SIZE(ovector), p->pcre1_jit_stack);
+       } else
+#endif
+       {
+               ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
+                               eol - line, 0, flags, ovector,
+                               ARRAY_SIZE(ovector));
+       }
+
        if (ret < 0 && ret != PCRE_ERROR_NOMATCH)
                die("pcre_exec failed with error code %d", ret);
        if (ret > 0) {
@@ -394,7 +434,15 @@ static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
 static void free_pcre1_regexp(struct grep_pat *p)
 {
        pcre_free(p->pcre1_regexp);
-       pcre_free(p->pcre1_extra_info);
+#ifdef GIT_PCRE1_USE_JIT
+       if (p->pcre1_jit_on) {
+               pcre_free_study(p->pcre1_extra_info);
+               pcre_jit_stack_free(p->pcre1_jit_stack);
+       } else
+#endif
+       {
+               pcre_free(p->pcre1_extra_info);
+       }
        pcre_free((void *)p->pcre1_tables);
 }
 #else /* !USE_LIBPCRE1 */
@@ -414,6 +462,127 @@ static void free_pcre1_regexp(struct grep_pat *p)
 }
 #endif /* !USE_LIBPCRE1 */
 
+#ifdef USE_LIBPCRE2
+static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
+{
+       int error;
+       PCRE2_UCHAR errbuf[256];
+       PCRE2_SIZE erroffset;
+       int options = PCRE2_MULTILINE;
+       const uint8_t *character_tables = NULL;
+       int jitret;
+
+       assert(opt->pcre2);
+
+       p->pcre2_compile_context = NULL;
+
+       if (opt->ignore_case) {
+               if (has_non_ascii(p->pattern)) {
+                       character_tables = pcre2_maketables(NULL);
+                       p->pcre2_compile_context = pcre2_compile_context_create(NULL);
+                       pcre2_set_character_tables(p->pcre2_compile_context, character_tables);
+               }
+               options |= PCRE2_CASELESS;
+       }
+       if (is_utf8_locale() && has_non_ascii(p->pattern))
+               options |= PCRE2_UTF;
+
+       p->pcre2_pattern = pcre2_compile((PCRE2_SPTR)p->pattern,
+                                        p->patternlen, options, &error, &erroffset,
+                                        p->pcre2_compile_context);
+
+       if (p->pcre2_pattern) {
+               p->pcre2_match_data = pcre2_match_data_create_from_pattern(p->pcre2_pattern, NULL);
+               if (!p->pcre2_match_data)
+                       die("Couldn't allocate PCRE2 match data");
+       } else {
+               pcre2_get_error_message(error, errbuf, sizeof(errbuf));
+               compile_regexp_failed(p, (const char *)&errbuf);
+       }
+
+       pcre2_config(PCRE2_CONFIG_JIT, &p->pcre2_jit_on);
+       if (p->pcre2_jit_on == 1) {
+               jitret = pcre2_jit_compile(p->pcre2_pattern, PCRE2_JIT_COMPLETE);
+               if (jitret)
+                       die("Couldn't JIT the PCRE2 pattern '%s', got '%d'\n", p->pattern, jitret);
+               p->pcre2_jit_stack = pcre2_jit_stack_create(1, 1024 * 1024, NULL);
+               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)
+                       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) {
+               die("BUG: The pcre2_jit_on variable should be 0 or 1, not %d",
+                   p->pcre1_jit_on);
+       }
+}
+
+static int pcre2match(struct grep_pat *p, const char *line, const char *eol,
+               regmatch_t *match, int eflags)
+{
+       int ret, flags = 0;
+       PCRE2_SIZE *ovector;
+       PCRE2_UCHAR errbuf[256];
+
+       if (eflags & REG_NOTBOL)
+               flags |= PCRE2_NOTBOL;
+
+       if (p->pcre2_jit_on)
+               ret = pcre2_jit_match(p->pcre2_pattern, (unsigned char *)line,
+                                     eol - line, 0, flags, p->pcre2_match_data,
+                                     NULL);
+       else
+               ret = pcre2_match(p->pcre2_pattern, (unsigned char *)line,
+                                 eol - line, 0, flags, p->pcre2_match_data,
+                                 NULL);
+
+       if (ret < 0 && ret != PCRE2_ERROR_NOMATCH) {
+               pcre2_get_error_message(ret, errbuf, sizeof(errbuf));
+               die("%s failed with error code %d: %s",
+                   (p->pcre2_jit_on ? "pcre2_jit_match" : "pcre2_match"), ret,
+                   errbuf);
+       }
+       if (ret > 0) {
+               ovector = pcre2_get_ovector_pointer(p->pcre2_match_data);
+               ret = 0;
+               match->rm_so = (int)ovector[0];
+               match->rm_eo = (int)ovector[1];
+       }
+
+       return ret;
+}
+
+static void free_pcre2_pattern(struct grep_pat *p)
+{
+       pcre2_compile_context_free(p->pcre2_compile_context);
+       pcre2_code_free(p->pcre2_pattern);
+       pcre2_match_data_free(p->pcre2_match_data);
+       pcre2_jit_stack_free(p->pcre2_jit_stack);
+       pcre2_match_context_free(p->pcre2_match_context);
+}
+#else /* !USE_LIBPCRE2 */
+static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
+{
+       /*
+        * Unreachable until USE_LIBPCRE2 becomes synonymous with
+        * USE_LIBPCRE. See the sibling comment in
+        * grep_set_pattern_type_option().
+        */
+       die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE");
+}
+
+static int pcre2match(struct grep_pat *p, const char *line, const char *eol,
+               regmatch_t *match, int eflags)
+{
+       return 1;
+}
+
+static void free_pcre2_pattern(struct grep_pat *p)
+{
+}
+#endif /* !USE_LIBPCRE2 */
+
 static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
 {
        struct strbuf sb = STRBUF_INIT;
@@ -479,6 +648,11 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
                return;
        }
 
+       if (opt->pcre2) {
+               compile_pcre2_pattern(p, opt);
+               return;
+       }
+
        if (opt->pcre1) {
                compile_pcre1_regexp(p, opt);
                return;
@@ -838,6 +1012,8 @@ void free_grep_patterns(struct grep_opt *opt)
                                kwsfree(p->kws);
                        else if (p->pcre1_regexp)
                                free_pcre1_regexp(p);
+                       else if (p->pcre2_pattern)
+                               free_pcre2_pattern(p);
                        else
                                regfree(&p->regexp);
                        free(p->pattern);
@@ -918,6 +1094,8 @@ static int patmatch(struct grep_pat *p, char *line, char *eol,
                hit = !fixmatch(p, line, eol, match);
        else if (p->pcre1_regexp)
                hit = !pcre1match(p, line, eol, match, eflags);
+       else if (p->pcre2_pattern)
+               hit = !pcre2match(p, line, eol, match, eflags);
        else
                hit = !regexec_buf(&p->regexp, line, eol - line, 1, match,
                                   eflags);
@@ -1407,11 +1585,11 @@ static int fill_textconv_grep(struct userdiff_driver *driver,
         */
        df = alloc_filespec(gs->path);
        switch (gs->type) {
-       case GREP_SOURCE_SHA1:
+       case GREP_SOURCE_OID:
                fill_filespec(df, gs->identifier, 1, 0100644);
                break;
        case GREP_SOURCE_FILE:
-               fill_filespec(df, null_sha1, 0, 0100644);
+               fill_filespec(df, &null_oid, 0, 0100644);
                break;
        default:
                die("BUG: attempt to textconv something without a path?");
@@ -1751,9 +1929,8 @@ void grep_source_init(struct grep_source *gs, enum grep_source_type type,
                 * If the identifier is non-NULL (in the submodule case) it
                 * will be a SHA1 that needs to be copied.
                 */
-       case GREP_SOURCE_SHA1:
-               gs->identifier = xmalloc(20);
-               hashcpy(gs->identifier, identifier);
+       case GREP_SOURCE_OID:
+               gs->identifier = oiddup(identifier);
                break;
        case GREP_SOURCE_BUF:
                gs->identifier = NULL;
@@ -1776,7 +1953,7 @@ void grep_source_clear_data(struct grep_source *gs)
 {
        switch (gs->type) {
        case GREP_SOURCE_FILE:
-       case GREP_SOURCE_SHA1:
+       case GREP_SOURCE_OID:
        case GREP_SOURCE_SUBMODULE:
                free(gs->buf);
                gs->buf = NULL;
@@ -1788,7 +1965,7 @@ void grep_source_clear_data(struct grep_source *gs)
        }
 }
 
-static int grep_source_load_sha1(struct grep_source *gs)
+static int grep_source_load_oid(struct grep_source *gs)
 {
        enum object_type type;
 
@@ -1799,7 +1976,7 @@ static int grep_source_load_sha1(struct grep_source *gs)
        if (!gs->buf)
                return error(_("'%s': unable to read %s"),
                             gs->name,
-                            sha1_to_hex(gs->identifier));
+                            oid_to_hex(gs->identifier));
        return 0;
 }
 
@@ -1845,8 +2022,8 @@ static int grep_source_load(struct grep_source *gs)
        switch (gs->type) {
        case GREP_SOURCE_FILE:
                return grep_source_load_file(gs);
-       case GREP_SOURCE_SHA1:
-               return grep_source_load_sha1(gs);
+       case GREP_SOURCE_OID:
+               return grep_source_load_oid(gs);
        case GREP_SOURCE_BUF:
                return gs->buf ? 0 : -1;
        case GREP_SOURCE_SUBMODULE:
diff --git a/grep.h b/grep.h
index 38ac82b6384f8c6a505a8ed764610aa8404f8597..b8f93bfc2d518beddc90fed74e419cb1c6fb07f1 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -3,9 +3,33 @@
 #include "color.h"
 #ifdef USE_LIBPCRE1
 #include <pcre.h>
+#ifdef PCRE_CONFIG_JIT
+#if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32
+#ifndef NO_LIBPCRE1_JIT
+#define GIT_PCRE1_USE_JIT
+#endif
+#endif
+#endif
+#ifndef PCRE_STUDY_JIT_COMPILE
+#define PCRE_STUDY_JIT_COMPILE 0
+#endif
+#if PCRE_MAJOR <= 8 && PCRE_MINOR < 20
+typedef int pcre_jit_stack;
+#endif
 #else
 typedef int pcre;
 typedef int pcre_extra;
+typedef int pcre_jit_stack;
+#endif
+#ifdef USE_LIBPCRE2
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+#else
+typedef int pcre2_code;
+typedef int pcre2_match_data;
+typedef int pcre2_compile_context;
+typedef int pcre2_match_context;
+typedef int pcre2_jit_stack;
 #endif
 #include "kwset.h"
 #include "thread-utils.h"
@@ -48,7 +72,15 @@ struct grep_pat {
        regex_t regexp;
        pcre *pcre1_regexp;
        pcre_extra *pcre1_extra_info;
+       pcre_jit_stack *pcre1_jit_stack;
        const unsigned char *pcre1_tables;
+       int pcre1_jit_on;
+       pcre2_code *pcre2_pattern;
+       pcre2_match_data *pcre2_match_data;
+       pcre2_compile_context *pcre2_compile_context;
+       pcre2_match_context *pcre2_match_context;
+       pcre2_jit_stack *pcre2_jit_stack;
+       uint32_t pcre2_jit_on;
        kwset_t kws;
        unsigned fixed:1;
        unsigned ignore_case:1;
@@ -112,6 +144,7 @@ struct grep_opt {
        int extended;
        int use_reflog_filter;
        int pcre1;
+       int pcre2;
        int relative;
        int pathname;
        int null_following_name;
@@ -158,7 +191,7 @@ struct grep_source {
        char *name;
 
        enum grep_source_type {
-               GREP_SOURCE_SHA1,
+               GREP_SOURCE_OID,
                GREP_SOURCE_FILE,
                GREP_SOURCE_BUF,
                GREP_SOURCE_SUBMODULE,
diff --git a/help.c b/help.c
index db7f3d79a016881639a8c0640451afe35b011e5e..8ba0777410bd6377a1325622f7d73a53a0aa5a60 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"
@@ -9,6 +10,7 @@
 #include "column.h"
 #include "version.h"
 #include "refs.h"
+#include "parse-options.h"
 
 void add_cmdname(struct cmdnames *cmds, const char *name, int len)
 {
@@ -289,7 +291,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);
 
@@ -383,16 +385,30 @@ const char *help_unknown_cmd(const char *cmd)
 
 int cmd_version(int argc, const char **argv, const char *prefix)
 {
+       int build_options = 0;
+       const char * const usage[] = {
+               N_("git version [<options>]"),
+               NULL
+       };
+       struct option options[] = {
+               OPT_BOOL(0, "build-options", &build_options,
+                        "also print build options"),
+               OPT_END()
+       };
+
+       argc = parse_options(argc, argv, prefix, options, usage, 0);
+
        /*
         * The format of this string should be kept stable for compatibility
         * with external projects that rely on the output of "git version".
+        *
+        * Always show the version, even if other options are given.
         */
        printf("git version %s\n", git_version_string);
-       while (*++argv) {
-               if (!strcmp(*argv, "--build-options")) {
-                       printf("sizeof-long: %d\n", (int)sizeof(long));
-                       /* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */
-               }
+
+       if (build_options) {
+               printf("sizeof-long: %d\n", (int)sizeof(long));
+               /* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */
        }
        return 0;
 }
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"
diff --git a/http.c b/http.c
index d2e11ec6f012d3b2a9570f0c322aebf53a13cc0a..013bb0cc650888426156fd1c8d173544c1ec90e1 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"
diff --git a/ident.c b/ident.c
index bea871c8e02b7173eeba5527d22f5ae7783c011e..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;
@@ -72,12 +73,10 @@ static int add_mailname_host(struct strbuf *buf)
        FILE *mailname;
        struct strbuf mailnamebuf = STRBUF_INIT;
 
-       mailname = fopen("/etc/mailname", "r");
-       if (!mailname) {
-               if (errno != ENOENT)
-                       warning_errno("cannot open /etc/mailname");
+       mailname = fopen_or_warn("/etc/mailname", "r");
+       if (!mailname)
                return -1;
-       }
+
        if (strbuf_getline(&mailnamebuf, mailname) == EOF) {
                if (ferror(mailname))
                        warning_errno("cannot read /etc/mailname");
index 857591660f485d65dec3390b22dd2083c94d7a44..59e9b12d294da13fcfc2955c61f50709de1ae84f 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "credential.h"
 #include "exec_cmd.h"
 #include "run-command.h"
index b9087814b8ccd0082efc41c617e33e8046ea17d5..2588ce076749ecbb6bfbe591666430edf4ff9073 100644 (file)
@@ -500,12 +500,12 @@ static struct commit *check_single_commit(struct rev_info *revs)
 static void fill_blob_sha1(struct commit *commit, struct diff_filespec *spec)
 {
        unsigned mode;
-       unsigned char sha1[20];
+       struct object_id oid;
 
        if (get_tree_entry(commit->object.oid.hash, spec->path,
-                          sha1, &mode))
+                          oid.hash, &mode))
                die("There is no path %s in the commit", spec->path);
-       fill_filespec(spec, sha1, 1, mode);
+       fill_filespec(spec, &oid, 1, mode);
 
        return;
 }
@@ -819,8 +819,8 @@ static void queue_diffs(struct line_log_data *range,
        assert(commit);
 
        DIFF_QUEUE_CLEAR(&diff_queued_diff);
-       diff_tree_sha1(parent ? parent->tree->object.oid.hash : NULL,
-                       commit->tree->object.oid.hash, "", opt);
+       diff_tree_oid(parent ? &parent->tree->object.oid : NULL,
+                     &commit->tree->object.oid, "", opt);
        if (opt->detect_rename) {
                filter_diffs_for_paths(range, 1);
                if (diff_might_be_rename())
index d7eafb61a6831020149d0da607bb47b995192296..b9576efe97b98d8b7971045b7be3698b9592c5e6 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "cache.h"
+#include "config.h"
 #include "attr.h"
 #include "xdiff-interface.h"
 #include "run-command.h"
index a4ec11c2bf62bbda4304d19913f25965247d4027..410ab4f02de5b532485c46b5cceffc3c677df214 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "diff.h"
 #include "commit.h"
 #include "tag.h"
@@ -655,7 +656,7 @@ void show_log(struct rev_info *opt)
                struct strbuf notebuf = STRBUF_INIT;
 
                raw = (opt->commit_format == CMIT_FMT_USERFORMAT);
-               format_display_notes(commit->object.oid.hash, &notebuf,
+               format_display_notes(&commit->object.oid, &notebuf,
                                     get_log_output_encoding(), raw);
                ctx.notes_message = notebuf.len
                        ? strbuf_detach(&notebuf, NULL)
@@ -803,7 +804,7 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
        parents = get_saved_parents(opt, commit);
        if (!parents) {
                if (opt->show_root_diff) {
-                       diff_root_tree_sha1(oid->hash, "", &opt->diffopt);
+                       diff_root_tree_oid(oid, "", &opt->diffopt);
                        log_tree_diff_flush(opt);
                }
                return !opt->loginfo;
@@ -822,8 +823,8 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
                         * we merged _in_.
                         */
                        parse_commit_or_die(parents->item);
-                       diff_tree_sha1(parents->item->tree->object.oid.hash,
-                                      oid->hash, "", &opt->diffopt);
+                       diff_tree_oid(&parents->item->tree->object.oid,
+                                     oid, "", &opt->diffopt);
                        log_tree_diff_flush(opt);
                        return !opt->loginfo;
                }
@@ -837,8 +838,8 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
                struct commit *parent = parents->item;
 
                parse_commit_or_die(parent);
-               diff_tree_sha1(parent->tree->object.oid.hash,
-                              oid->hash, "", &opt->diffopt);
+               diff_tree_oid(&parent->tree->object.oid,
+                             oid, "", &opt->diffopt);
                log_tree_diff_flush(opt);
 
                showed_log |= !opt->loginfo;
index f92cb9f729ca05ae1e80c9c27bc102dbb64a8dc0..f59162453eecdfb841383f71911303b594aa81e4 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "utf8.h"
 #include "strbuf.h"
 #include "mailinfo.h"
index eac12d4888993ebf4fde5194e19704db885824ee..59e5ee41a8cdde0613e5dfa890cb52b21666868f 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"
@@ -528,7 +529,7 @@ static struct string_list *get_renames(struct merge_options *o,
        opts.show_rename_progress = o->show_rename_progress;
        opts.output_format = DIFF_FORMAT_NO_OUTPUT;
        diff_setup_done(&opts);
-       diff_tree_sha1(o_tree->object.oid.hash, tree->object.oid.hash, "", &opts);
+       diff_tree_oid(&o_tree->object.oid, &tree->object.oid, "", &opts);
        diffcore_std(&opts);
        if (opts.needed_rename_limit > o->needed_rename_limit)
                o->needed_rename_limit = opts.needed_rename_limit;
index 2843e985760ae2b48f2f8103c573cee92fc1c350..29b4cede5f8d539416d0af22f31b0aabc0e28c46 100644 (file)
@@ -69,15 +69,15 @@ int notes_cache_write(struct notes_cache *c)
 char *notes_cache_get(struct notes_cache *c, struct object_id *key_oid,
                      size_t *outsize)
 {
-       const unsigned char *value_sha1;
+       const struct object_id *value_oid;
        enum object_type type;
        char *value;
        unsigned long size;
 
-       value_sha1 = get_note(&c->tree, key_oid->hash);
-       if (!value_sha1)
+       value_oid = get_note(&c->tree, key_oid);
+       if (!value_oid)
                return NULL;
-       value = read_sha1_file(value_sha1, &type, &size);
+       value = read_sha1_file(value_oid->hash, &type, &size);
 
        *outsize = size;
        return value;
@@ -90,5 +90,5 @@ int notes_cache_put(struct notes_cache *c, struct object_id *key_oid,
 
        if (write_sha1_file(data, size, "blob", value_oid.hash) < 0)
                return -1;
-       return add_note(&c->tree, key_oid->hash, value_oid.hash, NULL);
+       return add_note(&c->tree, key_oid, &value_oid, NULL);
 }
index 6244f6af9c655203953d91977f08dc982393ce78..70e3fbeefbe24233a545e75c0322a8a310778e43 100644 (file)
@@ -22,21 +22,21 @@ void init_notes_merge_options(struct notes_merge_options *o)
        o->verbosity = NOTES_MERGE_VERBOSITY_DEFAULT;
 }
 
-static int path_to_sha1(const char *path, unsigned char *sha1)
+static int path_to_oid(const char *path, struct object_id *oid)
 {
-       char hex_sha1[40];
+       char hex_oid[GIT_SHA1_HEXSZ];
        int i = 0;
-       while (*path && i < 40) {
+       while (*path && i < GIT_SHA1_HEXSZ) {
                if (*path != '/')
-                       hex_sha1[i++] = *path;
+                       hex_oid[i++] = *path;
                path++;
        }
-       if (*path || i != 40)
+       if (*path || i != GIT_SHA1_HEXSZ)
                return -1;
-       return get_sha1_hex(hex_sha1, sha1);
+       return get_oid_hex(hex_oid, oid);
 }
 
-static int verify_notes_filepair(struct diff_filepair *p, unsigned char *sha1)
+static int verify_notes_filepair(struct diff_filepair *p, struct object_id *oid)
 {
        switch (p->status) {
        case DIFF_STATUS_MODIFIED:
@@ -54,11 +54,11 @@ static int verify_notes_filepair(struct diff_filepair *p, unsigned char *sha1)
                return -1;
        }
        assert(!strcmp(p->one->path, p->two->path));
-       return path_to_sha1(p->one->path, sha1);
+       return path_to_oid(p->one->path, oid);
 }
 
 static struct notes_merge_pair *find_notes_merge_pair_pos(
-               struct notes_merge_pair *list, int len, unsigned char *obj,
+               struct notes_merge_pair *list, int len, struct object_id *obj,
                int insert_new, int *occupied)
 {
        /*
@@ -75,7 +75,7 @@ static struct notes_merge_pair *find_notes_merge_pair_pos(
        int i = last_index < len ? last_index : len - 1;
        int prev_cmp = 0, cmp = -1;
        while (i >= 0 && i < len) {
-               cmp = hashcmp(obj, list[i].obj.hash);
+               cmp = oidcmp(obj, &list[i].obj);
                if (!cmp) /* obj belongs @ i */
                        break;
                else if (cmp < 0 && prev_cmp <= 0) /* obj belongs < i */
@@ -114,8 +114,8 @@ static struct object_id uninitialized = {
 };
 
 static struct notes_merge_pair *diff_tree_remote(struct notes_merge_options *o,
-                                                const unsigned char *base,
-                                                const unsigned char *remote,
+                                                const struct object_id *base,
+                                                const struct object_id *remote,
                                                 int *num_changes)
 {
        struct diff_options opt;
@@ -123,13 +123,13 @@ static struct notes_merge_pair *diff_tree_remote(struct notes_merge_options *o,
        int i, len = 0;
 
        trace_printf("\tdiff_tree_remote(base = %.7s, remote = %.7s)\n",
-              sha1_to_hex(base), sha1_to_hex(remote));
+              oid_to_hex(base), oid_to_hex(remote));
 
        diff_setup(&opt);
        DIFF_OPT_SET(&opt, RECURSIVE);
        opt.output_format = DIFF_FORMAT_NO_OUTPUT;
        diff_setup_done(&opt);
-       diff_tree_sha1(base, remote, "", &opt);
+       diff_tree_oid(base, remote, "", &opt);
        diffcore_std(&opt);
 
        changes = xcalloc(diff_queued_diff.nr, sizeof(struct notes_merge_pair));
@@ -138,19 +138,19 @@ static struct notes_merge_pair *diff_tree_remote(struct notes_merge_options *o,
                struct diff_filepair *p = diff_queued_diff.queue[i];
                struct notes_merge_pair *mp;
                int occupied;
-               unsigned char obj[20];
+               struct object_id obj;
 
-               if (verify_notes_filepair(p, obj)) {
+               if (verify_notes_filepair(p, &obj)) {
                        trace_printf("\t\tCannot merge entry '%s' (%c): "
                               "%.7s -> %.7s. Skipping!\n", p->one->path,
                               p->status, oid_to_hex(&p->one->oid),
                               oid_to_hex(&p->two->oid));
                        continue;
                }
-               mp = find_notes_merge_pair_pos(changes, len, obj, 1, &occupied);
+               mp = find_notes_merge_pair_pos(changes, len, &obj, 1, &occupied);
                if (occupied) {
                        /* We've found an addition/deletion pair */
-                       assert(!hashcmp(mp->obj.hash, obj));
+                       assert(!oidcmp(&mp->obj, &obj));
                        if (is_null_oid(&p->one->oid)) { /* addition */
                                assert(is_null_oid(&mp->remote));
                                oidcpy(&mp->remote, &p->two->oid);
@@ -160,7 +160,7 @@ static struct notes_merge_pair *diff_tree_remote(struct notes_merge_options *o,
                        } else
                                assert(!"Invalid existing change recorded");
                } else {
-                       hashcpy(mp->obj.hash, obj);
+                       oidcpy(&mp->obj, &obj);
                        oidcpy(&mp->base, &p->one->oid);
                        oidcpy(&mp->local, &uninitialized);
                        oidcpy(&mp->remote, &p->two->oid);
@@ -179,45 +179,45 @@ static struct notes_merge_pair *diff_tree_remote(struct notes_merge_options *o,
 
 static void diff_tree_local(struct notes_merge_options *o,
                            struct notes_merge_pair *changes, int len,
-                           const unsigned char *base,
-                           const unsigned char *local)
+                           const struct object_id *base,
+                           const struct object_id *local)
 {
        struct diff_options opt;
        int i;
 
        trace_printf("\tdiff_tree_local(len = %i, base = %.7s, local = %.7s)\n",
-              len, sha1_to_hex(base), sha1_to_hex(local));
+              len, oid_to_hex(base), oid_to_hex(local));
 
        diff_setup(&opt);
        DIFF_OPT_SET(&opt, RECURSIVE);
        opt.output_format = DIFF_FORMAT_NO_OUTPUT;
        diff_setup_done(&opt);
-       diff_tree_sha1(base, local, "", &opt);
+       diff_tree_oid(base, local, "", &opt);
        diffcore_std(&opt);
 
        for (i = 0; i < diff_queued_diff.nr; i++) {
                struct diff_filepair *p = diff_queued_diff.queue[i];
                struct notes_merge_pair *mp;
                int match;
-               unsigned char obj[20];
+               struct object_id obj;
 
-               if (verify_notes_filepair(p, obj)) {
+               if (verify_notes_filepair(p, &obj)) {
                        trace_printf("\t\tCannot merge entry '%s' (%c): "
                               "%.7s -> %.7s. Skipping!\n", p->one->path,
                               p->status, oid_to_hex(&p->one->oid),
                               oid_to_hex(&p->two->oid));
                        continue;
                }
-               mp = find_notes_merge_pair_pos(changes, len, obj, 0, &match);
+               mp = find_notes_merge_pair_pos(changes, len, &obj, 0, &match);
                if (!match) {
                        trace_printf("\t\tIgnoring local-only change for %s: "
-                              "%.7s -> %.7s\n", sha1_to_hex(obj),
+                              "%.7s -> %.7s\n", oid_to_hex(&obj),
                               oid_to_hex(&p->one->oid),
                               oid_to_hex(&p->two->oid));
                        continue;
                }
 
-               assert(!hashcmp(mp->obj.hash, obj));
+               assert(!oidcmp(&mp->obj, &obj));
                if (is_null_oid(&p->two->oid)) { /* deletion */
                        /*
                         * Either this is a true deletion (1), or it is part
@@ -292,11 +292,11 @@ static void check_notes_merge_worktree(struct notes_merge_options *o)
                    git_path(NOTES_MERGE_WORKTREE));
 }
 
-static void write_buf_to_worktree(const unsigned char *obj,
+static void write_buf_to_worktree(const struct object_id *obj,
                                  const char *buf, unsigned long size)
 {
        int fd;
-       char *path = git_pathdup(NOTES_MERGE_WORKTREE "/%s", sha1_to_hex(obj));
+       char *path = git_pathdup(NOTES_MERGE_WORKTREE "/%s", oid_to_hex(obj));
        if (safe_create_leading_directories_const(path))
                die_errno("unable to create directory for '%s'", path);
 
@@ -320,19 +320,19 @@ static void write_buf_to_worktree(const unsigned char *obj,
        free(path);
 }
 
-static void write_note_to_worktree(const unsigned char *obj,
-                                  const unsigned char *note)
+static void write_note_to_worktree(const struct object_id *obj,
+                                  const struct object_id *note)
 {
        enum object_type type;
        unsigned long size;
-       void *buf = read_sha1_file(note, &type, &size);
+       void *buf = read_sha1_file(note->hash, &type, &size);
 
        if (!buf)
                die("cannot read note %s for object %s",
-                   sha1_to_hex(note), sha1_to_hex(obj));
+                   oid_to_hex(note), oid_to_hex(obj));
        if (type != OBJ_BLOB)
                die("blob expected in note %s for object %s",
-                   sha1_to_hex(note), sha1_to_hex(obj));
+                   oid_to_hex(note), oid_to_hex(obj));
        write_buf_to_worktree(obj, buf, size);
        free(buf);
 }
@@ -358,7 +358,7 @@ static int ll_merge_in_worktree(struct notes_merge_options *o,
        if ((status < 0) || !result_buf.ptr)
                die("Failed to execute internal merge");
 
-       write_buf_to_worktree(p->obj.hash, result_buf.ptr, result_buf.size);
+       write_buf_to_worktree(&p->obj, result_buf.ptr, result_buf.size);
        free(result_buf.ptr);
 
        return status;
@@ -393,7 +393,7 @@ static int merge_one_change_manual(struct notes_merge_options *o,
                                "deleted in %s and modified in %s. Version from %s "
                                "left in tree.\n",
                                oid_to_hex(&p->obj), lref, rref, rref);
-               write_note_to_worktree(p->obj.hash, p->remote.hash);
+               write_note_to_worktree(&p->obj, &p->remote);
        } else if (is_null_oid(&p->remote)) {
                /* D/F conflict, checkout p->local */
                assert(!is_null_oid(&p->local));
@@ -402,7 +402,7 @@ static int merge_one_change_manual(struct notes_merge_options *o,
                                "deleted in %s and modified in %s. Version from %s "
                                "left in tree.\n",
                                oid_to_hex(&p->obj), rref, lref, lref);
-               write_note_to_worktree(p->obj.hash, p->local.hash);
+               write_note_to_worktree(&p->obj, &p->local);
        } else {
                /* "regular" conflict, checkout result of ll_merge() */
                const char *reason = "content";
@@ -444,14 +444,14 @@ static int merge_one_change(struct notes_merge_options *o,
                if (o->verbosity >= 2)
                        printf("Using remote notes for %s\n",
                                                oid_to_hex(&p->obj));
-               if (add_note(t, p->obj.hash, p->remote.hash, combine_notes_overwrite))
+               if (add_note(t, &p->obj, &p->remote, combine_notes_overwrite))
                        die("BUG: combine_notes_overwrite failed");
                return 0;
        case NOTES_MERGE_RESOLVE_UNION:
                if (o->verbosity >= 2)
                        printf("Concatenating local and remote notes for %s\n",
                                                        oid_to_hex(&p->obj));
-               if (add_note(t, p->obj.hash, p->remote.hash, combine_notes_concatenate))
+               if (add_note(t, &p->obj, &p->remote, combine_notes_concatenate))
                        die("failed to concatenate notes "
                            "(combine_notes_concatenate)");
                return 0;
@@ -459,7 +459,7 @@ static int merge_one_change(struct notes_merge_options *o,
                if (o->verbosity >= 2)
                        printf("Concatenating unique lines in local and remote "
                                "notes for %s\n", oid_to_hex(&p->obj));
-               if (add_note(t, p->obj.hash, p->remote.hash, combine_notes_cat_sort_uniq))
+               if (add_note(t, &p->obj, &p->remote, combine_notes_cat_sort_uniq))
                        die("failed to concatenate notes "
                            "(combine_notes_cat_sort_uniq)");
                return 0;
@@ -491,7 +491,7 @@ static int merge_changes(struct notes_merge_options *o,
                           !oidcmp(&p->local, &p->base)) {
                        /* no local change; adopt remote change */
                        trace_printf("\t\t\tno local change, adopted remote\n");
-                       if (add_note(t, p->obj.hash, p->remote.hash,
+                       if (add_note(t, &p->obj, &p->remote,
                                     combine_notes_overwrite))
                                die("BUG: combine_notes_overwrite failed");
                } else {
@@ -505,16 +505,17 @@ static int merge_changes(struct notes_merge_options *o,
 }
 
 static int merge_from_diffs(struct notes_merge_options *o,
-                           const unsigned char *base,
-                           const unsigned char *local,
-                           const unsigned char *remote, struct notes_tree *t)
+                           const struct object_id *base,
+                           const struct object_id *local,
+                           const struct object_id *remote,
+                           struct notes_tree *t)
 {
        struct notes_merge_pair *changes;
        int num_changes, conflicts;
 
        trace_printf("\tmerge_from_diffs(base = %.7s, local = %.7s, "
-              "remote = %.7s)\n", sha1_to_hex(base), sha1_to_hex(local),
-              sha1_to_hex(remote));
+              "remote = %.7s)\n", oid_to_hex(base), oid_to_hex(local),
+              oid_to_hex(remote));
 
        changes = diff_tree_remote(o, base, remote, &num_changes);
        diff_tree_local(o, changes, num_changes, base, local);
@@ -533,17 +534,17 @@ static int merge_from_diffs(struct notes_merge_options *o,
 
 int notes_merge(struct notes_merge_options *o,
                struct notes_tree *local_tree,
-               unsigned char *result_sha1)
+               struct object_id *result_oid)
 {
        struct object_id local_oid, remote_oid;
        struct commit *local, *remote;
        struct commit_list *bases = NULL;
-       const unsigned char *base_sha1, *base_tree_sha1;
+       const struct object_id *base_oid, *base_tree_oid;
        int result = 0;
 
        assert(o->local_ref && o->remote_ref);
        assert(!strcmp(o->local_ref, local_tree->ref));
-       hashclr(result_sha1);
+       oidclr(result_oid);
 
        trace_printf("notes_merge(o->local_ref = %s, o->remote_ref = %s)\n",
               o->local_ref, o->remote_ref);
@@ -553,16 +554,16 @@ int notes_merge(struct notes_merge_options *o,
                die("Failed to resolve local notes ref '%s'", o->local_ref);
        else if (!check_refname_format(o->local_ref, 0) &&
                is_null_oid(&local_oid))
-               local = NULL; /* local_sha1 == null_sha1 indicates unborn ref */
+               local = NULL; /* local_oid == null_oid indicates unborn ref */
        else if (!(local = lookup_commit_reference(&local_oid)))
                die("Could not parse local commit %s (%s)",
                    oid_to_hex(&local_oid), o->local_ref);
        trace_printf("\tlocal commit: %.7s\n", oid_to_hex(&local_oid));
 
-       /* Dereference o->remote_ref into remote_sha1 */
+       /* Dereference o->remote_ref into remote_oid */
        if (get_oid(o->remote_ref, &remote_oid)) {
                /*
-                * Failed to get remote_sha1. If o->remote_ref looks like an
+                * Failed to get remote_oid. If o->remote_ref looks like an
                 * unborn ref, perform the merge using an empty notes tree.
                 */
                if (!check_refname_format(o->remote_ref, 0)) {
@@ -583,12 +584,12 @@ int notes_merge(struct notes_merge_options *o,
                    "(%s)", o->remote_ref, o->local_ref);
        if (!local) {
                /* result == remote commit */
-               hashcpy(result_sha1, remote_oid.hash);
+               oidcpy(result_oid, &remote_oid);
                goto found_result;
        }
        if (!remote) {
                /* result == local commit */
-               hashcpy(result_sha1, local_oid.hash);
+               oidcpy(result_oid, &local_oid);
                goto found_result;
        }
        assert(local && remote);
@@ -596,48 +597,48 @@ int notes_merge(struct notes_merge_options *o,
        /* Find merge bases */
        bases = get_merge_bases(local, remote);
        if (!bases) {
-               base_sha1 = null_sha1;
-               base_tree_sha1 = EMPTY_TREE_SHA1_BIN;
+               base_oid = &null_oid;
+               base_tree_oid = &empty_tree_oid;
                if (o->verbosity >= 4)
                        printf("No merge base found; doing history-less merge\n");
        } else if (!bases->next) {
-               base_sha1 = bases->item->object.oid.hash;
-               base_tree_sha1 = bases->item->tree->object.oid.hash;
+               base_oid = &bases->item->object.oid;
+               base_tree_oid = &bases->item->tree->object.oid;
                if (o->verbosity >= 4)
                        printf("One merge base found (%.7s)\n",
-                               sha1_to_hex(base_sha1));
+                              oid_to_hex(base_oid));
        } else {
                /* TODO: How to handle multiple merge-bases? */
-               base_sha1 = bases->item->object.oid.hash;
-               base_tree_sha1 = bases->item->tree->object.oid.hash;
+               base_oid = &bases->item->object.oid;
+               base_tree_oid = &bases->item->tree->object.oid;
                if (o->verbosity >= 3)
                        printf("Multiple merge bases found. Using the first "
-                               "(%.7s)\n", sha1_to_hex(base_sha1));
+                               "(%.7s)\n", oid_to_hex(base_oid));
        }
 
        if (o->verbosity >= 4)
                printf("Merging remote commit %.7s into local commit %.7s with "
                        "merge-base %.7s\n", oid_to_hex(&remote->object.oid),
                        oid_to_hex(&local->object.oid),
-                       sha1_to_hex(base_sha1));
+                       oid_to_hex(base_oid));
 
-       if (!hashcmp(remote->object.oid.hash, base_sha1)) {
+       if (!oidcmp(&remote->object.oid, base_oid)) {
                /* Already merged; result == local commit */
                if (o->verbosity >= 2)
                        printf("Already up-to-date!\n");
-               hashcpy(result_sha1, local->object.oid.hash);
+               oidcpy(result_oid, &local->object.oid);
                goto found_result;
        }
-       if (!hashcmp(local->object.oid.hash, base_sha1)) {
+       if (!oidcmp(&local->object.oid, base_oid)) {
                /* Fast-forward; result == remote commit */
                if (o->verbosity >= 2)
                        printf("Fast-forward\n");
-               hashcpy(result_sha1, remote->object.oid.hash);
+               oidcpy(result_oid, &remote->object.oid);
                goto found_result;
        }
 
-       result = merge_from_diffs(o, base_tree_sha1, local->tree->object.oid.hash,
-                                 remote->tree->object.oid.hash, local_tree);
+       result = merge_from_diffs(o, base_tree_oid, &local->tree->object.oid,
+                                 &remote->tree->object.oid, local_tree);
 
        if (result != 0) { /* non-trivial merge (with or without conflicts) */
                /* Commit (partial) result */
@@ -646,28 +647,28 @@ int notes_merge(struct notes_merge_options *o,
                commit_list_insert(local, &parents);
                create_notes_commit(local_tree, parents,
                                    o->commit_msg.buf, o->commit_msg.len,
-                                   result_sha1);
+                                   result_oid->hash);
        }
 
 found_result:
        free_commit_list(bases);
        strbuf_release(&(o->commit_msg));
-       trace_printf("notes_merge(): result = %i, result_sha1 = %.7s\n",
-              result, sha1_to_hex(result_sha1));
+       trace_printf("notes_merge(): result = %i, result_oid = %.7s\n",
+              result, oid_to_hex(result_oid));
        return result;
 }
 
 int notes_merge_commit(struct notes_merge_options *o,
                       struct notes_tree *partial_tree,
                       struct commit *partial_commit,
-                      unsigned char *result_sha1)
+                      struct object_id *result_oid)
 {
        /*
         * Iterate through files in .git/NOTES_MERGE_WORKTREE and add all
         * found notes to 'partial_tree'. Write the updated notes tree to
         * the DB, and commit the resulting tree object while reusing the
         * commit message and parents from 'partial_commit'.
-        * Finally store the new commit object SHA1 into 'result_sha1'.
+        * Finally store the new commit object OID into 'result_oid'.
         */
        DIR *dir;
        struct dirent *e;
@@ -693,12 +694,12 @@ int notes_merge_commit(struct notes_merge_options *o,
        baselen = path.len;
        while ((e = readdir(dir)) != NULL) {
                struct stat st;
-               unsigned char obj_sha1[20], blob_sha1[20];
+               struct object_id obj_oid, blob_oid;
 
                if (is_dot_or_dotdot(e->d_name))
                        continue;
 
-               if (strlen(e->d_name) != 40 || get_sha1_hex(e->d_name, obj_sha1)) {
+               if (get_oid_hex(e->d_name, &obj_oid)) {
                        if (o->verbosity >= 3)
                                printf("Skipping non-SHA1 entry '%s%s'\n",
                                        path.buf, e->d_name);
@@ -709,23 +710,23 @@ int notes_merge_commit(struct notes_merge_options *o,
                /* write file as blob, and add to partial_tree */
                if (stat(path.buf, &st))
                        die_errno("Failed to stat '%s'", path.buf);
-               if (index_path(blob_sha1, path.buf, &st, HASH_WRITE_OBJECT))
+               if (index_path(blob_oid.hash, path.buf, &st, HASH_WRITE_OBJECT))
                        die("Failed to write blob object from '%s'", path.buf);
-               if (add_note(partial_tree, obj_sha1, blob_sha1, NULL))
+               if (add_note(partial_tree, &obj_oid, &blob_oid, NULL))
                        die("Failed to add resolved note '%s' to notes tree",
                            path.buf);
                if (o->verbosity >= 4)
                        printf("Added resolved note for object %s: %s\n",
-                               sha1_to_hex(obj_sha1), sha1_to_hex(blob_sha1));
+                               oid_to_hex(&obj_oid), oid_to_hex(&blob_oid));
                strbuf_setlen(&path, baselen);
        }
 
        create_notes_commit(partial_tree, partial_commit->parents,
-                           msg, strlen(msg), result_sha1);
+                           msg, strlen(msg), result_oid->hash);
        unuse_commit_buffer(partial_commit, buffer);
        if (o->verbosity >= 4)
                printf("Finalized notes merge commit: %s\n",
-                       sha1_to_hex(result_sha1));
+                       oid_to_hex(result_oid));
        strbuf_release(&path);
        closedir(dir);
        return 0;
index 0d890563b5f427fe6924e34b3931ade51e00e18d..f815f23451b4fc8c8a88be0f9475890d8c84c60f 100644 (file)
@@ -32,16 +32,16 @@ void init_notes_merge_options(struct notes_merge_options *o);
  * outcomes:
  *
  * 1. The merge trivially results in an existing commit (e.g. fast-forward or
- *    already-up-to-date). 'local_tree' is untouched, the SHA1 of the result
- *    is written into 'result_sha1' and 0 is returned.
+ *    already-up-to-date). 'local_tree' is untouched, the OID of the result
+ *    is written into 'result_oid' and 0 is returned.
  * 2. The merge successfully completes, producing a merge commit. local_tree
- *    contains the updated notes tree, the SHA1 of the resulting commit is
- *    written into 'result_sha1', and 1 is returned.
+ *    contains the updated notes tree, the OID of the resulting commit is
+ *    written into 'result_oid', and 1 is returned.
  * 3. The merge results in conflicts. This is similar to #2 in that the
  *    partial merge result (i.e. merge result minus the unmerged entries)
- *    are stored in 'local_tree', and the SHA1 or the resulting commit
+ *    are stored in 'local_tree', and the OID or the resulting commit
  *    (to be amended when the conflicts have been resolved) is written into
- *    'result_sha1'. The unmerged entries are written into the
+ *    'result_oid'. The unmerged entries are written into the
  *    .git/NOTES_MERGE_WORKTREE directory with conflict markers.
  *    -1 is returned.
  *
@@ -52,7 +52,7 @@ void init_notes_merge_options(struct notes_merge_options *o);
  */
 int notes_merge(struct notes_merge_options *o,
                struct notes_tree *local_tree,
-               unsigned char *result_sha1);
+               struct object_id *result_oid);
 
 /*
  * Finalize conflict resolution from an earlier notes_merge()
@@ -62,13 +62,13 @@ int notes_merge(struct notes_merge_options *o,
  * call to notes_merge().
  *
  * This function will add the (now resolved) notes in .git/NOTES_MERGE_WORKTREE
- * to 'partial_tree', and create a final notes merge commit, the SHA1 of which
- * will be stored in 'result_sha1'.
+ * to 'partial_tree', and create a final notes merge commit, the OID of which
+ * will be stored in 'result_oid'.
  */
 int notes_merge_commit(struct notes_merge_options *o,
                       struct notes_tree *partial_tree,
                       struct commit *partial_commit,
-                      unsigned char *result_sha1);
+                      struct object_id *result_oid);
 
 /*
  * Abort conflict resolution from an earlier notes_merge()
index 031503d7b2ba9217cffa52652b57aa063208fb1a..9765deb41ab02dba909ec9027701bf2fdc53f310 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "commit.h"
 #include "refs.h"
 #include "notes-utils.h"
@@ -158,7 +159,7 @@ struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd)
 }
 
 int copy_note_for_rewrite(struct notes_rewrite_cfg *c,
-                         const unsigned char *from_obj, const unsigned char *to_obj)
+                         const struct object_id *from_obj, const struct object_id *to_obj)
 {
        int ret = 0;
        int i;
index fa538e1d9502c07fb1d72901c5939cd276fa1722..11905783989aa0d87be08e0c4311762b4647e9a4 100644 (file)
@@ -40,7 +40,7 @@ struct notes_rewrite_cfg {
 int parse_notes_merge_strategy(const char *v, enum notes_merge_strategy *s);
 struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd);
 int copy_note_for_rewrite(struct notes_rewrite_cfg *c,
-                         const unsigned char *from_obj, const unsigned char *to_obj);
+                         const struct object_id *from_obj, const struct object_id *to_obj);
 void finish_copy_notes_for_rewrite(struct notes_rewrite_cfg *c, const char *msg);
 
 #endif
diff --git a/notes.c b/notes.c
index 542563b280ad305da1452d57653728b9005874e6..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"
@@ -35,8 +36,8 @@ struct int_node {
  * subtree.
  */
 struct leaf_node {
-       unsigned char key_sha1[20];
-       unsigned char val_sha1[20];
+       struct object_id key_oid;
+       struct object_id val_oid;
 };
 
 /*
@@ -51,7 +52,7 @@ struct non_note {
        struct non_note *next; /* grounded (last->next == NULL) */
        char *path;
        unsigned int mode;
-       unsigned char sha1[20];
+       struct object_id oid;
 };
 
 #define PTR_TYPE_NULL     0
@@ -65,8 +66,10 @@ struct non_note {
 
 #define GET_NIBBLE(n, sha1) (((sha1[(n) >> 1]) >> ((~(n) & 0x01) << 2)) & 0x0f)
 
+#define KEY_INDEX (GIT_SHA1_RAWSZ - 1)
+#define FANOUT_PATH_SEPARATORS ((GIT_SHA1_HEXSZ / 2) - 1)
 #define SUBTREE_SHA1_PREFIXCMP(key_sha1, subtree_sha1) \
-       (memcmp(key_sha1, subtree_sha1, subtree_sha1[19]))
+       (memcmp(key_sha1, subtree_sha1, subtree_sha1[KEY_INDEX]))
 
 struct notes_tree default_notes_tree;
 
@@ -100,7 +103,7 @@ static void **note_tree_search(struct notes_tree *t, struct int_node **tree,
 
        if (GET_PTR_TYPE(p) == PTR_TYPE_SUBTREE) {
                l = (struct leaf_node *) CLR_PTR_TYPE(p);
-               if (!SUBTREE_SHA1_PREFIXCMP(key_sha1, l->key_sha1)) {
+               if (!SUBTREE_SHA1_PREFIXCMP(key_sha1, l->key_oid.hash)) {
                        /* unpack tree and resume search */
                        (*tree)->a[0] = NULL;
                        load_subtree(t, l, *tree, *n);
@@ -118,7 +121,7 @@ static void **note_tree_search(struct notes_tree *t, struct int_node **tree,
                return note_tree_search(t, tree, n, key_sha1);
        case PTR_TYPE_SUBTREE:
                l = (struct leaf_node *) CLR_PTR_TYPE(p);
-               if (!SUBTREE_SHA1_PREFIXCMP(key_sha1, l->key_sha1)) {
+               if (!SUBTREE_SHA1_PREFIXCMP(key_sha1, l->key_oid.hash)) {
                        /* unpack tree and resume search */
                        (*tree)->a[i] = NULL;
                        load_subtree(t, l, *tree, *n);
@@ -143,7 +146,7 @@ static struct leaf_node *note_tree_find(struct notes_tree *t,
        void **p = note_tree_search(t, &tree, &n, key_sha1);
        if (GET_PTR_TYPE(*p) == PTR_TYPE_NOTE) {
                struct leaf_node *l = (struct leaf_node *) CLR_PTR_TYPE(*p);
-               if (!hashcmp(key_sha1, l->key_sha1))
+               if (!hashcmp(key_sha1, l->key_oid.hash))
                        return l;
        }
        return NULL;
@@ -194,19 +197,19 @@ static void note_tree_remove(struct notes_tree *t,
                struct leaf_node *entry)
 {
        struct leaf_node *l;
-       struct int_node *parent_stack[20];
+       struct int_node *parent_stack[GIT_SHA1_RAWSZ];
        unsigned char i, j;
-       void **p = note_tree_search(t, &tree, &n, entry->key_sha1);
+       void **p = note_tree_search(t, &tree, &n, entry->key_oid.hash);
 
        assert(GET_PTR_TYPE(entry) == 0); /* no type bits set */
        if (GET_PTR_TYPE(*p) != PTR_TYPE_NOTE)
                return; /* type mismatch, nothing to remove */
        l = (struct leaf_node *) CLR_PTR_TYPE(*p);
-       if (hashcmp(l->key_sha1, entry->key_sha1))
+       if (oidcmp(&l->key_oid, &entry->key_oid))
                return; /* key mismatch, nothing to remove */
 
        /* we have found a matching entry */
-       hashcpy(entry->val_sha1, l->val_sha1);
+       oidcpy(&entry->val_oid, &l->val_oid);
        free(l);
        *p = SET_PTR_TYPE(NULL, PTR_TYPE_NULL);
 
@@ -216,14 +219,14 @@ static void note_tree_remove(struct notes_tree *t,
        /* first, build stack of ancestors between root and current node */
        parent_stack[0] = t->root;
        for (i = 0; i < n; i++) {
-               j = GET_NIBBLE(i, entry->key_sha1);
+               j = GET_NIBBLE(i, entry->key_oid.hash);
                parent_stack[i + 1] = CLR_PTR_TYPE(parent_stack[i]->a[j]);
        }
        assert(i == n && parent_stack[i] == tree);
        /* next, unwind stack until note_tree_consolidate() is done */
        while (i > 0 &&
               !note_tree_consolidate(parent_stack[i], parent_stack[i - 1],
-                                     GET_NIBBLE(i - 1, entry->key_sha1)))
+                                     GET_NIBBLE(i - 1, entry->key_oid.hash)))
                i--;
 }
 
@@ -246,7 +249,7 @@ static int note_tree_insert(struct notes_tree *t, struct int_node *tree,
 {
        struct int_node *new_node;
        struct leaf_node *l;
-       void **p = note_tree_search(t, &tree, &n, entry->key_sha1);
+       void **p = note_tree_search(t, &tree, &n, entry->key_oid.hash);
        int ret = 0;
 
        assert(GET_PTR_TYPE(entry) == 0); /* no type bits set */
@@ -254,7 +257,7 @@ static int note_tree_insert(struct notes_tree *t, struct int_node *tree,
        switch (GET_PTR_TYPE(*p)) {
        case PTR_TYPE_NULL:
                assert(!*p);
-               if (is_null_sha1(entry->val_sha1))
+               if (is_null_oid(&entry->val_oid))
                        free(entry);
                else
                        *p = SET_PTR_TYPE(entry, type);
@@ -262,22 +265,22 @@ static int note_tree_insert(struct notes_tree *t, struct int_node *tree,
        case PTR_TYPE_NOTE:
                switch (type) {
                case PTR_TYPE_NOTE:
-                       if (!hashcmp(l->key_sha1, entry->key_sha1)) {
+                       if (!oidcmp(&l->key_oid, &entry->key_oid)) {
                                /* skip concatenation if l == entry */
-                               if (!hashcmp(l->val_sha1, entry->val_sha1))
+                               if (!oidcmp(&l->val_oid, &entry->val_oid))
                                        return 0;
 
-                               ret = combine_notes(l->val_sha1,
-                                                   entry->val_sha1);
-                               if (!ret && is_null_sha1(l->val_sha1))
+                               ret = combine_notes(l->val_oid.hash,
+                                                   entry->val_oid.hash);
+                               if (!ret && is_null_oid(&l->val_oid))
                                        note_tree_remove(t, tree, n, entry);
                                free(entry);
                                return ret;
                        }
                        break;
                case PTR_TYPE_SUBTREE:
-                       if (!SUBTREE_SHA1_PREFIXCMP(l->key_sha1,
-                                                   entry->key_sha1)) {
+                       if (!SUBTREE_SHA1_PREFIXCMP(l->key_oid.hash,
+                                                   entry->key_oid.hash)) {
                                /* unpack 'entry' */
                                load_subtree(t, entry, tree, n);
                                free(entry);
@@ -287,7 +290,7 @@ static int note_tree_insert(struct notes_tree *t, struct int_node *tree,
                }
                break;
        case PTR_TYPE_SUBTREE:
-               if (!SUBTREE_SHA1_PREFIXCMP(entry->key_sha1, l->key_sha1)) {
+               if (!SUBTREE_SHA1_PREFIXCMP(entry->key_oid.hash, l->key_oid.hash)) {
                        /* unpack 'l' and restart insert */
                        *p = NULL;
                        load_subtree(t, l, tree, n);
@@ -301,7 +304,7 @@ static int note_tree_insert(struct notes_tree *t, struct int_node *tree,
        /* non-matching leaf_node */
        assert(GET_PTR_TYPE(*p) == PTR_TYPE_NOTE ||
               GET_PTR_TYPE(*p) == PTR_TYPE_SUBTREE);
-       if (is_null_sha1(entry->val_sha1)) { /* skip insertion of empty note */
+       if (is_null_oid(&entry->val_oid)) { /* skip insertion of empty note */
                free(entry);
                return 0;
        }
@@ -341,21 +344,21 @@ static void note_tree_free(struct int_node *tree)
  * Otherwise, returns number of bytes written to sha1 (i.e. hex_len / 2).
  * Pads sha1 with NULs up to sha1_len (not included in returned length).
  */
-static int get_sha1_hex_segment(const char *hex, unsigned int hex_len,
-               unsigned char *sha1, unsigned int sha1_len)
+static int get_oid_hex_segment(const char *hex, unsigned int hex_len,
+               unsigned char *oid, unsigned int oid_len)
 {
        unsigned int i, len = hex_len >> 1;
-       if (hex_len % 2 != 0 || len > sha1_len)
+       if (hex_len % 2 != 0 || len > oid_len)
                return -1;
        for (i = 0; i < len; i++) {
                unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]);
                if (val & ~0xff)
                        return -1;
-               *sha1++ = val;
+               *oid++ = val;
                hex += 2;
        }
-       for (; i < sha1_len; i++)
-               *sha1++ = 0;
+       for (; i < oid_len; i++)
+               *oid++ = 0;
        return len;
 }
 
@@ -373,7 +376,7 @@ static void add_non_note(struct notes_tree *t, char *path,
        n->next = NULL;
        n->path = path;
        n->mode = mode;
-       hashcpy(n->sha1, sha1);
+       hashcpy(n->oid.hash, sha1);
        t->prev_non_note = n;
 
        if (!t->first_non_note) {
@@ -399,7 +402,7 @@ static void add_non_note(struct notes_tree *t, char *path,
        if (non_note_cmp(p, n) == 0) { /* n ~= p; overwrite p with n */
                assert(strcmp(p->path, n->path) == 0);
                p->mode = n->mode;
-               hashcpy(p->sha1, n->sha1);
+               oidcpy(&p->oid, &n->oid);
                free(n);
                t->prev_non_note = p;
                return;
@@ -413,7 +416,7 @@ static void add_non_note(struct notes_tree *t, char *path,
 static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                struct int_node *node, unsigned int n)
 {
-       unsigned char object_sha1[20];
+       struct object_id object_oid;
        unsigned int prefix_len;
        void *buf;
        struct tree_desc desc;
@@ -422,18 +425,18 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
        unsigned char type;
        struct leaf_node *l;
 
-       buf = fill_tree_descriptor(&desc, subtree->val_sha1);
+       buf = fill_tree_descriptor(&desc, subtree->val_oid.hash);
        if (!buf)
                die("Could not read %s for notes-index",
-                    sha1_to_hex(subtree->val_sha1));
+                    oid_to_hex(&subtree->val_oid));
 
-       prefix_len = subtree->key_sha1[19];
+       prefix_len = subtree->key_oid.hash[KEY_INDEX];
        assert(prefix_len * 2 >= n);
-       memcpy(object_sha1, subtree->key_sha1, prefix_len);
+       memcpy(object_oid.hash, subtree->key_oid.hash, prefix_len);
        while (tree_entry(&desc, &entry)) {
                path_len = strlen(entry.path);
-               len = get_sha1_hex_segment(entry.path, path_len,
-                               object_sha1 + prefix_len, 20 - prefix_len);
+               len = get_oid_hex_segment(entry.path, path_len,
+                               object_oid.hash + prefix_len, GIT_SHA1_RAWSZ - prefix_len);
                if (len < 0)
                        goto handle_non_note; /* entry.path is not a SHA1 */
                len += prefix_len;
@@ -443,16 +446,16 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                 * If object SHA1 is incomplete (len < 20), and current
                 * component consists of 2 hex chars, assume note subtree
                 */
-               if (len <= 20) {
+               if (len <= GIT_SHA1_RAWSZ) {
                        type = PTR_TYPE_NOTE;
                        l = (struct leaf_node *)
                                xcalloc(1, sizeof(struct leaf_node));
-                       hashcpy(l->key_sha1, object_sha1);
-                       hashcpy(l->val_sha1, entry.oid->hash);
-                       if (len < 20) {
+                       oidcpy(&l->key_oid, &object_oid);
+                       oidcpy(&l->val_oid, entry.oid);
+                       if (len < GIT_SHA1_RAWSZ) {
                                if (!S_ISDIR(entry.mode) || path_len != 2)
                                        goto handle_non_note; /* not subtree */
-                               l->key_sha1[19] = (unsigned char) len;
+                               l->key_oid.hash[KEY_INDEX] = (unsigned char) len;
                                type = PTR_TYPE_SUBTREE;
                        }
                        if (note_tree_insert(t, node, n, l, type,
@@ -460,7 +463,7 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                                die("Failed to load %s %s into notes tree "
                                    "from %s",
                                    type == PTR_TYPE_NOTE ? "note" : "subtree",
-                                   sha1_to_hex(l->key_sha1), t->ref);
+                                   oid_to_hex(&l->key_oid), t->ref);
                }
                continue;
 
@@ -486,7 +489,7 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                 */
                {
                        struct strbuf non_note_path = STRBUF_INIT;
-                       const char *q = sha1_to_hex(subtree->key_sha1);
+                       const char *q = oid_to_hex(&subtree->key_oid);
                        int i;
                        for (i = 0; i < prefix_len; i++) {
                                strbuf_addch(&non_note_path, *q++);
@@ -542,14 +545,14 @@ static unsigned char determine_fanout(struct int_node *tree, unsigned char n,
 }
 
 /* hex SHA1 + 19 * '/' + NUL */
-#define FANOUT_PATH_MAX 40 + 19 + 1
+#define FANOUT_PATH_MAX GIT_SHA1_HEXSZ + FANOUT_PATH_SEPARATORS + 1
 
 static void construct_path_with_fanout(const unsigned char *sha1,
                unsigned char fanout, char *path)
 {
        unsigned int i = 0, j = 0;
        const char *hex_sha1 = sha1_to_hex(sha1);
-       assert(fanout < 20);
+       assert(fanout < GIT_SHA1_RAWSZ);
        while (fanout) {
                path[i++] = hex_sha1[j++];
                path[i++] = hex_sha1[j++];
@@ -599,15 +602,17 @@ static int for_each_note_helper(struct notes_tree *t, struct int_node *tree,
                            flags & FOR_EACH_NOTE_YIELD_SUBTREES) {
                                /* invoke callback with subtree */
                                unsigned int path_len =
-                                       l->key_sha1[19] * 2 + fanout;
+                                       l->key_oid.hash[KEY_INDEX] * 2 + fanout;
                                assert(path_len < FANOUT_PATH_MAX - 1);
-                               construct_path_with_fanout(l->key_sha1, fanout,
+                               construct_path_with_fanout(l->key_oid.hash,
+                                                          fanout,
                                                           path);
                                /* Create trailing slash, if needed */
                                if (path[path_len - 1] != '/')
                                        path[path_len++] = '/';
                                path[path_len] = '\0';
-                               ret = fn(l->key_sha1, l->val_sha1, path,
+                               ret = fn(&l->key_oid, &l->val_oid,
+                                        path,
                                         cb_data);
                        }
                        if (n > fanout * 2 ||
@@ -621,8 +626,10 @@ static int for_each_note_helper(struct notes_tree *t, struct int_node *tree,
                        break;
                case PTR_TYPE_NOTE:
                        l = (struct leaf_node *) CLR_PTR_TYPE(p);
-                       construct_path_with_fanout(l->key_sha1, fanout, path);
-                       ret = fn(l->key_sha1, l->val_sha1, path, cb_data);
+                       construct_path_with_fanout(l->key_oid.hash, fanout,
+                                                  path);
+                       ret = fn(&l->key_oid, &l->val_oid, path,
+                                cb_data);
                        break;
                }
                if (ret)
@@ -650,7 +657,7 @@ static void write_tree_entry(struct strbuf *buf, unsigned int mode,
                unsigned char *sha1)
 {
        strbuf_addf(buf, "%o %.*s%c", mode, path_len, path, '\0');
-       strbuf_add(buf, sha1, 20);
+       strbuf_add(buf, sha1, GIT_SHA1_RAWSZ);
 }
 
 static void tree_write_stack_init_subtree(struct tree_write_stack *tws,
@@ -662,7 +669,7 @@ static void tree_write_stack_init_subtree(struct tree_write_stack *tws,
        n = (struct tree_write_stack *)
                xmalloc(sizeof(struct tree_write_stack));
        n->next = NULL;
-       strbuf_init(&n->buf, 256 * (32 + 40)); /* assume 256 entries per tree */
+       strbuf_init(&n->buf, 256 * (32 + GIT_SHA1_HEXSZ)); /* assume 256 entries per tree */
        n->path[0] = n->path[1] = '\0';
        tws->next = n;
        tws->path[0] = path[0];
@@ -673,18 +680,18 @@ static int tree_write_stack_finish_subtree(struct tree_write_stack *tws)
 {
        int ret;
        struct tree_write_stack *n = tws->next;
-       unsigned char s[20];
+       struct object_id s;
        if (n) {
                ret = tree_write_stack_finish_subtree(n);
                if (ret)
                        return ret;
-               ret = write_sha1_file(n->buf.buf, n->buf.len, tree_type, s);
+               ret = write_sha1_file(n->buf.buf, n->buf.len, tree_type, s.hash);
                if (ret)
                        return ret;
                strbuf_release(&n->buf);
                free(n);
                tws->next = NULL;
-               write_tree_entry(&tws->buf, 040000, tws->path, 2, s);
+               write_tree_entry(&tws->buf, 040000, tws->path, 2, s.hash);
                tws->path[0] = tws->path[1] = '\0';
        }
        return 0;
@@ -692,7 +699,7 @@ static int tree_write_stack_finish_subtree(struct tree_write_stack *tws)
 
 static int write_each_note_helper(struct tree_write_stack *tws,
                const char *path, unsigned int mode,
-               const unsigned char *sha1)
+               const struct object_id *oid)
 {
        size_t path_len = strlen(path);
        unsigned int n = 0;
@@ -722,7 +729,7 @@ static int write_each_note_helper(struct tree_write_stack *tws,
 
        /* Finally add given entry to the current tree object */
        write_tree_entry(&tws->buf, mode, path + 3 * n, path_len - (3 * n),
-                        sha1);
+                        oid->hash);
 
        return 0;
 }
@@ -742,7 +749,7 @@ static int write_each_non_note_until(const char *note_path,
                        ; /* do nothing, prefer note to non-note */
                else {
                        ret = write_each_note_helper(d->root, n->path, n->mode,
-                                                    n->sha1);
+                                                    &n->oid);
                        if (ret)
                                return ret;
                }
@@ -752,8 +759,8 @@ static int write_each_non_note_until(const char *note_path,
        return 0;
 }
 
-static int write_each_note(const unsigned char *object_sha1,
-               const unsigned char *note_sha1, char *note_path,
+static int write_each_note(const struct object_id *object_oid,
+               const struct object_id *note_oid, char *note_path,
                void *cb_data)
 {
        struct write_each_note_data *d =
@@ -767,11 +774,11 @@ static int write_each_note(const unsigned char *object_sha1,
                note_path[note_path_len] = '\0';
                mode = 040000;
        }
-       assert(note_path_len <= 40 + 19);
+       assert(note_path_len <= GIT_SHA1_HEXSZ + FANOUT_PATH_SEPARATORS);
 
        /* Weave non-note entries into note entries */
        return  write_each_non_note_until(note_path, d) ||
-               write_each_note_helper(d->root, note_path, mode, note_sha1);
+               write_each_note_helper(d->root, note_path, mode, note_oid);
 }
 
 struct note_delete_list {
@@ -779,20 +786,20 @@ struct note_delete_list {
        const unsigned char *sha1;
 };
 
-static int prune_notes_helper(const unsigned char *object_sha1,
-               const unsigned char *note_sha1, char *note_path,
+static int prune_notes_helper(const struct object_id *object_oid,
+               const struct object_id *note_oid, char *note_path,
                void *cb_data)
 {
        struct note_delete_list **l = (struct note_delete_list **) cb_data;
        struct note_delete_list *n;
 
-       if (has_sha1_file(object_sha1))
+       if (has_object_file(object_oid))
                return 0; /* nothing to do for this note */
 
        /* failed to find object => prune this note */
        n = (struct note_delete_list *) xmalloc(sizeof(*n));
        n->next = *l;
-       n->sha1 = object_sha1;
+       n->sha1 = object_oid->hash;
        *l = n;
        return 0;
 }
@@ -942,8 +949,8 @@ void string_list_add_refs_by_glob(struct string_list *list, const char *glob)
        if (has_glob_specials(glob)) {
                for_each_glob_ref(string_list_add_one_ref, glob, list);
        } else {
-               unsigned char sha1[20];
-               if (get_sha1(glob, sha1))
+               struct object_id oid;
+               if (get_oid(glob, &oid))
                        warning("notes ref %s is invalid", glob);
                if (!unsorted_string_list_has_string(list, glob))
                        string_list_append(list, glob);
@@ -1027,8 +1034,8 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
                die("Failed to read notes tree referenced by %s (%s)",
                    notes_ref, oid_to_hex(&object_oid));
 
-       hashclr(root_tree.key_sha1);
-       hashcpy(root_tree.val_sha1, oid.hash);
+       oidclr(&root_tree.key_oid);
+       oidcpy(&root_tree.val_oid, &oid);
        load_subtree(t, &root_tree, t->root, 0);
 }
 
@@ -1080,8 +1087,8 @@ void init_display_notes(struct display_notes_opt *opt)
        string_list_clear(&display_notes_refs, 0);
 }
 
-int add_note(struct notes_tree *t, const unsigned char *object_sha1,
-               const unsigned char *note_sha1, combine_notes_fn combine_notes)
+int add_note(struct notes_tree *t, const struct object_id *object_oid,
+               const struct object_id *note_oid, combine_notes_fn combine_notes)
 {
        struct leaf_node *l;
 
@@ -1092,8 +1099,8 @@ int add_note(struct notes_tree *t, const unsigned char *object_sha1,
        if (!combine_notes)
                combine_notes = t->combine_notes;
        l = (struct leaf_node *) xmalloc(sizeof(struct leaf_node));
-       hashcpy(l->key_sha1, object_sha1);
-       hashcpy(l->val_sha1, note_sha1);
+       oidcpy(&l->key_oid, object_oid);
+       oidcpy(&l->val_oid, note_oid);
        return note_tree_insert(t, t->root, 0, l, PTR_TYPE_NOTE, combine_notes);
 }
 
@@ -1104,25 +1111,25 @@ int remove_note(struct notes_tree *t, const unsigned char *object_sha1)
        if (!t)
                t = &default_notes_tree;
        assert(t->initialized);
-       hashcpy(l.key_sha1, object_sha1);
-       hashclr(l.val_sha1);
+       hashcpy(l.key_oid.hash, object_sha1);
+       oidclr(&l.val_oid);
        note_tree_remove(t, t->root, 0, &l);
-       if (is_null_sha1(l.val_sha1)) /* no note was removed */
+       if (is_null_oid(&l.val_oid)) /* no note was removed */
                return 1;
        t->dirty = 1;
        return 0;
 }
 
-const unsigned char *get_note(struct notes_tree *t,
-               const unsigned char *object_sha1)
+const struct object_id *get_note(struct notes_tree *t,
+               const struct object_id *oid)
 {
        struct leaf_node *found;
 
        if (!t)
                t = &default_notes_tree;
        assert(t->initialized);
-       found = note_tree_find(t, t->root, 0, object_sha1);
-       return found ? found->val_sha1 : NULL;
+       found = note_tree_find(t, t->root, 0, oid->hash);
+       return found ? &found->val_oid : NULL;
 }
 
 int for_each_note(struct notes_tree *t, int flags, each_note_fn fn,
@@ -1146,7 +1153,7 @@ int write_notes_tree(struct notes_tree *t, unsigned char *result)
 
        /* Prepare for traversal of current notes tree */
        root.next = NULL; /* last forward entry in list is grounded */
-       strbuf_init(&root.buf, 256 * (32 + 40)); /* assume 256 entries */
+       strbuf_init(&root.buf, 256 * (32 + GIT_SHA1_HEXSZ)); /* assume 256 entries */
        root.path[0] = root.path[1] = '\0';
        cb_data.root = &root;
        cb_data.next_non_note = t->first_non_note;
@@ -1209,11 +1216,11 @@ void free_notes(struct notes_tree *t)
  * (raw != 0) gives the %N userformat; otherwise, the note message is given
  * for human consumption.
  */
-static void format_note(struct notes_tree *t, const unsigned char *object_sha1,
+static void format_note(struct notes_tree *t, const struct object_id *object_oid,
                        struct strbuf *sb, const char *output_encoding, int raw)
 {
        static const char utf8[] = "utf-8";
-       const unsigned char *sha1;
+       const struct object_id *oid;
        char *msg, *msg_p;
        unsigned long linelen, msglen;
        enum object_type type;
@@ -1223,11 +1230,11 @@ static void format_note(struct notes_tree *t, const unsigned char *object_sha1,
        if (!t->initialized)
                init_notes(t, NULL, NULL, 0);
 
-       sha1 = get_note(t, object_sha1);
-       if (!sha1)
+       oid = get_note(t, object_oid);
+       if (!oid)
                return;
 
-       if (!(msg = read_sha1_file(sha1, &type, &msglen)) || type != OBJ_BLOB) {
+       if (!(msg = read_sha1_file(oid->hash, &type, &msglen)) || type != OBJ_BLOB) {
                free(msg);
                return;
        }
@@ -1271,22 +1278,22 @@ static void format_note(struct notes_tree *t, const unsigned char *object_sha1,
        free(msg);
 }
 
-void format_display_notes(const unsigned char *object_sha1,
+void format_display_notes(const struct object_id *object_oid,
                          struct strbuf *sb, const char *output_encoding, int raw)
 {
        int i;
        assert(display_notes_trees);
        for (i = 0; display_notes_trees[i]; i++)
-               format_note(display_notes_trees[i], object_sha1, sb,
+               format_note(display_notes_trees[i], object_oid, sb,
                            output_encoding, raw);
 }
 
 int copy_note(struct notes_tree *t,
-             const unsigned char *from_obj, const unsigned char *to_obj,
+             const struct object_id *from_obj, const struct object_id *to_obj,
              int force, combine_notes_fn combine_notes)
 {
-       const unsigned char *note = get_note(t, from_obj);
-       const unsigned char *existing_note = get_note(t, to_obj);
+       const struct object_id *note = get_note(t, from_obj);
+       const struct object_id *existing_note = get_note(t, to_obj);
 
        if (!force && existing_note)
                return 1;
@@ -1294,7 +1301,7 @@ int copy_note(struct notes_tree *t,
        if (note)
                return add_note(t, to_obj, note, combine_notes);
        else if (existing_note)
-               return add_note(t, to_obj, null_sha1, combine_notes);
+               return add_note(t, to_obj, &null_oid, combine_notes);
 
        return 0;
 }
@@ -1311,9 +1318,9 @@ void expand_notes_ref(struct strbuf *sb)
 
 void expand_loose_notes_ref(struct strbuf *sb)
 {
-       unsigned char object[20];
+       struct object_id object;
 
-       if (get_sha1(sb->buf, object)) {
+       if (get_oid(sb->buf, &object)) {
                /* fallback to expand_notes_ref */
                expand_notes_ref(sb);
        }
diff --git a/notes.h b/notes.h
index 5345642cfd1c36f3935cb4a7e38ab32f6992b383..3848c2fb3f03510c1d0e1bd23ef6fbb3060b89c6 100644 (file)
--- a/notes.h
+++ b/notes.h
@@ -121,8 +121,8 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
  * are not persistent until a subsequent call to write_notes_tree() returns
  * zero.
  */
-int add_note(struct notes_tree *t, const unsigned char *object_sha1,
-               const unsigned char *note_sha1, combine_notes_fn combine_notes);
+int add_note(struct notes_tree *t, const struct object_id *object_oid,
+               const struct object_id *note_oid, combine_notes_fn combine_notes);
 
 /*
  * Remove the given note object from the given notes_tree structure
@@ -140,8 +140,8 @@ int remove_note(struct notes_tree *t, const unsigned char *object_sha1);
  *
  * Return NULL if the given object has no notes.
  */
-const unsigned char *get_note(struct notes_tree *t,
-               const unsigned char *object_sha1);
+const struct object_id *get_note(struct notes_tree *t,
+               const struct object_id *object_oid);
 
 /*
  * Copy a note from one object to another in the given notes_tree.
@@ -156,7 +156,7 @@ const unsigned char *get_note(struct notes_tree *t,
  * zero.
  */
 int copy_note(struct notes_tree *t,
-             const unsigned char *from_obj, const unsigned char *to_obj,
+             const struct object_id *from_obj, const struct object_id *to_obj,
              int force, combine_notes_fn combine_notes);
 
 /*
@@ -202,8 +202,8 @@ int copy_note(struct notes_tree *t,
  * - copy_note()
  * - free_notes()
  */
-typedef int each_note_fn(const unsigned char *object_sha1,
-               const unsigned char *note_sha1, char *note_path,
+typedef int each_note_fn(const struct object_id *object_oid,
+               const struct object_id *note_oid, char *note_path,
                void *cb_data);
 int for_each_note(struct notes_tree *t, int flags, each_note_fn fn,
                void *cb_data);
@@ -277,7 +277,7 @@ void init_display_notes(struct display_notes_opt *opt);
  *
  * You *must* call init_display_notes() before using this function.
  */
-void format_display_notes(const unsigned char *object_sha1,
+void format_display_notes(const struct object_id *object_oid,
                          struct strbuf *sb, const char *output_encoding, int raw);
 
 /*
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"
index 92eba7a059e89873e2d94fd5ee37a92b887bde4c..9c0ab9e67a80b54f87d9b9d52fa08de7167aec4a 100644 (file)
@@ -11,18 +11,18 @@ static int patch_id_defined(struct commit *commit)
 }
 
 int commit_patch_id(struct commit *commit, struct diff_options *options,
-                   unsigned char *sha1, int diff_header_only)
+                   struct object_id *oid, int diff_header_only)
 {
        if (!patch_id_defined(commit))
                return -1;
 
        if (commit->parents)
-               diff_tree_sha1(commit->parents->item->object.oid.hash,
-                              commit->object.oid.hash, "", options);
+               diff_tree_oid(&commit->parents->item->object.oid,
+                             &commit->object.oid, "", options);
        else
-               diff_root_tree_sha1(commit->object.oid.hash, "", options);
+               diff_root_tree_oid(&commit->object.oid, "", options);
        diffcore_std(options);
-       return diff_flush_patch_id(options, sha1, diff_header_only);
+       return diff_flush_patch_id(options, oid, diff_header_only);
 }
 
 /*
@@ -39,15 +39,15 @@ static int patch_id_cmp(struct patch_id *a,
                        struct patch_id *b,
                        struct diff_options *opt)
 {
-       if (is_null_sha1(a->patch_id) &&
-           commit_patch_id(a->commit, opt, a->patch_id, 0))
+       if (is_null_oid(&a->patch_id) &&
+           commit_patch_id(a->commit, opt, &a->patch_id, 0))
                return error("Could not get patch ID for %s",
                        oid_to_hex(&a->commit->object.oid));
-       if (is_null_sha1(b->patch_id) &&
-           commit_patch_id(b->commit, opt, b->patch_id, 0))
+       if (is_null_oid(&b->patch_id) &&
+           commit_patch_id(b->commit, opt, &b->patch_id, 0))
                return error("Could not get patch ID for %s",
                        oid_to_hex(&b->commit->object.oid));
-       return hashcmp(a->patch_id, b->patch_id);
+       return oidcmp(&a->patch_id, &b->patch_id);
 }
 
 int init_patch_ids(struct patch_ids *ids)
@@ -71,13 +71,13 @@ static int init_patch_id_entry(struct patch_id *patch,
                               struct commit *commit,
                               struct patch_ids *ids)
 {
-       unsigned char header_only_patch_id[GIT_MAX_RAWSZ];
+       struct object_id header_only_patch_id;
 
        patch->commit = commit;
-       if (commit_patch_id(commit, &ids->diffopts, header_only_patch_id, 1))
+       if (commit_patch_id(commit, &ids->diffopts, &header_only_patch_id, 1))
                return -1;
 
-       hashmap_entry_init(patch, sha1hash(header_only_patch_id));
+       hashmap_entry_init(patch, sha1hash(header_only_patch_id.hash));
        return 0;
 }
 
index b9e5751f8e2f6ef17bfa444fe6d8f3f2c6b7bb85..bec0f727a7bc4345e524ff04d9569c68fabd2209 100644 (file)
@@ -3,7 +3,7 @@
 
 struct patch_id {
        struct hashmap_entry ent;
-       unsigned char patch_id[GIT_MAX_RAWSZ];
+       struct object_id patch_id;
        struct commit *commit;
 };
 
@@ -13,7 +13,7 @@ struct patch_ids {
 };
 
 int commit_patch_id(struct commit *commit, struct diff_options *options,
-                   unsigned char *sha1, int);
+                   struct object_id *oid, int);
 int init_patch_ids(struct patch_ids *);
 int free_patch_ids(struct patch_ids *);
 struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *);
index 828405021fca4214585e1d46b65f604d14e61143..ecc5331c232ef81f26343fd958a9b66e92a3fa5e 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"
index 09701bd2ffef3eb6d9104916e4119f757c06c244..9c9f81b5b0e0560e05da3ec3fa62c05eae92d1e3 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"
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..c8c766dab020472d5f318c247e376f27373a5261 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"
diff --git a/refs.c b/refs.c
index f0685c92513e306188d89380a1c3020024a4edb4..84112c88ee4349ef8c7411f6e046d0f2d289ea04 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"
index d8b3f73147c8af88597ad71259aef0a9f53dd104..621a4086c37362180f151cc1648444d4cfd69d13 100644 (file)
@@ -1,4 +1,5 @@
 #include "../cache.h"
+#include "../config.h"
 #include "../refs.h"
 #include "refs-internal.h"
 #include "ref-cache.h"
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 f87bf851ba75af9229b1a9171191673af330505b..e034ea00d49c81675d664085c0d67763609bfd8a 100644 (file)
@@ -51,17 +51,17 @@ static void terminate_batch(void)
 }
 
 /* NOTE: 'ref' refers to a git reference, while 'rev' refers to a svn revision. */
-static char *read_ref_note(const unsigned char sha1[20])
+static char *read_ref_note(const struct object_id *oid)
 {
-       const unsigned char *note_sha1;
+       const struct object_id *note_oid;
        char *msg = NULL;
        unsigned long msglen;
        enum object_type type;
 
        init_notes(NULL, notes_ref, NULL, 0);
-       if (!(note_sha1 = get_note(NULL, sha1)))
+       if (!(note_oid = get_note(NULL, oid)))
                return NULL;    /* note tree not found */
-       if (!(msg = read_sha1_file(note_sha1, &type, &msglen)))
+       if (!(msg = read_sha1_file(note_oid->hash, &type, &msglen)))
                error("Empty notes tree. %s", notes_ref);
        else if (!msglen || type != OBJ_BLOB) {
                error("Note contains unusable content. "
@@ -99,8 +99,8 @@ static int parse_rev_note(const char *msg, struct rev_note *res)
        return -1;
 }
 
-static int note2mark_cb(const unsigned char *object_sha1,
-               const unsigned char *note_sha1, char *note_path,
+static int note2mark_cb(const struct object_id *object_oid,
+               const struct object_id *note_oid, char *note_path,
                void *cb_data)
 {
        FILE *file = (FILE *)cb_data;
@@ -109,14 +109,14 @@ static int note2mark_cb(const unsigned char *object_sha1,
        enum object_type type;
        struct rev_note note;
 
-       if (!(msg = read_sha1_file(note_sha1, &type, &msglen)) ||
+       if (!(msg = read_sha1_file(note_oid->hash, &type, &msglen)) ||
                        !msglen || type != OBJ_BLOB) {
                free(msg);
                return 1;
        }
        if (parse_rev_note(msg, &note))
                return 2;
-       if (fprintf(file, ":%d %s\n", note.rev_nr, sha1_to_hex(object_sha1)) < 1)
+       if (fprintf(file, ":%d %s\n", note.rev_nr, oid_to_hex(object_oid)) < 1)
                return 3;
        return 0;
 }
@@ -124,10 +124,8 @@ static int note2mark_cb(const unsigned char *object_sha1,
 static void regenerate_marks(void)
 {
        int ret;
-       FILE *marksfile = fopen(marksfilename, "w+");
+       FILE *marksfile = xfopen(marksfilename, "w+");
 
-       if (!marksfile)
-               die_errno("Couldn't create mark file %s.", marksfilename);
        ret = for_each_note(NULL, 0, note2mark_cb, marksfile);
        if (ret)
                die("Regeneration of marks failed, returned %d.", ret);
@@ -148,9 +146,7 @@ static void check_or_regenerate_marks(int latestrev)
        marksfile = fopen(marksfilename, "r");
        if (!marksfile) {
                regenerate_marks();
-               marksfile = fopen(marksfilename, "r");
-               if (!marksfile)
-                       die_errno("cannot read marks file %s!", marksfilename);
+               marksfile = xfopen(marksfilename, "r");
                fclose(marksfile);
        } else {
                strbuf_addf(&sb, ":%d ", latestrev);
@@ -174,15 +170,15 @@ static int cmd_import(const char *line)
        int code;
        int dumpin_fd;
        char *note_msg;
-       unsigned char head_sha1[20];
+       struct object_id head_oid;
        unsigned int startrev;
        struct child_process svndump_proc = CHILD_PROCESS_INIT;
        const char *command = "svnrdump";
 
-       if (read_ref(private_ref, head_sha1))
+       if (read_ref(private_ref, head_oid.hash))
                startrev = 0;
        else {
-               note_msg = read_ref_note(head_sha1);
+               note_msg = read_ref_note(&head_oid);
                if(note_msg == NULL) {
                        warning("No note found for %s.", private_ref);
                        startrev = 0;
index 3649d60cdce7335f6bc5bcca4810ce869dacfdcf..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"
@@ -251,7 +252,7 @@ static const char *skip_spaces(const char *s)
 static void read_remotes_file(struct remote *remote)
 {
        struct strbuf buf = STRBUF_INIT;
-       FILE *f = fopen(git_path("remotes/%s", remote->name), "r");
+       FILE *f = fopen_or_warn(git_path("remotes/%s", remote->name), "r");
 
        if (!f)
                return;
@@ -277,7 +278,7 @@ static void read_branches_file(struct remote *remote)
 {
        char *frag;
        struct strbuf buf = STRBUF_INIT;
-       FILE *f = fopen(git_path("branches/%s", remote->name), "r");
+       FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r");
 
        if (!f)
                return;
index 3bd55caf3b0961888bcca06d3c54577cb25f5223..829b3b0f08f7546c168e2728687d5729c4607cfa 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"
@@ -200,7 +201,7 @@ static struct rerere_id *new_rerere_id(unsigned char *sha1)
 static void read_rr(struct string_list *rr)
 {
        struct strbuf buf = STRBUF_INIT;
-       FILE *in = fopen(git_path_merge_rr(), "r");
+       FILE *in = fopen_or_warn(git_path_merge_rr(), "r");
 
        if (!in)
                return;
@@ -484,13 +485,14 @@ static int handle_file(const char *path, unsigned char *sha1, const char *output
        io.input = fopen(path, "r");
        io.io.wrerror = 0;
        if (!io.input)
-               return error("Could not open %s", path);
+               return error_errno("Could not open %s", path);
 
        if (output) {
                io.io.output = fopen(output, "w");
                if (!io.io.output) {
+                       error_errno("Could not write %s", output);
                        fclose(io.input);
-                       return error("Could not write %s", output);
+                       return -1;
                }
        }
 
index f88c14bab3188c65631593640289b26d00a6a3fc..12eb332350e2dd96bc1c6fee0d4f62f2556569a1 100644 (file)
@@ -401,8 +401,8 @@ static int tree_difference = REV_TREE_SAME;
 
 static void file_add_remove(struct diff_options *options,
                    int addremove, unsigned mode,
-                   const unsigned char *sha1,
-                   int sha1_valid,
+                   const struct object_id *oid,
+                   int oid_valid,
                    const char *fullpath, unsigned dirty_submodule)
 {
        int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD;
@@ -414,9 +414,9 @@ static void file_add_remove(struct diff_options *options,
 
 static void file_change(struct diff_options *options,
                 unsigned old_mode, unsigned new_mode,
-                const unsigned char *old_sha1,
-                const unsigned char *new_sha1,
-                int old_sha1_valid, int new_sha1_valid,
+                const struct object_id *old_oid,
+                const struct object_id *new_oid,
+                int old_oid_valid, int new_oid_valid,
                 const char *fullpath,
                 unsigned old_dirty_submodule, unsigned new_dirty_submodule)
 {
@@ -455,7 +455,7 @@ static int rev_compare_tree(struct rev_info *revs,
 
        tree_difference = REV_TREE_SAME;
        DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
-       if (diff_tree_sha1(t1->object.oid.hash, t2->object.oid.hash, "",
+       if (diff_tree_oid(&t1->object.oid, &t2->object.oid, "",
                           &revs->pruning) < 0)
                return REV_TREE_DIFFERENT;
        return tree_difference;
@@ -471,7 +471,7 @@ static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
 
        tree_difference = REV_TREE_SAME;
        DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
-       retval = diff_tree_sha1(NULL, t1->object.oid.hash, "", &revs->pruning);
+       retval = diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning);
 
        return retval >= 0 && (tree_difference == REV_TREE_SAME);
 }
@@ -2031,7 +2031,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
        } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
                revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_FIXED;
-       } else if (!strcmp(arg, "--perl-regexp")) {
+       } else if (!strcmp(arg, "--perl-regexp") || !strcmp(arg, "-P")) {
                revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_PCRE;
        } else if (!strcmp(arg, "--all-match")) {
                revs->grep_filter.all_match = 1;
@@ -2944,7 +2944,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
        if (opt->show_notes) {
                if (!buf.len)
                        strbuf_addstr(&buf, message);
-               format_display_notes(commit->object.oid.hash, &buf, encoding, 1);
+               format_display_notes(&commit->object.oid, &buf, encoding, 1);
        }
 
        /*
index 78bb34ebec297102c852a5b88ec7b4f10ffbc1d8..ed3cee3211bb80fac5c52bfe542a2b06fb308584 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "commit.h"
 #include "refs.h"
 #include "pkt-line.h"
index 924fb1d0c3c84dd823393d7dea21af2d70a8d54e..224afe79b96c89a70a36db85aa6c61826b2ebec1 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "lockfile.h"
 #include "sequencer.h"
 #include "dir.h"
@@ -899,8 +900,8 @@ static void flush_rewritten_pending(void) {
        FILE *out;
 
        if (strbuf_read_file(&buf, rebase_path_rewritten_pending(), 82) > 0 &&
-                       !get_sha1("HEAD", newsha1) &&
-                       (out = fopen(rebase_path_rewritten_list(), "a"))) {
+           !get_sha1("HEAD", newsha1) &&
+           (out = fopen_or_warn(rebase_path_rewritten_list(), "a"))) {
                char *bol = buf.buf, *eol;
 
                while (*bol) {
@@ -919,7 +920,7 @@ static void flush_rewritten_pending(void) {
 
 static void record_in_rewritten(struct object_id *oid,
                enum todo_command next_command) {
-       FILE *out = fopen(rebase_path_rewritten_pending(), "a");
+       FILE *out = fopen_or_warn(rebase_path_rewritten_pending(), "a");
 
        if (!out)
                return;
@@ -1381,7 +1382,7 @@ static int read_populate_todo(struct todo_list *todo_list,
 
        if (is_rebase_i(opts)) {
                struct todo_list done = TODO_LIST_INIT;
-               FILE *f = fopen(rebase_path_msgtotal(), "w");
+               FILE *f = fopen_or_warn(rebase_path_msgtotal(), "w");
 
                if (strbuf_read_file(&done.buf, rebase_path_done(), 0) > 0 &&
                                !parse_insn_buffer(done.buf.buf, &done))
@@ -2130,8 +2131,8 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
                        if (read_oneliner(&buf, rebase_path_orig_head(), 0) &&
                            !get_sha1(buf.buf, orig.hash) &&
                            !get_sha1("HEAD", head.hash)) {
-                               diff_tree_sha1(orig.hash, head.hash,
-                                              "", &log_tree_opt.diffopt);
+                               diff_tree_oid(&orig, &head, "",
+                                             &log_tree_opt.diffopt);
                                log_tree_diff_flush(&log_tree_opt);
                        }
                }
index 6f865b73a3aa014a9cecb13dbf86dede70a02a59..5ec5b1d827a54486c83efc802ebc6eb1f40062c4 100644 (file)
@@ -133,7 +133,7 @@ static int read_pack_info_file(const char *infofile)
        char line[1000];
        int old_cnt = 0;
 
-       fp = fopen(infofile, "r");
+       fp = fopen_or_warn(infofile, "r");
        if (!fp)
                return 1; /* nonexistent is not an error. */
 
diff --git a/setup.c b/setup.c
index e3f7699a902aed20a83820067cf913df2f3750a9..358fbc2e5301d9412b55463065b912b5708c3ceb 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "dir.h"
 #include "string-list.h"
 
@@ -134,23 +135,27 @@ int path_inside_repo(const char *prefix, const char *path)
 
 int check_filename(const char *prefix, const char *arg)
 {
-       const char *name;
        char *to_free = NULL;
        struct stat st;
 
-       if (starts_with(arg, ":/")) {
-               if (arg[2] == '\0') /* ":/" is root dir, always exists */
+       if (skip_prefix(arg, ":/", &arg)) {
+               if (!*arg) /* ":/" is root dir, always exists */
                        return 1;
-               name = arg + 2;
-       } else if (prefix)
-               name = to_free = prefix_filename(prefix, arg);
-       else
-               name = arg;
-       if (!lstat(name, &st)) {
+               prefix = NULL;
+       } else if (skip_prefix(arg, ":!", &arg) ||
+                  skip_prefix(arg, ":^", &arg)) {
+               if (!*arg) /* excluding everything is silly, but allowed */
+                       return 1;
+       }
+
+       if (prefix)
+               arg = to_free = prefix_filename(prefix, arg);
+
+       if (!lstat(arg, &st)) {
                free(to_free);
                return 1; /* file exists */
        }
-       if (errno == ENOENT || errno == ENOTDIR) {
+       if (is_missing_file_error(errno)) {
                free(to_free);
                return 0; /* file does not exist */
        }
@@ -181,6 +186,24 @@ static void NORETURN die_verify_filename(const char *prefix,
 
 }
 
+/*
+ * Check for arguments that don't resolve as actual files,
+ * but which look sufficiently like pathspecs that we'll consider
+ * them such for the purposes of rev/pathspec DWIM parsing.
+ */
+static int looks_like_pathspec(const char *arg)
+{
+       /* anything with a wildcard character */
+       if (!no_wildcard(arg))
+               return 1;
+
+       /* long-form pathspec magic */
+       if (starts_with(arg, ":("))
+               return 1;
+
+       return 0;
+}
+
 /*
  * Verify a filename that we got as an argument for a pathspec
  * entry. Note that a filename that begins with "-" never verifies
@@ -207,7 +230,7 @@ void verify_filename(const char *prefix,
 {
        if (*arg == '-')
                die("bad flag '%s' used after filename", arg);
-       if (check_filename(prefix, arg) || !no_wildcard(arg))
+       if (looks_like_pathspec(arg) || check_filename(prefix, arg))
                return;
        die_verify_filename(prefix, arg, diagnose_misspelt_rev);
 }
@@ -945,19 +968,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;
        }
 
        /*
@@ -973,8 +998,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);
 
@@ -982,10 +1009,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)
index feb227a8377cd3ca5fb524fd04ebccb713dede4b..a900b280428fa4931b1a60a9ac788edaff89634e 100644 (file)
@@ -7,6 +7,7 @@
  * creation etc.
  */
 #include "cache.h"
+#include "config.h"
 #include "string-list.h"
 #include "lockfile.h"
 #include "delta.h"
index e9ffe685d58366dc3802986519e3e2fd22c151a4..d2d732c19b62dd13c27852fcbf2385b29dd58b1d 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "tag.h"
 #include "commit.h"
 #include "tree.h"
@@ -1408,7 +1409,7 @@ static void diagnose_invalid_sha1_path(const char *prefix,
        if (file_exists(filename))
                die("Path '%s' exists on disk, but not in '%.*s'.",
                    filename, object_name_len, object_name);
-       if (errno == ENOENT || errno == ENOTDIR) {
+       if (is_missing_file_error(errno)) {
                char *fullname = xstrfmt("%s%s", prefix, filename);
 
                if (!get_tree_entry(tree_sha1, fullname,
@@ -1473,7 +1474,7 @@ static void diagnose_invalid_index_path(int stage,
 
        if (file_exists(filename))
                die("Path '%s' exists on disk, but not in the index.", filename);
-       if (errno == ENOENT || errno == ENOTDIR)
+       if (is_missing_file_error(errno))
                die("Path '%s' does not exist (neither on disk nor in the index).",
                    filename);
 
index 7d451e1cde8d8a5af93695d2fcaf58e76e30ec84..d9a45cd359a780d77d2dc01bd8a315d49a6a994f 100644 (file)
@@ -7,7 +7,7 @@
 
 /*
  * Generic implementation of background process infrastructure.
- * See Documentation/technical/api-background-process.txt.
+ * See: Documentation/technical/api-sub-process.txt
  */
 
  /* data structures */
index 4f58491ddb0705ab56e238006199d35db19dfb5a..d8f8d5ea3277d4dcfc8119e726e2f78c9aa881c9 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "submodule-config.h"
 #include "submodule.h"
 #include "strbuf.h"
index bf5a93d16fb71cdeb87f589732b6f95f4a83fbe0..da0b805493b9e7cd4c26f027a9f24c823109850a 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "submodule-config.h"
 #include "submodule.h"
 #include "dir.h"
 #include "quote.h"
 #include "remote.h"
 #include "worktree.h"
+#include "parse-options.h"
 
 static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
-static int config_update_recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
+static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF;
 static int parallel_jobs = 1;
 static struct string_list changed_submodule_paths = STRING_LIST_INIT_DUP;
 static int initialized_fetch_ref_tips;
@@ -153,7 +155,8 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
        }
 }
 
-int submodule_config(const char *var, const char *value, void *cb)
+/* For loading from the .gitmodules file. */
+static int git_modules_config(const char *var, const char *value, void *cb)
 {
        if (!strcmp(var, "submodule.fetchjobs")) {
                parallel_jobs = git_config_int(var, value);
@@ -169,6 +172,56 @@ int submodule_config(const char *var, const char *value, void *cb)
        return 0;
 }
 
+/* Loads all submodule settings from the config. */
+int submodule_config(const char *var, const char *value, void *cb)
+{
+       if (!strcmp(var, "submodule.recurse")) {
+               int v = git_config_bool(var, value) ?
+                       RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
+               config_update_recurse_submodules = v;
+               return 0;
+       } else {
+               return git_modules_config(var, value, cb);
+       }
+}
+
+/* Cheap function that only determines if we're interested in submodules at all */
+int git_default_submodule_config(const char *var, const char *value, void *cb)
+{
+       if (!strcmp(var, "submodule.recurse")) {
+               int v = git_config_bool(var, value) ?
+                       RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
+               config_update_recurse_submodules = v;
+       }
+       return 0;
+}
+
+int option_parse_recurse_submodules_worktree_updater(const struct option *opt,
+                                                    const char *arg, int unset)
+{
+       if (unset) {
+               config_update_recurse_submodules = RECURSE_SUBMODULES_OFF;
+               return 0;
+       }
+       if (arg)
+               config_update_recurse_submodules =
+                       parse_update_recurse_submodules_arg(opt->long_name,
+                                                           arg);
+       else
+               config_update_recurse_submodules = RECURSE_SUBMODULES_ON;
+
+       return 0;
+}
+
+void load_submodule_cache(void)
+{
+       if (config_update_recurse_submodules == RECURSE_SUBMODULES_OFF)
+               return;
+
+       gitmodules_config();
+       git_config(submodule_config, NULL);
+}
+
 void gitmodules_config(void)
 {
        const char *work_tree = get_git_work_tree();
@@ -196,7 +249,8 @@ void gitmodules_config(void)
                }
 
                if (!gitmodules_is_unmerged)
-                       git_config_from_file(submodule_config, gitmodules_path.buf, NULL);
+                       git_config_from_file(git_modules_config,
+                               gitmodules_path.buf, NULL);
                strbuf_release(&gitmodules_path);
        }
 }
@@ -207,7 +261,7 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)
        unsigned char sha1[20];
 
        if (gitmodule_sha1_from_commit(commit_sha1, sha1, &rev)) {
-               git_config_from_blob_sha1(submodule_config, rev.buf,
+               git_config_from_blob_sha1(git_modules_config, rev.buf,
                                          sha1, NULL);
        }
        strbuf_release(&rev);
@@ -660,11 +714,6 @@ void set_config_fetch_recurse_submodules(int value)
        config_fetch_recurse_submodules = value;
 }
 
-void set_config_update_recurse_submodules(int value)
-{
-       config_update_recurse_submodules = value;
-}
-
 int should_update_submodules(void)
 {
        return config_update_recurse_submodules == RECURSE_SUBMODULES_ON;
index 8fb0f25498d58344adb86fee53770bb11cf36cbc..cbe5c1726f9adab2b032d872d4bd84425e6ce518 100644 (file)
@@ -39,6 +39,12 @@ extern void stage_updated_gitmodules(void);
 extern void set_diffopt_flags_from_submodule_config(struct diff_options *,
                const char *path);
 extern int submodule_config(const char *var, const char *value, void *cb);
+extern int git_default_submodule_config(const char *var, const char *value, void *cb);
+
+struct option;
+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 gitmodules_config_sha1(const unsigned char *commit_sha1);
 extern int is_submodule_initialized(const char *path);
@@ -69,7 +75,6 @@ extern void show_submodule_inline_diff(FILE *f, const char *path,
                const char *del, const char *add, const char *reset,
                const struct diff_options *opt);
 extern void set_config_fetch_recurse_submodules(int value);
-extern void set_config_update_recurse_submodules(int value);
 /* Check if we want to update any submodule.*/
 extern int should_update_submodules(void);
 /*
index 8e3ed6a76cb97831e85152af8e9da21d18ed2fc1..1a7b8bd3d650fe1111c77115d2c68644b6ac9edb 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "string-list.h"
 
 /*
index 2f144d539a4822619a9383ded2d3adb270484624..c6c57bba0d397e44e8897b05d479a30b53311517 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "submodule-config.h"
 #include "submodule.h"
 
index 58bd4aeb2c52c67831a1dced2ef6b09755d417d3..2d26f86800906ab1783edf10e7196adadd5f4af7 100755 (executable)
@@ -781,8 +781,9 @@ test_submodule_forced_switch () {
 # - Removing a submodule with a git directory absorbs the submodules
 #   git directory first into the superproject.
 
-test_submodule_switch_recursing () {
-       command="$1"
+test_submodule_switch_recursing_with_args () {
+       cmd_args="$1"
+       command="git $cmd_args --recurse-submodules"
        RESULTDS=success
        if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1
        then
@@ -984,6 +985,18 @@ test_submodule_switch_recursing () {
                )
        '
 
+       test_expect_success "git -c submodule.recurse=true $cmd_args: modified submodule updates submodule work tree" '
+               prolog &&
+               reset_work_tree_to_interested add_sub1 &&
+               (
+                       cd submodule_update &&
+                       git branch -t modify_sub1 origin/modify_sub1 &&
+                       git -c submodule.recurse=true $cmd_args modify_sub1 &&
+                       test_superproject_content origin/modify_sub1 &&
+                       test_submodule_content sub1 origin/modify_sub1
+               )
+       '
+
        # Updating a submodule to an invalid sha1 doesn't update the
        # superproject nor the submodule's work tree.
        test_expect_success "$command: updating to a missing submodule commit fails" '
@@ -1016,8 +1029,9 @@ test_submodule_switch_recursing () {
 # Test that submodule contents are updated when switching between commits
 # that change a submodule, but throwing away local changes in
 # the superproject as well as the submodule is allowed.
-test_submodule_forced_switch_recursing () {
-       command="$1"
+test_submodule_forced_switch_recursing_with_args () {
+       cmd_args="$1"
+       command="git $cmd_args --recurse-submodules"
        RESULT=success
        if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1
        then
index b6fc880395791c6f33577dc83387939ceb786bbf..b50211b2591d19904fa3c995b01aea2121db476a 100644 (file)
@@ -108,7 +108,14 @@ test_perf_create_repo_from () {
                cd "$repo" &&
                "$MODERN_GIT" init -q &&
                test_perf_do_repo_symlink_config_ &&
-               mv .git/hooks .git/hooks-disabled 2>/dev/null
+               mv .git/hooks .git/hooks-disabled 2>/dev/null &&
+               if test -f .git/index.lock
+               then
+                       # We may be copying a repo that can't run "git
+                       # status" due to a locked index. Since we have
+                       # a copy it's fine to remove the lock.
+                       rm .git/index.lock
+               fi
        ) || error "failed to copy repository '$source' to '$repo'"
 }
 
index 8faba2e8bc52a2611eb55dbd807f9eba34748698..487b92a5de3238821ed3d8aadadb1f07d35e0609 100755 (executable)
@@ -49,4 +49,16 @@ test_expect_success "--help does not work for guides" "
        test_i18ncmp expect actual
 "
 
+test_expect_success 'generate builtin list' '
+       git --list-builtins >builtins
+'
+
+while read builtin
+do
+       test_expect_success "$builtin can handle -h" '
+               test_expect_code 129 git $builtin -h >output 2>&1 &&
+               test_i18ngrep usage output
+       '
+done <builtins
+
 test_done
index 7019d0a04feb7714f0ed8aad1d093c3a3878c78a..91a6fafcb425f367192c7eb4e4cdf0ae4d19ac37 100755 (executable)
@@ -8,9 +8,9 @@ test_description='read-tree can handle submodules'
 KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
 KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1
 
-test_submodule_switch_recursing "git read-tree --recurse-submodules -u -m"
+test_submodule_switch_recursing_with_args "read-tree -u -m"
 
-test_submodule_forced_switch_recursing "git read-tree --recurse-submodules -u --reset"
+test_submodule_forced_switch_recursing_with_args "read-tree -u --reset"
 
 test_submodule_switch "git read-tree -u -m"
 
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 ff50960ccaed9953c5738c9bbf602bf0d326e15a..bafed5c9b88481992ca6cf4cd6c13596c7baf16b 100755 (executable)
@@ -183,11 +183,22 @@ test_expect_success 'proper error on non-existent files' '
        test_cmp expect actual
 '
 
+test_expect_success 'proper error on directory "files"' '
+       echo "Error (-1) reading configuration file a-directory." >expect &&
+       mkdir a-directory &&
+       test_expect_code 2 test-config configset_get_value foo.bar a-directory 2>output &&
+       grep "^warning:" output &&
+       grep "^Error" output >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success POSIXPERM,SANITY 'proper error on non-accessible files' '
        chmod -r .git/config &&
        test_when_finished "chmod +r .git/config" &&
        echo "Error (-1) reading configuration file .git/config." >expect &&
-       test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>actual &&
+       test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>output &&
+       grep "^warning:" output &&
+       grep "^Error" output >actual &&
        test_cmp expect actual
 '
 
@@ -215,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 aa3522336966749fbea6e8dbe6d8f32cf711a021..6ef15738e44ed8ad82960c042b3212fce266ec93 100755 (executable)
@@ -64,9 +64,9 @@ test_expect_success '"checkout <submodule>" honors submodule.*.ignore from .git/
 '
 
 KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
-test_submodule_switch_recursing "git checkout --recurse-submodules"
+test_submodule_switch_recursing_with_args "checkout"
 
-test_submodule_forced_switch_recursing "git checkout -f --recurse-submodules"
+test_submodule_forced_switch_recursing_with_args "checkout -f"
 
 test_submodule_switch "git checkout"
 
index 66606e7508559e343d1b6959397dec77ddf5c6ac..3f3531f0a49be39e29b20a36a55f0d27f04b4fc8 100755 (executable)
@@ -404,8 +404,20 @@ test_expect_success 'log with various grep.patternType configurations & command-
                        --grep="(1|2)" >actual.fixed.short-arg &&
                git log --pretty=tformat:%s -E \
                        --grep="\|2" >actual.extended.short-arg &&
+               if test_have_prereq PCRE
+               then
+                       git log --pretty=tformat:%s -P \
+                               --grep="[\d]\|" >actual.perl.short-arg
+               else
+                       test_must_fail git log -P \
+                               --grep="[\d]\|"
+               fi &&
                test_cmp expect.fixed actual.fixed.short-arg &&
                test_cmp expect.extended actual.extended.short-arg &&
+               if test_have_prereq PCRE
+               then
+                       test_cmp expect.perl actual.perl.short-arg
+               fi &&
 
                git log --pretty=tformat:%s --fixed-strings \
                        --grep="(1|2)" >actual.fixed.long-arg &&
index 001343e2fc2722506172e702266f5bab6278d1e8..935df6a65cab2ba901856633baad7b2e38ebecfa 100755 (executable)
@@ -29,6 +29,12 @@ test_expect_success '"git log -- :/a" should not be ambiguous' '
        git log -- :/a
 '
 
+# This differs from the ":/a" check above in that :/in looks like a pathspec,
+# but doesn't match an actual file.
+test_expect_success '"git log :/in" should not be ambiguous' '
+       git log :/in
+'
+
 test_expect_success '"git log :" should be ambiguous' '
        test_must_fail git log : 2>error &&
        test_i18ngrep ambiguous error
@@ -46,6 +52,32 @@ test_expect_success 'git log HEAD -- :/' '
        test_cmp expected actual
 '
 
+test_expect_success '"git log :^sub" is not ambiguous' '
+       git log :^sub
+'
+
+test_expect_success '"git log :^does-not-exist" does not match anything' '
+       test_must_fail git log :^does-not-exist
+'
+
+test_expect_success  '"git log :!" behaves the same as :^' '
+       git log :!sub &&
+       test_must_fail git log :!does-not-exist
+'
+
+test_expect_success '"git log :(exclude)sub" is not ambiguous' '
+       git log ":(exclude)sub"
+'
+
+test_expect_success '"git log :(exclude)sub --" must resolve as an object' '
+       test_must_fail git log ":(exclude)sub" --
+'
+
+test_expect_success '"git log :(unknown-magic) complains of bogus magic' '
+       test_must_fail git log ":(unknown-magic)" 2>error &&
+       test_i18ngrep pathspec.magic error
+'
+
 test_expect_success 'command line pathspec parsing for "git log"' '
        git reset --hard &&
        >a &&
index a8a587abc3799f069deab3bc48914cea81bb15cf..9372508c993e72ad99da004ca2400df81c721006 100755 (executable)
@@ -139,7 +139,13 @@ test_expect_success 'bogus offset into v2 extended table' '
 test_expect_success 'bogus offset inside v2 extended table' '
        # We need two objects here, so we can plausibly require
        # an extended table (if the first object were larger than 2^31).
-       do_pack "$object $(git rev-parse HEAD)" --index-version=2 &&
+       #
+       # Note that the value is important here. We want $object as
+       # the second entry in sorted-sha1 order. The sha1 of 1485 starts
+       # with "000", which sorts before that of $object (which starts
+       # with "fff").
+       second=$(echo 1485 | git hash-object -w --stdin) &&
+       do_pack "$object $second" --index-version=2 &&
 
        # We have to make extra room for the table, so we cannot
        # just munge in place as usual.
index 94fc9be9ced3c89214b29e11c95201a38cc99d74..02106c9226605f3b241160a8b46e6dbf3a9d3fc0 100755 (executable)
@@ -85,8 +85,15 @@ test_expect_success 'use branch.<name>.remote if possible' '
 '
 
 test_expect_success 'confuses pattern as remote when no remote specified' '
-       cat >exp <<-\EOF &&
-       fatal: '\''refs*master'\'' does not appear to be a git repository
+       if test_have_prereq MINGW
+       then
+               # Windows does not like asterisks in pathname
+               does_not_exist=master
+       else
+               does_not_exist="refs*master"
+       fi &&
+       cat >exp <<-EOF &&
+       fatal: '\''$does_not_exist'\'' does not appear to be a git repository
        fatal: Could not read from remote repository.
 
        Please make sure you have the correct access rights
@@ -98,7 +105,7 @@ test_expect_success 'confuses pattern as remote when no remote specified' '
        # fetch <branch>.
        # We could just as easily have used "master"; the "*" emphasizes its
        # role as a pattern.
-       test_must_fail git ls-remote refs*master >actual 2>&1 &&
+       test_must_fail git ls-remote "$does_not_exist" >actual 2>&1 &&
        test_i18ncmp exp actual
 '
 
index f3b0a8d30afcb472398bef8623a49ba6bac7dc24..162baf101f340885619e0a1e67b0b14cf37a2347 100755 (executable)
@@ -71,6 +71,16 @@ test_expect_success "fetch --recurse-submodules recurses into submodules" '
        test_i18ncmp expect.err actual.err
 '
 
+test_expect_success "submodule.recurse option triggers recursive fetch" '
+       add_upstream_commit &&
+       (
+               cd downstream &&
+               git -c submodule.recurse fetch >../actual.out 2>../actual.err
+       ) &&
+       test_must_be_empty actual.out &&
+       test_i18ncmp expect.err actual.err
+'
+
 test_expect_success "fetch --recurse-submodules -j2 has the same output behaviour" '
        add_upstream_commit &&
        (
index 23c533e82e71e3b6ed26fc69313c4b51c36c3faa..beff65b8ace505d78c3997a737711ee7fc6383b5 100755 (executable)
@@ -126,6 +126,27 @@ test_expect_success 'push succeeds if submodule commit not on remote but using o
        )
 '
 
+test_expect_success 'push succeeds if submodule commit not on remote but using auto-on-demand via submodule.recurse config' '
+       (
+               cd work/gar/bage &&
+               >recurse-on-demand-from-submodule-recurse-config &&
+               git add recurse-on-demand-from-submodule-recurse-config &&
+               git commit -m "Recurse submodule.recurse from config junk"
+       ) &&
+       (
+               cd work &&
+               git add gar/bage &&
+               git commit -m "Recurse submodule.recurse from config for gar/bage" &&
+               git -c submodule.recurse push ../pub.git master &&
+               # Check that the supermodule commit got there
+               git fetch ../pub.git &&
+               git diff --quiet FETCH_HEAD master &&
+               # Check that the submodule commit got there too
+               cd gar/bage &&
+               git diff --quiet origin/master master
+       )
+'
+
 test_expect_success 'push recurse-submodules on command line overrides config' '
        (
                cd work/gar/bage &&
index b195f71ea98423711d57c6d31ea8eca5eb5bca5c..b322c2f72202fbfda5c74f8d085744dd29c55fb3 100755 (executable)
@@ -1,10 +1,10 @@
 #!/bin/sh
 
-test_description='various UNC path tests (Windows-only)'
+test_description='various Windows-only path tests'
 . ./test-lib.sh
 
 if ! test_have_prereq MINGW; then
-       skip_all='skipping UNC path tests, requires Windows'
+       skip_all='skipping Windows-only path tests'
        test_done
 fi
 
@@ -45,4 +45,10 @@ test_expect_success push '
        test "$rev" = "$(git rev-parse --verify refs/heads/to-push)"
 '
 
+test_expect_success 'remote nick cannot contain backslashes' '
+       BACKSLASHED="$(pwd | tr / \\\\)" &&
+       git ls-remote "$BACKSLASHED" >out 2>err &&
+       test_i18ngrep ! "unable to access" err
+'
+
 test_done
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 f86ccdf215abe725a0fb7ce35fb4760f25fb1b8c..a1cb9ff858e4a2113bbf7fb732b9e6d0cb308445 100755 (executable)
@@ -9,9 +9,9 @@ KNOWN_FAILURE_SUBMODULE_RECURSIVE_NESTED=1
 KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
 KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1
 
-test_submodule_switch_recursing "git reset --recurse-submodules --keep"
+test_submodule_switch_recursing_with_args "reset --keep"
 
-test_submodule_forced_switch_recursing "git reset --hard --recurse-submodules"
+test_submodule_forced_switch_recursing_with_args "reset --hard"
 
 test_submodule_switch "git reset --keep"
 
index 3a58197f472f38c320de33fa82896c0a77d125ae..7184113b9b2b381a6e7e0def8a8c1ba06771f8a6 100755 (executable)
@@ -33,6 +33,24 @@ test_expect_success 'grep correctly finds patterns in a submodule' '
        test_cmp expect actual
 '
 
+test_expect_success 'grep finds patterns in a submodule via config' '
+       test_config submodule.recurse true &&
+       # expect from previous test
+       git grep -e "(3|4)" >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'grep --no-recurse-submodules overrides config' '
+       test_config submodule.recurse true &&
+       cat >expect <<-\EOF &&
+       a:(1|2)d(3|4)
+       b/b:(3|4)
+       EOF
+
+       git grep -e "(3|4)" --no-recurse-submodules >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'grep and basic pathspecs' '
        cat >expect <<-\EOF &&
        submodule/a:(1|2)d(3|4)
index 4936725c675f9dd3290e40722d8e40d63f3c874c..2306574dc9bacbfbb69469d95563b429a4cbb893 100644 (file)
@@ -1020,7 +1020,7 @@ esac
 test -z "$NO_PERL" && test_set_prereq PERL
 test -z "$NO_PTHREADS" && test_set_prereq PTHREADS
 test -z "$NO_PYTHON" && test_set_prereq PYTHON
-test -n "$USE_LIBPCRE1" && test_set_prereq PCRE
+test -n "$USE_LIBPCRE1$USE_LIBPCRE2" && test_set_prereq PCRE
 test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
 
 # Can we rely on git's output in the C locale?
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 9bfcf870f9078f75349bd3b4976c71bbf5c49ebf..b9995306f259da0a929babdfe1fb5b99eaacead8 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "transport.h"
 #include "run-command.h"
 #include "pkt-line.h"
index e164e532b2f76617d822c3bef9492b9525b56e83..467e3817243567dadfaf853fddef8a0ef894f270 100644 (file)
 } while(0)
 
 static struct combine_diff_path *ll_diff_tree_paths(
-       struct combine_diff_path *p, const unsigned char *sha1,
-       const unsigned char **parents_sha1, int nparent,
+       struct combine_diff_path *p, const struct object_id *oid,
+       const struct object_id **parents_oid, int nparent,
        struct strbuf *base, struct diff_options *opt);
-static int ll_diff_tree_sha1(const unsigned char *old, const unsigned char *new,
-                            struct strbuf *base, struct diff_options *opt);
+static int ll_diff_tree_oid(const struct object_id *old_oid,
+                           const struct object_id *new_oid,
+                           struct strbuf *base, struct diff_options *opt);
 
 /*
  * Compare two tree entries, taking into account only path/S_ISDIR(mode),
@@ -74,25 +75,25 @@ static int emit_diff_first_parent_only(struct diff_options *opt, struct combine_
 {
        struct combine_diff_parent *p0 = &p->parent[0];
        if (p->mode && p0->mode) {
-               opt->change(opt, p0->mode, p->mode, p0->oid.hash, p->oid.hash,
+               opt->change(opt, p0->mode, p->mode, &p0->oid, &p->oid,
                        1, 1, p->path, 0, 0);
        }
        else {
-               const unsigned char *sha1;
+               const struct object_id *oid;
                unsigned int mode;
                int addremove;
 
                if (p->mode) {
                        addremove = '+';
-                       sha1 = p->oid.hash;
+                       oid = &p->oid;
                        mode = p->mode;
                } else {
                        addremove = '-';
-                       sha1 = p0->oid.hash;
+                       oid = &p0->oid;
                        mode = p0->mode;
                }
 
-               opt->add_remove(opt, addremove, mode, sha1, 1, p->path, 0);
+               opt->add_remove(opt, addremove, mode, oid, 1, p->path, 0);
        }
 
        return 0;       /* we are done with p */
@@ -131,7 +132,7 @@ static int emit_diff_first_parent_only(struct diff_options *opt, struct combine_
  */
 static struct combine_diff_path *path_appendnew(struct combine_diff_path *last,
        int nparent, const struct strbuf *base, const char *path, int pathlen,
-       unsigned mode, const unsigned char *sha1)
+       unsigned mode, const struct object_id *oid)
 {
        struct combine_diff_path *p;
        size_t len = st_add(base->len, pathlen);
@@ -161,7 +162,7 @@ static struct combine_diff_path *path_appendnew(struct combine_diff_path *last,
        memcpy(p->path + base->len, path, pathlen);
        p->path[len] = 0;
        p->mode = mode;
-       hashcpy(p->oid.hash, sha1 ? sha1 : null_sha1);
+       oidcpy(&p->oid, oid ? oid : &null_oid);
 
        return p;
 }
@@ -183,7 +184,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p,
 {
        unsigned mode;
        const char *path;
-       const unsigned char *sha1;
+       const struct object_id *oid;
        int pathlen;
        int old_baselen = base->len;
        int i, isdir, recurse = 0, emitthis = 1;
@@ -193,7 +194,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p,
 
        if (t) {
                /* path present in resulting tree */
-               sha1 = tree_entry_extract(t, &path, &mode)->hash;
+               oid = tree_entry_extract(t, &path, &mode);
                pathlen = tree_entry_len(&t->entry);
                isdir = S_ISDIR(mode);
        } else {
@@ -208,7 +209,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p,
                pathlen = tree_entry_len(&tp[imin].entry);
 
                isdir = S_ISDIR(mode);
-               sha1 = NULL;
+               oid = NULL;
                mode = 0;
        }
 
@@ -220,7 +221,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p,
        if (emitthis) {
                int keep;
                struct combine_diff_path *pprev = p;
-               p = path_appendnew(p, nparent, base, path, pathlen, mode, sha1);
+               p = path_appendnew(p, nparent, base, path, pathlen, mode, oid);
 
                for (i = 0; i < nparent; ++i) {
                        /*
@@ -229,7 +230,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p,
                         */
                        int tpi_valid = tp && !(tp[i].entry.mode & S_IFXMIN_NEQ);
 
-                       const unsigned char *sha1_i;
+                       const struct object_id *oid_i;
                        unsigned mode_i;
 
                        p->parent[i].status =
@@ -239,16 +240,16 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p,
                                                DIFF_STATUS_ADDED;
 
                        if (tpi_valid) {
-                               sha1_i = tp[i].entry.oid->hash;
+                               oid_i = tp[i].entry.oid;
                                mode_i = tp[i].entry.mode;
                        }
                        else {
-                               sha1_i = NULL;
+                               oid_i = &null_oid;
                                mode_i = 0;
                        }
 
                        p->parent[i].mode = mode_i;
-                       hashcpy(p->parent[i].oid.hash, sha1_i ? sha1_i : null_sha1);
+                       oidcpy(&p->parent[i].oid, oid_i);
                }
 
                keep = 1;
@@ -273,21 +274,20 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p,
        }
 
        if (recurse) {
-               const unsigned char **parents_sha1;
+               const struct object_id **parents_oid;
 
-               FAST_ARRAY_ALLOC(parents_sha1, nparent);
+               FAST_ARRAY_ALLOC(parents_oid, nparent);
                for (i = 0; i < nparent; ++i) {
                        /* same rule as in emitthis */
                        int tpi_valid = tp && !(tp[i].entry.mode & S_IFXMIN_NEQ);
 
-                       parents_sha1[i] = tpi_valid ? tp[i].entry.oid->hash
-                                                   : NULL;
+                       parents_oid[i] = tpi_valid ? tp[i].entry.oid : NULL;
                }
 
                strbuf_add(base, path, pathlen);
                strbuf_addch(base, '/');
-               p = ll_diff_tree_paths(p, sha1, parents_sha1, nparent, base, opt);
-               FAST_ARRAY_FREE(parents_sha1, nparent);
+               p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt);
+               FAST_ARRAY_FREE(parents_oid, nparent);
        }
 
        strbuf_setlen(base, old_baselen);
@@ -312,7 +312,7 @@ static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
 
 
 /*
- * generate paths for combined diff D(sha1,parents_sha1[])
+ * generate paths for combined diff D(sha1,parents_oid[])
  *
  * Resulting paths are appended to combine_diff_path linked list, and also, are
  * emitted on the go via opt->pathchange() callback, so it is possible to
@@ -404,8 +404,8 @@ static inline void update_tp_entries(struct tree_desc *tp, int nparent)
 }
 
 static struct combine_diff_path *ll_diff_tree_paths(
-       struct combine_diff_path *p, const unsigned char *sha1,
-       const unsigned char **parents_sha1, int nparent,
+       struct combine_diff_path *p, const struct object_id *oid,
+       const struct object_id **parents_oid, int nparent,
        struct strbuf *base, struct diff_options *opt)
 {
        struct tree_desc t, *tp;
@@ -419,11 +419,11 @@ static struct combine_diff_path *ll_diff_tree_paths(
         * load parents first, as they are probably already cached.
         *
         * ( log_tree_diff() parses commit->parent before calling here via
-        *   diff_tree_sha1(parent, commit) )
+        *   diff_tree_oid(parent, commit) )
         */
        for (i = 0; i < nparent; ++i)
-               tptree[i] = fill_tree_descriptor(&tp[i], parents_sha1[i]);
-       ttree = fill_tree_descriptor(&t, sha1);
+               tptree[i] = fill_tree_descriptor(&tp[i], parents_oid[i]->hash);
+       ttree = fill_tree_descriptor(&t, oid->hash);
 
        /* Enable recursion indefinitely */
        opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
@@ -548,11 +548,11 @@ static struct combine_diff_path *ll_diff_tree_paths(
 }
 
 struct combine_diff_path *diff_tree_paths(
-       struct combine_diff_path *p, const unsigned char *sha1,
-       const unsigned char **parents_sha1, int nparent,
+       struct combine_diff_path *p, const struct object_id *oid,
+       const struct object_id **parents_oid, int nparent,
        struct strbuf *base, struct diff_options *opt)
 {
-       p = ll_diff_tree_paths(p, sha1, parents_sha1, nparent, base, opt);
+       p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt);
 
        /*
         * free pre-allocated last element, if any
@@ -577,7 +577,9 @@ static inline int diff_might_be_rename(void)
                !DIFF_FILE_VALID(diff_queued_diff.queue[0]->one);
 }
 
-static void try_to_follow_renames(const unsigned char *old, const unsigned char *new, struct strbuf *base, struct diff_options *opt)
+static void try_to_follow_renames(const struct object_id *old_oid,
+                                 const struct object_id *new_oid,
+                                 struct strbuf *base, struct diff_options *opt)
 {
        struct diff_options diff_opts;
        struct diff_queue_struct *q = &diff_queued_diff;
@@ -615,7 +617,7 @@ static void try_to_follow_renames(const unsigned char *old, const unsigned char
        diff_opts.break_opt = opt->break_opt;
        diff_opts.rename_score = opt->rename_score;
        diff_setup_done(&diff_opts);
-       ll_diff_tree_sha1(old, new, base, &diff_opts);
+       ll_diff_tree_oid(old_oid, new_oid, base, &diff_opts);
        diffcore_std(&diff_opts);
        clear_pathspec(&diff_opts.pathspec);
 
@@ -674,15 +676,16 @@ static void try_to_follow_renames(const unsigned char *old, const unsigned char
        q->nr = 1;
 }
 
-static int ll_diff_tree_sha1(const unsigned char *old, const unsigned char *new,
-                            struct strbuf *base, struct diff_options *opt)
+static int ll_diff_tree_oid(const struct object_id *old_oid,
+                           const struct object_id *new_oid,
+                           struct strbuf *base, struct diff_options *opt)
 {
        struct combine_diff_path phead, *p;
        pathchange_fn_t pathchange_old = opt->pathchange;
 
        phead.next = NULL;
        opt->pathchange = emit_diff_first_parent_only;
-       diff_tree_paths(&phead, new, &old, 1, base, opt);
+       diff_tree_paths(&phead, new_oid, &old_oid, 1, base, opt);
 
        for (p = phead.next; p;) {
                struct combine_diff_path *pprev = p;
@@ -694,7 +697,9 @@ static int ll_diff_tree_sha1(const unsigned char *old, const unsigned char *new,
        return 0;
 }
 
-int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base_str, struct diff_options *opt)
+int diff_tree_oid(const struct object_id *old_oid,
+                 const struct object_id *new_oid,
+                 const char *base_str, struct diff_options *opt)
 {
        struct strbuf base;
        int retval;
@@ -702,16 +707,16 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha
        strbuf_init(&base, PATH_MAX);
        strbuf_addstr(&base, base_str);
 
-       retval = ll_diff_tree_sha1(old, new, &base, opt);
+       retval = ll_diff_tree_oid(old_oid, new_oid, &base, opt);
        if (!*base_str && DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename())
-               try_to_follow_renames(old, new, &base, opt);
+               try_to_follow_renames(old_oid, new_oid, &base, opt);
 
        strbuf_release(&base);
 
        return retval;
 }
 
-int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_options *opt)
+int diff_root_tree_oid(const struct object_id *new_oid, const char *base, struct diff_options *opt)
 {
-       return diff_tree_sha1(NULL, new, base, opt);
+       return diff_tree_oid(NULL, new_oid, base, opt);
 }
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"
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 d83741770949f457b364896b6ff8632c0a700d69..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)
 {
@@ -418,6 +419,32 @@ FILE *fopen_for_writing(const char *path)
        return ret;
 }
 
+static void warn_on_inaccessible(const char *path)
+{
+       warning_errno(_("unable to access '%s'"), path);
+}
+
+int warn_on_fopen_errors(const char *path)
+{
+       if (errno != ENOENT && errno != ENOTDIR) {
+               warn_on_inaccessible(path);
+               return -1;
+       }
+
+       return 0;
+}
+
+FILE *fopen_or_warn(const char *path, const char *mode)
+{
+       FILE *fp = fopen(path, mode);
+
+       if (fp)
+               return fp;
+
+       warn_on_fopen_errors(path);
+       return NULL;
+}
+
 int xmkstemp(char *template)
 {
        int fd;
@@ -576,15 +603,10 @@ int remove_or_warn(unsigned int mode, const char *file)
        return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file);
 }
 
-void warn_on_inaccessible(const char *path)
-{
-       warning_errno(_("unable to access '%s'"), path);
-}
-
 static int access_error_is_ok(int err, unsigned flag)
 {
-       return err == ENOENT || err == ENOTDIR ||
-               ((flag & ACCESS_EACCES_OK) && err == EACCES);
+       return (is_missing_file_error(err) ||
+               ((flag & ACCESS_EACCES_OK) && err == EACCES));
 }
 
 int access_or_warn(const char *path, int mode, unsigned flag)
index 25aafc35c8332a311ce89002e7c17b200ccbfde6..bf651f16fae83ffe30676790685799e8f2280082 100644 (file)
@@ -1066,7 +1066,8 @@ static void show_am_in_progress(struct wt_status *s,
 static char *read_line_from_git_path(const char *filename)
 {
        struct strbuf buf = STRBUF_INIT;
-       FILE *fp = fopen(git_path("%s", filename), "r");
+       FILE *fp = fopen_or_warn(git_path("%s", filename), "r");
+
        if (!fp) {
                strbuf_release(&buf);
                return NULL;
index 060038c2d6b92512e6625d0f5d94ed5439cd249c..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"
@@ -164,9 +165,9 @@ int read_mmfile(mmfile_t *ptr, const char *filename)
        size_t sz;
 
        if (stat(filename, &st))
-               return error("Could not stat %s", filename);
+               return error_errno("Could not stat %s", filename);
        if ((f = fopen(filename, "rb")) == NULL)
-               return error("Could not open %s", filename);
+               return error_errno("Could not open %s", filename);
        sz = xsize_t(st.st_size);
        ptr->ptr = xmalloc(sz ? sz : 1);
        if (sz && fread(ptr->ptr, sz, 1, f) != 1) {