Merge branch 'ah/filter-branch-setup'
authorJunio C Hamano <gitster@pobox.com>
Thu, 22 Jun 2017 21:15:21 +0000 (14:15 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 22 Jun 2017 21:15:21 +0000 (14:15 -0700)
"filter-branch" learned a pseudo filter "--setup" that can be used
to define a common function/variable that can be used by other
filters.

* ah/filter-branch-setup:
filter-branch: add [--] to usage
filter-branch: add `--setup` step

108 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
apply.c
attr.c
bisect.c
blame.c
builtin/am.c
builtin/blame.c
builtin/checkout.c
builtin/clone.c
builtin/commit.c
builtin/credential.c
builtin/diff-files.c
builtin/diff-index.c
builtin/diff-tree.c
builtin/diff.c
builtin/fast-export.c
builtin/fetch.c
builtin/fsck.c
builtin/grep.c
builtin/log.c
builtin/merge.c
builtin/notes.c
builtin/pull.c
builtin/push.c
builtin/read-tree.c
builtin/remote-ext.c
builtin/remote-fd.c
builtin/reset.c
builtin/rev-list.c
builtin/rm.c
builtin/show-branch.c
builtin/submodule--helper.c
builtin/update-index.c
builtin/upload-archive.c
cache.h
combine-diff.c
commit.c
compat/fopen.c
compat/mingw.c
config.c
config.mak.uname
configure.ac
contrib/completion/git-completion.bash
diff-lib.c
diff-no-index.c
diff.c
diff.h
diffcore-rename.c
diffcore.h
dir.c
dir.h
fast-import.c
git-compat-util.h
git.c
grep.c
grep.h
help.c
ident.c
line-log.c
log-tree.c
merge-recursive.c
notes-cache.c
notes-merge.c
notes-merge.h
notes-utils.c
notes-utils.h
notes.c
notes.h
patch-ids.c
patch-ids.h
remote-testsvn.c
remote.c
rerere.c
revision.c
sequencer.c
server-info.c
setup.c
sha1_name.c
sub-process.h
submodule.c
submodule.h
t/lib-submodule-update.sh
t/perf/perf-lib.sh
t/t0012-help.sh
t/t1013-read-tree-submodule.sh
t/t1308-config-set.sh
t/t2013-checkout-submodule.sh
t/t4005-diff-rename-2.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/t7112-reset-submodule.sh
t/t7814-grep-recurse-submodules.sh
t/test-lib.sh
tree-diff.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..b94cd5633c8ebda7e09874a1012fb75cbccc64e0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,8 @@ all::
 # have been written to the final string if enough space had been available.
 #
 # Define FREAD_READS_DIRECTORIES if you are on a system which succeeds
-# when attempting to read from an fopen'ed directory.
+# when attempting to read from an fopen'ed directory (or even to fopen
+# it at all).
 #
 # Define NO_OPENSSL environment variable if you do not have OpenSSL.
 # This also implies BLK_SHA1.
@@ -29,8 +30,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 +1105,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 +2281,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)))'\' >>$@+
diff --git a/apply.c b/apply.c
index c49cef0637355d33a7a1636fb283210784f14e02..679ed7732d2385c4d7704f60335514b2b5f75c39 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -762,17 +762,6 @@ static char *find_name_traditional(struct apply_state *state,
        return find_name_common(state, line, def, p_value, line + len, 0);
 }
 
-static int count_slashes(const char *cp)
-{
-       int cnt = 0;
-       char ch;
-
-       while ((ch = *cp++))
-               if (ch == '/')
-                       cnt++;
-       return cnt;
-}
-
 /*
  * Given the string after "--- " or "+++ ", guess the appropriate
  * p_value for the given patch.
@@ -3741,7 +3730,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;
diff --git a/attr.c b/attr.c
index 7e2134471cb4afc1b891208ebe4bebd6ad55571d..821203e2a980c329fc065a0dfabe37ef67a4bbbe 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -720,16 +720,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..2a2b9b7267acbb8752015d64ec477f64c6047875 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -438,10 +438,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 +666,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 843c845cbaf6bc9d60ec8dcf79bad1ce0669319c..194b58e96066f9620005f64a57ca9ecc618c86f4 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 5ee146bfb31df8e3d8edf356f4817e3f53f8ad3b..3985f9a89f985baa139ea69f5fde8ce1384871f6 100644 (file)
@@ -563,7 +563,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 +1275,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..749ad7f05b657ba34534a4ae6601dd5d85649b36 100644 (file)
@@ -481,7 +481,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 a6b2af39d3e881480193a38ff1ca3b65cdc55d94..1624eed7e7625c18da7ffb58f1b9ae456c3dbd77 100644 (file)
 #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 +857,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 +1165,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 +1198,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 743f16ae2aad7d71789f2b38287aea13cf29fc26..a2ea019c590190a00d1a7cf51a917c7ebdc7886c 100644 (file)
@@ -360,7 +360,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 da1ba4c86205ca55ae1880cb768b093b101bd85a..e3c9e190b06a63250a9c7eff3e256efcb10660f7 100644 (file)
@@ -1699,10 +1699,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;
 
@@ -1809,7 +1806,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 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 a572da9d5152ddf541f71e1aaf8abdb3c98f8ffe..c97069a714e42a1737b5dfa223fe39c26ad9aa67 100644 (file)
@@ -20,6 +20,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..d59bf6cf5f8da394251532765f27a044c14a572d 100644 (file)
@@ -17,6 +17,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..7e15d01f36396fdc6b630eb43a5f36d462fb78e6 100644 (file)
@@ -7,7 +7,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 +49,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 +98,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 +130,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 +151,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..d9152c21bf5a8aa41778f838b4d804ac698bdc2b 100644 (file)
@@ -56,8 +56,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 +174,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 +194,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 24e29ad7eab5edc0964a51f32602b062daabb907..a932be04f4d5f733eebe1ebeba82c1bc64de3088 100644 (file)
@@ -562,12 +562,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 +907,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..100248c5afe3e1c16fa7fe79696200aeb5d1bde2 100644 (file)
@@ -73,6 +73,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 cb2ba6cd1be46635ca8416a7d3f2b006f964190b..3a2c27f2413e5e377926e0e7df339549c37a76b3 100644 (file)
@@ -280,8 +280,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 7df9c253eebb3053693769d14efe0551393dfd4d..3e4b9600e86b661c99f4b936dfa574029ac4fbba 100644 (file)
@@ -224,7 +224,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 +303,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 +342,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 +351,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 +587,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 +600,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 +635,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 +649,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 +664,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 +673,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 +792,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 +1171,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 +1243,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 e89ec941ce2c97de7f8233a5e7e6f9010fabdb64..998437b23dcb32a45e4d722d695c86d3cc82b4bc 100644 (file)
@@ -846,8 +846,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 +863,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 +1052,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 +1363,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 a4a098f40f8e3e61c3f8b730a6b22a83c3c23566..84970cd85e8b0788928ff24b47c8c1b3dc3409e2 100644 (file)
@@ -415,7 +415,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 +839,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 7196bff0eb2454eee86f87241706523c0266e66e..c939a84b7629cd5d4dda09d427255410d723d95b 100644 (file)
@@ -109,11 +109,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 +129,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 +145,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 +157,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 +243,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 +292,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 +301,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 +352,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 +370,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 +393,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 +425,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 +439,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 +452,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 +476,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 +511,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 +554,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 +594,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 +617,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 +639,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 +656,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 +726,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 +762,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 +844,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 +880,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 da8b60fc85e93da880fb955992b8b753715fafda..69417e4f362f6d7baa11885bd1cb8c5cbb676b14 100644 (file)
@@ -337,8 +337,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..258648d5fd685f4284b3a2bbc0def0076a670b28 100644 (file)
@@ -498,6 +498,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..5bfd4c9f76d84c177b72a8ed97d3418d111583e9 100644 (file)
@@ -21,7 +21,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 +98,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 +147,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 +158,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 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 430602d102133d125009e8c8068ce5547c24cab7..45001e5200cb4c5aaf0ad316cf1622f9495d851d 100644 (file)
 #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 +265,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 +292,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..b250c515b1aecab2b43aebe591ad7a22d5829271 100644 (file)
@@ -277,6 +277,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 7c323d01235bf8bbb341004c843761dad99590d2..b39f10fcb64f047090967dbf8b31120d2beb1b67 100644 (file)
@@ -129,7 +129,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 4a6cc6f490f4e7b8a98adb362213535b6a9ae97d..3636a05594de18639bced97a1e18a128632bc00d 100644 (file)
@@ -5,6 +5,7 @@
 #include "color.h"
 #include "argv-array.h"
 #include "parse-options.h"
+#include "dir.h"
 
 static const char* show_branch_usage[] = {
     N_("git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
@@ -421,14 +422,6 @@ static int append_tag_ref(const char *refname, const struct object_id *oid,
 
 static const char *match_ref_pattern = NULL;
 static int match_ref_slash = 0;
-static int count_slash(const char *s)
-{
-       int cnt = 0;
-       while (*s)
-               if (*s++ == '/')
-                       cnt++;
-       return cnt;
-}
 
 static int append_matching_ref(const char *refname, const struct object_id *oid,
                               int flag, void *cb_data)
@@ -438,7 +431,7 @@ static int append_matching_ref(const char *refname, const struct object_id *oid,
         * refs/tags/v0.99.9a and friends.
         */
        const char *tail;
-       int slash = count_slash(refname);
+       int slash = count_slashes(refname);
        for (tail = refname; *tail && match_ref_slash < slash; )
                if (*tail++ == '/')
                        slash--;
@@ -529,7 +522,7 @@ static void append_one_rev(const char *av)
                int saved_matches = ref_name_cnt;
 
                match_ref_pattern = av;
-               match_ref_slash = count_slash(av);
+               match_ref_slash = count_slashes(av);
                for_each_ref(append_matching_ref, NULL);
                if (saved_matches == ref_name_cnt &&
                    ref_name_cnt < MAX_REVS)
index 8cc648d85b586752d39079e75cf81a4ee685b622..1b4d2b346762af8e6150d88fed87409e877ca676 100644 (file)
@@ -1221,9 +1221,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 ebfc09faa0d604218af8f5815af5e5fee5915158..f99b1e5790b9b6aeafaa88f438a8a50f1538c2fe 100644 (file)
@@ -257,7 +257,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 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.
         *
diff --git a/cache.h b/cache.h
index 4d92aae0e818015c1ec7a6d6bc99cb1391e0d824..d6ba8a2f11a63d4d9ec5257a75532414d22526c0 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1026,6 +1026,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);
index 2848034fe9c3f3cc1d930347e892cee1cbed4f52..ec9d930440993b265fe74aacd2a3fdb768dccf64 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 146cb3452adab3115f15d30c2b0f9f5480344279..34a139c40bd57ff2dd23318beca53fd2e2948000 100644 (file)
--- a/config.c
+++ b/config.c
@@ -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);
@@ -2656,6 +2656,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;
        }
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..2f55237e65acfcf9b7fed15ac0386d353eaf0105 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
 
@@ -869,9 +922,9 @@ AC_CACHE_CHECK([whether system succeeds to read fopen'ed directory],
 [
 AC_RUN_IFELSE(
        [AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
-               [[char c;
+               [[
                FILE *f = fopen(".", "r");
-               return f && fread(&c, 1, 1, f)]])],
+               return f)]])],
        [ac_cv_fread_reads_directories=no],
        [ac_cv_fread_reads_directories=yes])
 ])
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 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 5275c4b78011e90627c073f487f3f8298b483352..acedf86aecc151112898ff54575151f157776281 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -2702,13 +2702,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 +2717,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 +2748,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 +2768,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 +2842,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 +3008,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 +3030,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 +3239,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 +3298,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 +3344,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 +3368,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 +4071,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 +4582,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 +4614,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 +4654,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 +4669,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 +4805,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 +5077,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 +5110,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 +5123,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 +5138,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 +5149,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 +5277,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 9efcf1eab689bd0e637ea1b961b261eb97862b04..5f1afb56bc6e6d5dc5300380f980f4b2699ab08d 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -52,6 +52,15 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
 static int get_dtype(struct dirent *de, struct index_state *istate,
                     const char *path, int len);
 
+int count_slashes(const char *s)
+{
+       int cnt = 0;
+       while (*s)
+               if (*s++ == '/')
+                       cnt++;
+       return cnt;
+}
+
 int fspathcmp(const char *a, const char *b)
 {
        return ignore_case ? strcasecmp(a, b) : strcmp(a, b);
@@ -752,9 +761,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 +2346,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, '/');
diff --git a/dir.h b/dir.h
index a89c13e27a4fb55883f811a2c82fb465bb14988d..e3717055d193366e6780b50d68f6a3c2360d32c4 100644 (file)
--- a/dir.h
+++ b/dir.h
@@ -197,6 +197,9 @@ struct dir_struct {
        unsigned unmanaged_exclude_files;
 };
 
+/*Count the number of slashes for string s*/
+extern int count_slashes(const char *s);
+
 /*
  * The ordering of these constants is significant, with
  * higher-numbered match types signifying "closer" (i.e. more
index e69d219682e7929b6e8441ba620e708704471ff3..9a22fc92c0d029cf2a1362ea846f75f59978e870 100644 (file)
@@ -3285,9 +3285,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 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..1b8b7f51a65fa2a8e62d11d7ad99f19e2926977f 100644 (file)
--- a/git.c
+++ b/git.c
@@ -26,6 +26,8 @@ static const char *env_names[] = {
 static char *orig_env[4];
 static int save_restore_env_balance;
 
+static void list_builtins(void);
+
 static void save_env_before_alias(void)
 {
        int i;
@@ -232,6 +234,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);
@@ -529,6 +534,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)
 {
diff --git a/grep.c b/grep.c
index d03d424e5cf8d32d91e3082555d8add674e01486..d7ef21358ea7f592dffff98884eb34169e097880 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -179,22 +179,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 +380,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 +406,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 +433,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 +461,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 +647,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 +1011,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 +1093,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 +1584,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 +1928,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 +1952,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 +1964,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 +1975,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 +2021,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..f637fc80062094784d5734df91523642933ddcfc 100644 (file)
--- a/help.c
+++ b/help.c
@@ -9,6 +9,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)
 {
@@ -383,16 +384,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;
 }
diff --git a/ident.c b/ident.c
index bea871c8e02b7173eeba5527d22f5ae7783c011e..91c7609055bf3e0a4c0b7ae3cb46219ccaad53ef 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -72,12 +72,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 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 a4ec11c2bf62bbda4304d19913f25965247d4027..2903874ecf156c374ae0a120cdc20a5f5e41df53 100644 (file)
@@ -655,7 +655,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 +803,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 +822,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 +837,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 ae5238d82ca8c86b99391a0836a0539efe7eacde..5cc86df2d15729e9b0e8b36fdb151d5986f42a10 100644 (file)
@@ -528,7 +528,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..9ebf8419565019cca42d778be96e2f3b7d6f29df 100644 (file)
@@ -158,7 +158,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..4b3a1adda566bdc82ba7005083f37dff5bd62ed4 100644 (file)
--- a/notes.c
+++ b/notes.c
@@ -35,8 +35,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 +51,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 +65,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 +102,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 +120,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 +145,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 +196,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 +218,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 +248,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 +256,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 +264,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 +289,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 +303,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 +343,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 +375,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 +401,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 +415,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 +424,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 +445,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 +462,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 +488,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 +544,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 +601,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 +625,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 +656,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 +668,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 +679,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 +698,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 +728,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 +748,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 +758,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 +773,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 +785,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 +948,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 +1033,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 +1086,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 +1098,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 +1110,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 +1152,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 +1215,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 +1229,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 +1277,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 +1300,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 +1317,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);
 
 /*
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 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..f998f989e92a6eb919828c72d444f091d5fdfa6a 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -251,7 +251,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 +277,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..c26c29f87a6f35d2efffd226fa8922f36cd0bb37 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -200,7 +200,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 +484,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 924fb1d0c3c84dd823393d7dea21af2d70a8d54e..d63099d50fc4e23cb3585b12c61ba8863d2688f6 100644 (file)
@@ -899,8 +899,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 +919,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 +1381,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 +2130,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..751d02b9be627176009cdda4f1b20a3674b0dc95 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -134,23 +134,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 +185,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 +229,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);
 }
index e9ffe685d58366dc3802986519e3e2fd22c151a4..5126853bb5bda5f291039588db96064ffbd1ee5c 100644 (file)
@@ -1408,7 +1408,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 +1473,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 bf5a93d16fb71cdeb87f589732b6f95f4a83fbe0..1b8a3b575db6c85a42e9c9e285617113ecac4a84 100644 (file)
 #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 +154,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 +171,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 +248,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 +260,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 +713,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 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 ff50960ccaed9953c5738c9bbf602bf0d326e15a..e495a616161660bcade644dea42b5c8e53cc64b3 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
 '
 
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 135addbfbdae8e39ba0462e71278f41dfc552620..f542d2929d2316fa8d858fc29c1bdfb5ef4c3c71 100755 (executable)
@@ -3,84 +3,75 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
-test_description='Same rename detection as t4003 but testing diff-raw.
+test_description='Same rename detection as t4003 but testing diff-raw.'
 
-'
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
 
-test_expect_success \
-    'prepare reference tree' \
-    'cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING &&
-     echo frotz >rezrov &&
-    git update-index --add COPYING rezrov &&
-    tree=$(git write-tree) &&
-    echo $tree'
-
-test_expect_success \
-    'prepare work tree' \
-    'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 &&
-    sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 &&
-    rm -f COPYING &&
-    git update-index --add --remove COPYING COPYING.?'
+test_expect_success 'setup reference tree' '
+       cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING &&
+       echo frotz >rezrov &&
+       git update-index --add COPYING rezrov &&
+       tree=$(git write-tree) &&
+       echo $tree &&
+       sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 &&
+       sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 &&
+       origoid=$(git hash-object COPYING) &&
+       oid1=$(git hash-object COPYING.1) &&
+       oid2=$(git hash-object COPYING.2)
+'
 
+################################################################
 # tree has COPYING and rezrov.  work tree has COPYING.1 and COPYING.2,
 # both are slightly edited, and unchanged rezrov.  We say COPYING.1
 # and COPYING.2 are based on COPYING, and do not say anything about
 # rezrov.
 
-git diff-index -C $tree >current
-
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 R1234 COPYING COPYING.2
-EOF
+test_expect_success 'validate output from rename/copy detection (#1)' '
+       rm -f COPYING &&
+       git update-index --add --remove COPYING COPYING.? &&
 
-test_expect_success \
-    'validate output from rename/copy detection (#1)' \
-    'compare_diff_raw current expected'
+       cat <<-EOF >expected &&
+       :100644 100644 $origoid $oid1 C1234     COPYING COPYING.1
+       :100644 100644 $origoid $oid2 R1234     COPYING COPYING.2
+       EOF
+       git diff-index -C $tree >current &&
+       compare_diff_raw expected current
+'
 
 ################################################################
-
-test_expect_success \
-    'prepare work tree again' \
-    'mv COPYING.2 COPYING &&
-     git update-index --add --remove COPYING COPYING.1 COPYING.2'
-
 # tree has COPYING and rezrov.  work tree has COPYING and COPYING.1,
 # both are slightly edited, and unchanged rezrov.  We say COPYING.1
 # is based on COPYING and COPYING is still there, and do not say anything
 # about rezrov.
 
-git diff-index -C $tree >current
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 M     COPYING
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1
-EOF
+test_expect_success 'validate output from rename/copy detection (#2)' '
+       mv COPYING.2 COPYING &&
+       git update-index --add --remove COPYING COPYING.1 COPYING.2 &&
 
-test_expect_success \
-    'validate output from rename/copy detection (#2)' \
-    'compare_diff_raw current expected'
+       cat <<-EOF >expected &&
+       :100644 100644 $origoid $oid2 M COPYING
+       :100644 100644 $origoid $oid1 C1234     COPYING COPYING.1
+       EOF
+       git diff-index -C $tree >current &&
+       compare_diff_raw current expected
+'
 
 ################################################################
-
 # tree has COPYING and rezrov.  work tree has the same COPYING and
 # copy-edited COPYING.1, and unchanged rezrov.  We should not say
 # anything about rezrov or COPYING, since the revised again diff-raw
 # nows how to say Copy.
 
-test_expect_success \
-    'prepare work tree once again' \
-    'cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING &&
-     git update-index --add --remove COPYING COPYING.1'
-
-git diff-index -C --find-copies-harder $tree >current
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1
-EOF
+test_expect_success 'validate output from rename/copy detection (#3)' '
+       cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING &&
+       git update-index --add --remove COPYING COPYING.1 &&
 
-test_expect_success \
-    'validate output from rename/copy detection (#3)' \
-    'compare_diff_raw current expected'
+       cat <<-EOF >expected &&
+       :100644 100644 $origoid $oid1 C1234     COPYING COPYING.1
+       EOF
+       git diff-index -C --find-copies-harder $tree >current &&
+       compare_diff_raw current expected
+'
 
 test_done
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 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 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 d83741770949f457b364896b6ff8632c0a700d69..4632c7d4c08c3127c4017c98c0983871f0236d93 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -418,6 +418,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 +602,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..d3f78ca2a718d3e4928aa90067e24d19988514c1 100644 (file)
@@ -164,9 +164,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) {