Merge branch 'es/check-non-portable-pre-5.10'
authorJunio C Hamano <gitster@pobox.com>
Sun, 19 May 2019 07:45:33 +0000 (16:45 +0900)
committerJunio C Hamano <gitster@pobox.com>
Sun, 19 May 2019 07:45:33 +0000 (16:45 +0900)
Developer support update.

* es/check-non-portable-pre-5.10:
check-non-portable-shell: support Perl versions older than 5.10

176 files changed:
Documentation/RelNotes/2.22.0.txt
Documentation/config.txt
Documentation/config/pack.txt
Documentation/config/repack.txt
Documentation/config/trace2.txt [new file with mode: 0644]
Documentation/git-branch.txt
Documentation/git-checkout.txt
Documentation/git-difftool.txt
Documentation/git-ls-files.txt
Documentation/git-mergetool--lib.txt
Documentation/git-mergetool.txt
Documentation/git.txt
Documentation/revisions.txt
Documentation/technical/api-trace2.txt
Documentation/trace2-target-values.txt [new file with mode: 0644]
GIT-VERSION-GEN
Makefile
advice.h
archive.h
bisect.h
blame.h
branch.c
branch.h
builtin.h
builtin/clone.c
builtin/commit.c
builtin/difftool.c
builtin/multi-pack-index.c
builtin/pack-objects.c
builtin/pack-refs.c
builtin/rebase--interactive.c [deleted file]
builtin/rebase.c
builtin/repack.c
builtin/show-ref.c
builtin/submodule--helper.c
builtin/tag.c
bulk-checkin.h
cache.h
checkout.h
ci/install-dependencies.sh
column.h
commit-graph.c
commit.h
common-main.c
compat/access.c [new file with mode: 0644]
compat/fileno.c
compat/mingw.c
compat/mingw.h
compat/win32/trace2_win32_process_info.c
config.c
config.h
config.mak.uname
connect.h
connected.c
connected.h
contrib/diff-highlight/DiffHighlight.pm
csum-file.h
decorate.h
delta.h
dir.h
exec-cmd.h
fmt-merge-msg.h
fsmonitor.c
fsmonitor.h
gettext.h
git-compat-util.h
git-cvsexportcommit.perl
git-difftool--helper.sh
git-mergetool--lib.sh
git-mergetool.sh
grep.h
hashmap.h
help.h
http.c
http.h
khash.h
kwset.h
line-log.h
lockfile.h
ls-refs.h
mailinfo.h
merge-blobs.h
midx.c
midx.h
notes.h
object-store.h
object.h
oidmap.h
pack.h
packfile.c
parse-options-cb.c
parse-options.c
parse-options.h
path.h
pkt-line.h
ppc/sha1.c
prio-queue.h
protocol.h
quote.h
reachable.h
read-cache.c
reflog-walk.h
refs.h
remote.h
replace-object.h
resolve-undo.h
run-command.h
sequencer.c
sequencer.h
serve.h
sha1-lookup.h
sha1-name.c
streaming.h
string-list.h
sub-process.h
submodule-config.h
t/helper/test-parse-options.c
t/helper/test-read-cache.c
t/lib-httpd/apache.conf
t/perf/README
t/perf/aggregate.perl
t/perf/p5302-pack-index.sh
t/perf/p5310-pack-bitmaps.sh
t/perf/p5311-pack-bitmaps-fetch.sh
t/perf/p5600-partial-clone.sh [new file with mode: 0755]
t/perf/perf-lib.sh
t/perf/run
t/t0040-parse-options.sh
t/t0210-trace2-normal.sh
t/t0211-trace2-perf.sh
t/t0212-trace2-event.sh
t/t2018-checkout-branch.sh
t/t3200-branch.sh
t/t3507-cherry-pick-conflict.sh
t/t4253-am-keep-cr-dos.sh
t/t5310-pack-bitmaps.sh
t/t5580-clone-push-unc.sh
t/t6500-gc.sh
t/t7004-tag.sh
t/t7512-status-help.sh
t/t7519-status-fsmonitor.sh
t/t7610-mergetool.sh
t/t7700-repack.sh
t/t7800-difftool.sh
tag.h
tempfile.h
trace.h
trace2.c
trace2.h
trace2/tr2_cfg.c
trace2/tr2_dst.c
trace2/tr2_dst.h
trace2/tr2_sid.c
trace2/tr2_sysenv.c [new file with mode: 0644]
trace2/tr2_sysenv.h [new file with mode: 0644]
trace2/tr2_tbuf.c
trace2/tr2_tbuf.h
trace2/tr2_tgt.h
trace2/tr2_tgt_event.c
trace2/tr2_tgt_normal.c
trace2/tr2_tgt_perf.c
trace2/tr2_tls.c
trace2/tr2_tls.h
transport.h
tree-walk.h
upload-pack.c
upload-pack.h
url.h
urlmatch.h
utf8.h
varint.h
vcs-svn/sliding_window.h
vcs-svn/svndiff.h
worktree.h
wt-status.c
xdiff-interface.h
index 776e15512bca45f1d4b1c2c9a4bf084ab5e7045c..114f147fd63f6a2352cc8a9a0be1afc8dbd69a67 100644 (file)
@@ -95,6 +95,10 @@ UI, Workflows & Features
  * "git clone" learned a new --server-option option when talking over
    the protocol version 2.
 
+ * The connectivity bitmaps are created by default in bare
+   repositories now; also the pathname hash-cache is created by
+   default to avoid making crappy deltas when repacking.
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -158,6 +162,22 @@ Performance, Internal Implementation, Development Support etc.
    achieve better performance by batching the request for these
    promised blobs.
 
+ * During an initial "git clone --depth=..." partial clone, it is
+   pointless to spend cycles for a large portion of the connectivity
+   check that enumerates and skips promisor objects (which by
+   definition is all objects fetched from the other side).  This has
+   been optimized out.
+
+ * Mechanically and systematically drop "extern" from function
+   declarlation.
+
+ * The script to aggregate perf result unconditionally depended on
+   libjson-perl even though it did not have to, which has been
+   corrected.
+
+ * The internal implementation of "git rebase -i" has been updated to
+   avoid forking a separate "rebase--interactive" process.
+
 
 Fixes since v2.21
 -----------------
@@ -436,6 +456,24 @@ Fixes since v2.21
    corrected.
    (merge b71e56a683 vk/autoconf-gettext later to maint).
 
+ * Fix index-pack perf test so that the repeated invocations always
+   run in an empty repository, which emulates the initial clone
+   situation better.
+   (merge 775c71e16d jk/p5302-avoid-collision-check-cost later to maint).
+
+ * A "ls-files" that emulates "find" to enumerate files in the working
+   tree resulted in duplicated Makefile rules that caused the build to
+   issue an unnecessary warning during a trial build after merge
+   conflicts are resolved in working tree *.h files but before the
+   resolved results are added to the index.  This has been corrected.
+
+ * "git chery-pick" (and "revert" that shares the same runtime engine)
+   that deals with multiple commits got confused when the final step
+   gets stopped with a conflict and the user concluded the sequence
+   with "git commit".  Attempt to fix it by cleaning up the state
+   files used by these commands in such a situation.
+   (merge 4a72486de9 pw/clean-sequencer-state-upon-final-commit later to maint).
+
  * Code cleanup, docfix, build fix, etc.
    (merge 11f470aee7 jc/test-yes-doc later to maint).
    (merge 90503a240b js/doc-symref-in-proto-v1 later to maint).
@@ -471,3 +509,4 @@ Fixes since v2.21
    (merge dbe7b41019 js/t3301-unbreak-notes-test later to maint).
    (merge d8083e4180 km/t3000-retitle later to maint).
    (merge 9e4cbccbd7 tz/git-svn-doc-markup-fix later to maint).
+   (merge da9ca955a7 jk/ls-files-doc-markup-fix later to maint).
index d87846faa6c3ffad7cba97fe7348ef97e0112899..7e2a6f61f593921450c311b05269a3555baa97ad 100644 (file)
@@ -422,6 +422,8 @@ include::config/submodule.txt[]
 
 include::config/tag.txt[]
 
+include::config/trace2.txt[]
+
 include::config/transfer.txt[]
 
 include::config/uploadarchive.txt[]
index 425c73aa521a67f87941bd8fc11c69b52432cb00..9cdcfa7324784299f431d94b5237cc136aa585d1 100644 (file)
@@ -124,6 +124,4 @@ pack.writeBitmapHashCache::
        bitmapped and non-bitmapped objects (e.g., when serving a fetch
        between an older, bitmapped pack and objects that have been
        pushed since the last gc). The downside is that it consumes 4
-       bytes per object of disk space, and that JGit's bitmap
-       implementation does not understand it, causing it to complain if
-       Git and JGit are used on the same repository. Defaults to false.
+       bytes per object of disk space. Defaults to true.
index a5c37813fdad63791d2be8b09bc2ef128fd4a37e..9c413e177e02c6f28865ed79d84de3c5ccf43dd9 100644 (file)
@@ -24,4 +24,4 @@ repack.writeBitmaps::
        packs created for clones and fetches, at the cost of some disk
        space and extra time spent on the initial repack.  This has
        no effect if multiple packfiles are created.
-       Defaults to false.
+       Defaults to true on bare repos, false otherwise.
diff --git a/Documentation/config/trace2.txt b/Documentation/config/trace2.txt
new file mode 100644 (file)
index 0000000..a5f409c
--- /dev/null
@@ -0,0 +1,56 @@
+Trace2 config settings are only read from the system and global
+config files; repository local and worktree config files and `-c`
+command line arguments are not respected.
+
+trace2.normalTarget::
+       This variable controls the normal target destination.
+       It may be overridden by the `GIT_TR2` environment variable.
+       The following table shows possible values.
+
+trace2.perfTarget::
+       This variable controls the performance target destination.
+       It may be overridden by the `GIT_TR2_PERF` environment variable.
+       The following table shows possible values.
+
+trace2.eventTarget::
+       This variable controls the event target destination.
+       It may be overridden by the `GIT_TR2_EVENT` environment variable.
+       The following table shows possible values.
++
+include::../trace2-target-values.txt[]
+
+trace2.normalBrief::
+       Boolean.  When true `time`, `filename`, and `line` fields are
+       omitted from normal output.  May be overridden by the
+       `GIT_TR2_BRIEF` environment variable.  Defaults to false.
+
+trace2.perfBrief::
+       Boolean.  When true `time`, `filename`, and `line` fields are
+       omitted from PERF output.  May be overridden by the
+       `GIT_TR2_PERF_BRIEF` environment variable.  Defaults to false.
+
+trace2.eventBrief::
+       Boolean.  When true `time`, `filename`, and `line` fields are
+       omitted from event output.  May be overridden by the
+       `GIT_TR2_EVENT_BRIEF` environment variable.  Defaults to false.
+
+trace2.eventNesting::
+       Integer.  Specifies desired depth of nested regions in the
+       event output.  Regions deeper than this value will be
+       omitted.  May be overridden by the `GIT_TR2_EVENT_NESTING`
+       environment variable.  Defaults to 2.
+
+trace2.configParams::
+       A comma-separated list of patterns of "important" config
+       settings that should be recorded in the trace2 output.
+       For example, `core.*,remote.*.url` would cause the trace2
+       output to contain events listing each configured remote.
+       May be overridden by the `GIT_TR2_CONFIG_PARAMS` environment
+       variable.  Unset by default.
+
+trace2.destinationDebug::
+       Boolean.  When true Git will print error messages when a
+       trace target destination cannot be opened for writing.
+       By default, these errors are suppressed and tracing is
+       silently disabled.  May be overridden by the
+       `GIT_TR2_DST_DEBUG` environment variable.
index 0cd87ddeff205ac6b5a92260f690e642f16d0875..6ebd512b4f3344c2f166f5bb09f0b5c6eb96ab03 100644 (file)
@@ -45,7 +45,11 @@ argument is missing it defaults to `HEAD` (i.e. the tip of the current
 branch).
 
 The command's second form creates a new branch head named <branchname>
-which points to the current `HEAD`, or <start-point> if given.
+which points to the current `HEAD`, or <start-point> if given. As a
+special case, for <start-point>, you may use `"A...B"` as a shortcut for
+the merge base of `A` and `B` if there is exactly one merge base. You
+can leave out at most one of `A` and `B`, in which case it defaults to
+`HEAD`.
 
 Note that this will create the new branch, but it will not switch the
 working tree to it; use "git checkout <newbranch>" to switch to the
index 877e5f503a66145912886c14917f0e68512e6284..964f912d29ee92d55a3c98d40cc41941e7db743a 100644 (file)
@@ -313,6 +313,10 @@ leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.
 <start_point>::
        The name of a commit at which to start the new branch; see
        linkgit:git-branch[1] for details. Defaults to HEAD.
++
+As a special case, you may use `"A...B"` as a shortcut for the
+merge base of `A` and `B` if there is exactly one merge base. You can
+leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.
 
 <tree-ish>::
        Tree to checkout from (when paths are given). If not specified,
index 96c26e6aa82c98da1652023f0d04b4b63c8a4944..484c485fd06c9d52e09b5e7324f5f13fd444e4f9 100644 (file)
@@ -90,7 +90,9 @@ instead.  `--no-symlinks` is the default on Windows.
        When 'git-difftool' is invoked with the `-g` or `--gui` option
        the default diff tool will be read from the configured
        `diff.guitool` variable instead of `diff.tool`. The `--no-gui`
-       option can be used to override this setting.
+       option can be used to override this setting. If `diff.guitool`
+       is not set, we will fallback in the order of `merge.guitool`,
+       `diff.tool`, `merge.tool` until a tool is found.
 
 --[no-]trust-exit-code::
        'git-difftool' invokes a diff tool individually on each file.
index 5298f1bc3052f47e390eee780efe665083744309..8461c0e83e9d535b25755be1d5045cdc30145cb4 100644 (file)
@@ -118,6 +118,7 @@ OPTIONS
        linkgit:git-status[1] `--short` or linkgit:git-diff[1]
        `--name-status` for more user-friendly alternatives.
 +
+--
 This option identifies the file status with the following tags (followed by
 a space) at the start of each line:
 
@@ -128,6 +129,7 @@ a space) at the start of each line:
        C::     modified/changed
        K::     to be killed
        ?::     other
+--
 
 -v::
        Similar to `-t`, but use lowercase letters for files
index 055550b2bcc805780396b83b162a328230c0a1c6..4da9d240962f24da7daa7ebde7b4f0db4634cdd8 100644 (file)
@@ -28,7 +28,9 @@ to define the operation mode for the functions listed below.
 FUNCTIONS
 ---------
 get_merge_tool::
-       returns a merge tool.
+       returns a merge tool. the return code is 1 if we returned a guessed
+       merge tool, else 0. '$GIT_MERGETOOL_GUI' may be set to 'true' to
+       search for the appropriate guitool.
 
 get_merge_tool_cmd::
        returns the custom command for a merge tool.
index 0c7975a0507a35f9624516f0844ad11cd5141d50..6b14702e78498ee45f67e0084bea429d484b28cf 100644 (file)
@@ -83,7 +83,9 @@ success of the resolution after the custom tool has exited.
 --gui::
        When 'git-mergetool' is invoked with the `-g` or `--gui` option
        the default merge tool will be read from the configured
-       `merge.guitool` variable instead of `merge.tool`.
+       `merge.guitool` variable instead of `merge.tool`. If
+       `merge.guitool` is not set, we will fallback to the tool
+       configured under `merge.tool`.
 
 --no-gui::
        This overrides a previous `-g` or `--gui` setting and reads the
index 6d1f2fd9ae9e993e46d935f835bdfec4e6f686e1..72adfcc5e24b783f6924655088a968a5357b188e 100644 (file)
@@ -660,6 +660,27 @@ of clones and fetches.
        When a curl trace is enabled (see `GIT_TRACE_CURL` above), do not dump
        data (that is, only dump info lines and headers).
 
+`GIT_TR2`::
+       Enables more detailed trace messages from the "trace2" library.
+       Output from `GIT_TR2` is a simple text-based format for human
+       readability.
++
+The `GIT_TR2` variables can take many values. Any value available to
+the `GIT_TRACE` variables is also available to `GIT_TR2`. The `GIT_TR2`
+variables can also specify a Unix Domain Socket. See
+link:technical/api-trace2.html[Trace2 documentation] for full details.
+
+`GIT_TR2_EVENT`::
+       This setting writes a JSON-based format that is suited for machine
+       interpretation. See link:technical/api-trace2.html[Trace2 documentation]
+       for full details.
+
+`GIT_TR2_PERF`::
+       In addition to the text-based messages available in `GIT_TR2`, this
+       setting writes a column-based format for understanding nesting
+       regions. See link:technical/api-trace2.html[Trace2 documentation]
+       for full details.
+
 `GIT_REDACT_COOKIES`::
        This can be set to a comma-separated list of strings. When a curl trace
        is enabled (see `GIT_TRACE_CURL` above), whenever a "Cookies:" header
index 2337a995eccace3af47e98ed006a2ccbd44a4f4e..82c1e5754e775039f4e858fde64619f8a70e7af5 100644 (file)
@@ -65,7 +65,7 @@ some output processing may assume ref names in UTF-8.
 '@'::
   '@' alone is a shortcut for `HEAD`.
 
-'<refname>@{<date>}', e.g. 'master@\{yesterday\}', 'HEAD@{5 minutes ago}'::
+'[<refname>]@{<date>}', e.g. 'master@\{yesterday\}', 'HEAD@{5 minutes ago}'::
   A ref followed by the suffix '@' with a date specification
   enclosed in a brace
   pair (e.g. '\{yesterday\}', '{1 month 2 weeks 3 days 1 hour 1
@@ -95,7 +95,7 @@ some output processing may assume ref names in UTF-8.
   The construct '@{-<n>}' means the <n>th branch/commit checked out
   before the current one.
 
-'<branchname>@\{upstream\}', e.g. 'master@\{upstream\}', '@\{u\}'::
+'[<branchname>]@\{upstream\}', e.g. 'master@\{upstream\}', '@\{u\}'::
   The suffix '@\{upstream\}' to a branchname (short form '<branchname>@\{u\}')
   refers to the branch that the branch specified by branchname is set to build on
   top of (configured with `branch.<name>.remote` and
@@ -103,7 +103,7 @@ some output processing may assume ref names in UTF-8.
   current one. These suffixes are also accepted when spelled in uppercase, and
   they mean the same thing no matter the case.
 
-'<branchname>@\{push\}', e.g. 'master@\{push\}', '@\{push\}'::
+'[<branchname>]@\{push\}', e.g. 'master@\{push\}', '@\{push\}'::
   The suffix '@\{push}' reports the branch "where we would push to" if
   `git push` were run while `branchname` was checked out (or the current
   `HEAD` if no branchname is specified). Since our push destination is
@@ -131,7 +131,7 @@ from one location and push to another. In a non-triangular workflow,
 This suffix is also accepted when spelled in uppercase, and means the same
 thing no matter the case.
 
-'<rev>{caret}', e.g. 'HEAD{caret}, v1.5.1{caret}0'::
+'<rev>{caret}[<n>]', e.g. 'HEAD{caret}, v1.5.1{caret}0'::
   A suffix '{caret}' to a revision parameter means the first parent of
   that commit object.  '{caret}<n>' means the <n>th parent (i.e.
   '<rev>{caret}'
@@ -139,7 +139,9 @@ thing no matter the case.
   '<rev>{caret}0' means the commit itself and is used when '<rev>' is the
   object name of a tag object that refers to a commit object.
 
-'<rev>{tilde}<n>', e.g. 'master{tilde}3'::
+'<rev>{tilde}[<n>]', e.g. 'HEAD{tilde}, master{tilde}3'::
+  A suffix '{tilde}' to a revision parameter means the first parent of
+  that commit object.
   A suffix '{tilde}<n>' to a revision parameter means the commit
   object that is the <n>th generation ancestor of the named
   commit object, following only the first parents.  I.e. '<rev>{tilde}3' is
@@ -159,12 +161,12 @@ thing no matter the case.
   '<rev>{caret}0'
   is a short-hand for '<rev>{caret}\{commit\}'.
 +
-'rev{caret}\{object\}' can be used to make sure 'rev' names an
-object that exists, without requiring 'rev' to be a tag, and
-without dereferencing 'rev'; because a tag is already an object,
+'<rev>{caret}\{object\}' can be used to make sure '<rev>' names an
+object that exists, without requiring '<rev>' to be a tag, and
+without dereferencing '<rev>'; because a tag is already an object,
 it does not have to be dereferenced even once to get to an object.
 +
-'rev{caret}\{tag\}' can be used to ensure that 'rev' identifies an
+'<rev>{caret}\{tag\}' can be used to ensure that '<rev>' identifies an
 existing tag object.
 
 '<rev>{caret}{}', e.g. 'v0.99.8{caret}{}'::
@@ -194,19 +196,16 @@ existing tag object.
   Depending on the given text, the shell's word splitting rules might
   require additional quoting.
 
-'<rev>:<path>', e.g. 'HEAD:README', ':README', 'master:./README'::
+'<rev>:<path>', e.g. 'HEAD:README', 'master:./README'::
   A suffix ':' followed by a path names the blob or tree
   at the given path in the tree-ish object named by the part
   before the colon.
-  ':path' (with an empty part before the colon)
-  is a special case of the syntax described next: content
-  recorded in the index at the given path.
   A path starting with './' or '../' is relative to the current working directory.
   The given path will be converted to be relative to the working tree's root directory.
   This is most useful to address a blob or tree from a commit or tree that has
   the same tree structure as the working tree.
 
-':<n>:<path>', e.g. ':0:README', ':README'::
+':[<n>:]<path>', e.g. ':0:README', ':README'::
   A colon, optionally followed by a stage number (0 to 3) and a
   colon, followed by a path, names a blob object in the
   index at the given path. A missing stage number (and the colon
@@ -302,7 +301,7 @@ The 'r1{caret}@' notation means all parents of 'r1'.
 The 'r1{caret}!' notation includes commit 'r1' but excludes all of its parents.
 By itself, this notation denotes the single commit 'r1'.
 
-The '<rev>{caret}-<n>' notation includes '<rev>' but excludes the <n>th
+The '<rev>{caret}-[<n>]' notation includes '<rev>' but excludes the <n>th
 parent (i.e. a shorthand for '<rev>{caret}<n>..<rev>'), with '<n>' = 1 if
 not given. This is typically useful for merge commits where you
 can just pass '<commit>{caret}-' to get all the commits in the branch
index d0948ba250933ed7e5c3f06bdf70cb7a1e6e5814..9e585b8e79fbc70434fb9964159d9ee18757f82c 100644 (file)
@@ -22,21 +22,41 @@ Targets are defined using a VTable allowing easy extension to other
 formats in the future.  This might be used to define a binary format,
 for example.
 
+Trace2 is controlled using `trace2.*` config values in the system and
+global config files and `GIT_TR2*` environment variables.  Trace2 does
+not read from repo local or worktree config files or respect `-c`
+command line config settings.
+
 == Trace2 Targets
 
 Trace2 defines the following set of Trace2 Targets.
 Format details are given in a later section.
 
-`GIT_TR2` (NORMAL)::
+=== The Normal Format Target
+
+The normal format target is a tradition printf format and similar
+to GIT_TRACE format.  This format is enabled with the `GIT_TR`
+environment variable or the `trace2.normalTarget` system or global
+config setting.
+
+For example
 
-       a simple printf format like GIT_TRACE.
-+
 ------------
 $ export GIT_TR2=~/log.normal
 $ git version
 git version 2.20.1.155.g426c96fcdb
 ------------
-+
+
+or
+
+------------
+$ git config --global trace2.normalTarget ~/log.normal
+$ git version
+git version 2.20.1.155.g426c96fcdb
+------------
+
+yields
+
 ------------
 $ cat ~/log.normal
 12:28:42.620009 common-main.c:38                  version 2.20.1.155.g426c96fcdb
@@ -46,81 +66,86 @@ $ cat ~/log.normal
 12:28:42.621250 trace2/tr2_tgt_normal.c:124       atexit elapsed:0.001265 code:0
 ------------
 
-`GIT_TR2_PERF` (PERF)::
+=== The Performance Format Target
+
+The performance format target (PERF) is a column-based format to
+replace GIT_TRACE_PERFORMANCE and is suitable for development and
+testing, possibly to complement tools like gprof.  This format is
+enabled with the `GIT_TR2_PERF` environment variable or the
+`trace2.perfTarget` system or global config setting.
+
+For example
 
-       a column-based format to replace GIT_TRACE_PERFORMANCE suitable for
-       development and testing, possibly to complement tools like gprof.
-+
 ------------
 $ export GIT_TR2_PERF=~/log.perf
 $ git version
 git version 2.20.1.155.g426c96fcdb
 ------------
-+
+
+or
+
+------------
+$ git config --global trace2.perfTarget ~/log.perf
+$ git version
+git version 2.20.1.155.g426c96fcdb
+------------
+
+yields
+
 ------------
 $ cat ~/log.perf
 12:28:42.620675 common-main.c:38                  | d0 | main                     | version      |     |           |           |            | 2.20.1.155.g426c96fcdb
-12:28:42.621001 common-main.c:39                  | d0 | main                     | start        |     |           |           |            | git version
+12:28:42.621001 common-main.c:39                  | d0 | main                     | start        |     |  0.001173 |           |            | git version
 12:28:42.621111 git.c:432                         | d0 | main                     | cmd_name     |     |           |           |            | version (version)
 12:28:42.621225 git.c:662                         | d0 | main                     | exit         |     |  0.001227 |           |            | code:0
 12:28:42.621259 trace2/tr2_tgt_perf.c:211         | d0 | main                     | atexit       |     |  0.001265 |           |            | code:0
 ------------
 
-`GIT_TR2_EVENT` (EVENT)::
+=== The Event Format Target
+
+The event format target is a JSON-based format of event data suitable
+for telemetry analysis.  This format is enabled with the `GIT_TR2_EVENT`
+environment variable or the `trace2.eventTarget` system or global config
+setting.
+
+For example
 
-       a JSON-based format of event data suitable for telemetry analysis.
-+
 ------------
 $ export GIT_TR2_EVENT=~/log.event
 $ git version
 git version 2.20.1.155.g426c96fcdb
 ------------
-+
-------------
-$ cat ~/log.event
-{"event":"version","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.620713","file":"common-main.c","line":38,"evt":"1","exe":"2.20.1.155.g426c96fcdb"}
-{"event":"start","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621027","file":"common-main.c","line":39,"argv":["git","version"]}
-{"event":"cmd_name","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621122","file":"git.c","line":432,"name":"version","hierarchy":"version"}
-{"event":"exit","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621236","file":"git.c","line":662,"t_abs":0.001227,"code":0}
-{"event":"atexit","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621268","file":"trace2/tr2_tgt_event.c","line":163,"t_abs":0.001265,"code":0}
-------------
-
-== Enabling a Target
 
-A Trace2 Target is enabled when the corresponding environment variable
-(`GIT_TR2`, `GIT_TR2_PERF`, or `GIT_TR2_EVENT`) is set.  The following
-values are recognized.
+or
 
-`0`::
-`false`::
-
-       Disables the target.
-
-`1`::
-`true`::
-
-       Enables the target and writes stream to `STDERR`.
-
-`[2-9]`::
+------------
+$ git config --global trace2.eventTarget ~/log.event
+$ git version
+git version 2.20.1.155.g426c96fcdb
+------------
 
-       Enables the target and writes to the already opened file descriptor.
+yields
 
-`<absolute-pathname>`::
+------------
+$ cat ~/log.event
+{"event":"version","sid":"sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.620713Z","file":"common-main.c","line":38,"evt":"1","exe":"2.20.1.155.g426c96fcdb"}
+{"event":"start","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621027Z","file":"common-main.c","line":39,"t_abs":0.001173,"argv":["git","version"]}
+{"event":"cmd_name","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621122Z","file":"git.c","line":432,"name":"version","hierarchy":"version"}
+{"event":"exit","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621236Z","file":"git.c","line":662,"t_abs":0.001227,"code":0}
+{"event":"atexit","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621268Z","file":"trace2/tr2_tgt_event.c","line":163,"t_abs":0.001265,"code":0}
+------------
 
-       Enables the target, opens and writes to the file in append mode.
+=== Enabling a Target
 
-       If the target already exists and is a directory, the traces will be
-       written to files (one per process) underneath the given directory. They
-       will be named according to the last component of the SID (optionally
-       followed by a counter to avoid filename collisions).
+To enable a target, set the corresponding environment variable or
+system or global config value to one of the following:
 
-`af_unix:[<socket_type>:]<absolute-pathname>`::
+include::../trace2-target-values.txt[]
 
-       Enables the target, opens and writes to a Unix Domain Socket
-       (on platforms that support them).
-+
-Socket type can be either `stream` or `dgram`.  If the socket type is
-omitted, Git will try both.
+If the target already exists and is a directory, the traces will be
+written to files (one per process) underneath the given directory. They
+will be named according to the last component of the SID (optionally
+followed by a counter to avoid filename collisions).
 
 == Trace2 API
 
@@ -165,17 +190,23 @@ purposes.
 
 These are concerned with the lifetime of the overall git process.
 
+`void trace2_initialize_clock()`::
+
+       Initialize the Trace2 start clock and nothing else.  This should
+       be called at the very top of main() to capture the process start
+       time and reduce startup order dependencies.
+
 `void trace2_initialize()`::
 
        Determines if any Trace2 Targets should be enabled and
-       initializes the Trace2 facility.  This includes starting the
-       elapsed time clocks and thread local storage (TLS).
+       initializes the Trace2 facility.  This includes setting up the
+       Trace2 thread local storage (TLS).
 +
 This function emits a "version" message containing the version of git
 and the Trace2 protocol.
 +
 This function should be called from `main()` as early as possible in
-the life of the process.
+the life of the process after essential process initialization.
 
 `int trace2_is_enabled()`::
 
@@ -242,15 +273,16 @@ significantly affects program performance or behavior, such as
        Emits a "def_param" messages for "important" configuration
        settings.
 +
-The environment variable `GIT_TR2_CONFIG_PARAMS` can be set to a
+The environment variable `GIT_TR2_CONFIG_PARAMS` or the `trace2.configParams`
+config value can be set to a
 list of patterns of important configuration settings, for example:
 `core.*,remote.*.url`.  This function will iterate over all config
 settings and emit a "def_param" message for each match.
 
 `void trace2_cmd_set_config(const char *key, const char *value)`::
 
-       Emits a "def_param" message for a specific configuration
-       setting IFF it matches the `GIT_TR2_CONFIG_PARAMS` pattern.
+       Emits a "def_param" message for a new or updated key/value
+       pair IF `key` is considered important.
 +
 This is used to hook into `git_config_set()` and catch any
 configuration changes and update a value previously reported by
@@ -417,9 +449,6 @@ recursive tree walk.
 
 === NORMAL Format
 
-NORMAL format is enabled when the `GIT_TR2` environment variable is
-set.
-
 Events are written as lines of the form:
 
 ------------
@@ -436,8 +465,8 @@ Events are written as lines of the form:
 Note that this may contain embedded LF or CRLF characters that are
 not escaped, so the event may spill across multiple lines.
 
-If `GIT_TR2_BRIEF` is true, the `time`, `filename`, and `line` fields
-are omitted.
+If `GIT_TR2_BRIEF` or `trace2.normalBrief` is true, the `time`, `filename`,
+and `line` fields are omitted.
 
 This target is intended to be more of a summary (like GIT_TRACE) and
 less detailed than the other targets.  It ignores thread, region, and
@@ -445,9 +474,6 @@ data messages, for example.
 
 === PERF Format
 
-PERF format is enabled when the `GIT_TR2_PERF` environment variable
-is set.
-
 Events are written as lines of the form:
 
 ------------
@@ -507,8 +533,8 @@ This field is in anticipation of in-proc submodules in the future.
 15:33:33.532712 wt-status.c:2331                  | d0 | main                     | region_leave | r1  |  0.127568 |  0.001504 | status     | label:print
 ------------
 
-If `GIT_TR2_PERF_BRIEF` is true, the `time`, `file`, and `line`
-fields are omitted.
+If `GIT_TR2_PERF_BRIEF` or `trace2.perfBrief` is true, the `time`, `file`,
+and `line` fields are omitted.
 
 ------------
 d0 | main                     | region_leave | r1  |  0.011717 |  0.009122 | index      | label:preload
@@ -519,9 +545,6 @@ during development and is quite noisy.
 
 === EVENT Format
 
-EVENT format is enabled when the `GIT_TR2_EVENT` environment
-variable is set.
-
 Each event is a JSON-object containing multiple key/value pairs
 written as a single line and followed by a LF.
 
@@ -539,11 +562,11 @@ The following key/value pairs are common to all events:
 ------------
 {
        "event":"version",
-       "sid":"1547659722619736-11614",
+       "sid":"20190408T191827.272759Z-H9b68c35f-P00003510",
        "thread":"main",
-       "time":"2019-01-16 17:28:42.620713",
+       "time":"2019-04-08T19:18:27.282761Z",
        "file":"common-main.c",
-       "line":38,
+       "line":42,
        ...
 }
 ------------
@@ -575,9 +598,9 @@ The following key/value pairs are common to all events:
 `"repo":<repo-id>`::
        when present, is the integer repo-id as described previously.
 
-If `GIT_TR2_EVENT_BRIEF` is true, the `file` and `line` fields are omitted
-from all events and the `time` field is only present on the "start" and
-"atexit" events.
+If `GIT_TR2_EVENT_BRIEF` or `trace2.eventBrief` is true, the `file`
+and `line` fields are omitted from all events and the `time` field is
+only present on the "start" and "atexit" events.
 
 ==== Event-Specific Key/Value Pairs
 
@@ -600,6 +623,7 @@ from all events and the `time` field is only present on the "start" and
 {
        "event":"start",
        ...
+       "t_abs":0.001227, # elapsed time in seconds
        "argv":["git","version"]
 }
 ------------
@@ -887,7 +911,7 @@ visited.
 The `category` field may be used in a future enhancement to
 do category-based filtering.
 +
-The `GIT_TR2_EVENT_NESTING` environment variable can be used to
+`GIT_TR2_EVENT_NESTING` or `trace2.eventNesting` can be used to
 filter deeply nested regions and data events.  It defaults to "2".
 
 `"region_leave"`::
@@ -1117,7 +1141,7 @@ $ git status
 
 $ cat ~/log.perf
 d0 | main                     | version      |     |           |           |            | 2.20.1.160.g5676107ecd.dirty
-d0 | main                     | start        |     |           |           |            | git status
+d0 | main                     | start        |     |  0.001173 |           |            | git status
 d0 | main                     | def_repo     | r1  |           |           |            | worktree:/Users/jeffhost/work/gfw
 d0 | main                     | cmd_name     |     |           |           |            | status (status)
 ...
@@ -1162,7 +1186,7 @@ $ git status
 ...
 $ cat ~/log.perf
 d0 | main                     | version      |     |           |           |            | 2.20.1.162.gb4ccea44db.dirty
-d0 | main                     | start        |     |           |           |            | git status
+d0 | main                     | start        |     |  0.001173 |           |            | git status
 d0 | main                     | def_repo     | r1  |           |           |            | worktree:/Users/jeffhost/work/gfw
 d0 | main                     | cmd_name     |     |           |           |            | status (status)
 ...
@@ -1218,7 +1242,7 @@ $ git status
 ...
 $ cat ~/log.perf
 d0 | main                     | version      |     |           |           |            | 2.20.1.156.gf9916ae094.dirty
-d0 | main                     | start        |     |           |           |            | git status
+d0 | main                     | start        |     |  0.001173 |           |            | git status
 d0 | main                     | def_repo     | r1  |           |           |            | worktree:/Users/jeffhost/work/gfw
 d0 | main                     | cmd_name     |     |           |           |            | status (status)
 d0 | main                     | region_enter | r1  |  0.001791 |           | index      | label:do_read_index .git/index
diff --git a/Documentation/trace2-target-values.txt b/Documentation/trace2-target-values.txt
new file mode 100644 (file)
index 0000000..27d3c64
--- /dev/null
@@ -0,0 +1,10 @@
+--
+* `0` or `false` - Disables the target.
+* `1` or `true` - Writes to `STDERR`.
+* `[2-9]` - Writes to the already opened file descriptor.
+* `<absolute-pathname>` - Writes to the file in append mode.
+* `af_unix:[<socket_type>:]<absolute-pathname>` - Write to a
+Unix DomainSocket (on platforms that support them).  Socket
+type can be either `stream` or `dgram`; if omitted Git will
+try both.
+--
index 3fc4065da2ecdb7176766f1c5f5b9243cf4ab718..8a5009caf98c9ce87e794b89f398c64e61d2bb98 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.21.GIT
+DEF_VER=v2.22.0-rc0
 
 LF='
 '
index 5143cab9bdb2b303386074877838da3741ecc76d..8a7e2353520ddd7e0c8074d2b32d0441d97c1597 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -439,6 +439,9 @@ all::
 #
 # Define FILENO_IS_A_MACRO if fileno() is a macro, not a real function.
 #
+# Define NEED_ACCESS_ROOT_HANDLER if access() under root may success for X_OK
+# even if execution permission isn't granted for any user.
+#
 # Define PAGER_ENV to a SP separated VAR=VAL pairs to define
 # default environment variables to be passed when a pager is spawned, e.g.
 #
@@ -817,12 +820,12 @@ VCSSVN_LIB = vcs-svn/lib.a
 
 GENERATED_H += command-list.h
 
-LIB_H := $(shell git ls-files '*.h' ':!t/' ':!Documentation/' 2>/dev/null || \
+LIB_H := $(sort $(shell git ls-files '*.h' ':!t/' ':!Documentation/' 2>/dev/null || \
        $(FIND) . \
        -name .git -prune -o \
        -name t -prune -o \
        -name Documentation -prune -o \
-       -name '*.h' -print)
+       -name '*.h' -print))
 
 LIB_OBJS += abspath.o
 LIB_OBJS += advice.o
@@ -999,6 +1002,7 @@ LIB_OBJS += trace2/tr2_cfg.o
 LIB_OBJS += trace2/tr2_cmd_name.o
 LIB_OBJS += trace2/tr2_dst.o
 LIB_OBJS += trace2/tr2_sid.o
+LIB_OBJS += trace2/tr2_sysenv.o
 LIB_OBJS += trace2/tr2_tbuf.o
 LIB_OBJS += trace2/tr2_tgt_event.o
 LIB_OBJS += trace2/tr2_tgt_normal.o
@@ -1105,7 +1109,6 @@ BUILTIN_OBJS += builtin/push.o
 BUILTIN_OBJS += builtin/range-diff.o
 BUILTIN_OBJS += builtin/read-tree.o
 BUILTIN_OBJS += builtin/rebase.o
-BUILTIN_OBJS += builtin/rebase--interactive.o
 BUILTIN_OBJS += builtin/receive-pack.o
 BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
@@ -1168,8 +1171,11 @@ PTHREAD_CFLAGS =
 SPARSE_FLAGS ?=
 SP_EXTRA_FLAGS =
 
-# For the 'coccicheck' target
+# For the 'coccicheck' target; setting SPATCH_BATCH_SIZE higher will
+# usually result in less CPU usage at the cost of higher peak memory.
+# Setting it to 0 will feed all files in a single spatch invocation.
 SPATCH_FLAGS = --all-includes --patch .
+SPATCH_BATCH_SIZE = 1
 
 include config.mak.uname
 -include config.mak.autogen
@@ -1833,6 +1839,11 @@ ifdef FILENO_IS_A_MACRO
        COMPAT_OBJS += compat/fileno.o
 endif
 
+ifdef NEED_ACCESS_ROOT_HANDLER
+       COMPAT_CFLAGS += -DNEED_ACCESS_ROOT_HANDLER
+       COMPAT_OBJS += compat/access.o
+endif
+
 ifeq ($(TCLTK_PATH),)
 NO_TCLTK = NoThanks
 endif
@@ -2799,12 +2810,14 @@ endif
 
 %.cocci.patch: %.cocci $(COCCI_SOURCES)
        @echo '    ' SPATCH $<; \
-       ret=0; \
-       for f in $(COCCI_SOURCES); do \
-               $(SPATCH) --sp-file $< $$f $(SPATCH_FLAGS) || \
-                       { ret=$$?; break; }; \
-       done >$@+ 2>$@.log; \
-       if test $$ret != 0; \
+       if test $(SPATCH_BATCH_SIZE) = 0; then \
+               limit=; \
+       else \
+               limit='-n $(SPATCH_BATCH_SIZE)'; \
+       fi; \
+       if ! echo $(COCCI_SOURCES) | xargs $$limit \
+               $(SPATCH) --sp-file $< $(SPATCH_FLAGS) \
+               >$@+ 2>$@.log; \
        then \
                cat $@.log; \
                exit 1; \
index cb5d36161453dc4c3a8de8e6afd3b3ac28394eaa..e50f02cdfeff788910699f2d34fff1c93081c24b 100644 (file)
--- a/advice.h
+++ b/advice.h
@@ -32,7 +32,7 @@ int git_default_advice_config(const char *var, const char *value);
 __attribute__((format (printf, 1, 2)))
 void advise(const char *advice, ...);
 int error_resolve_conflict(const char *me);
-extern void NORETURN die_resolve_conflict(const char *me);
+void NORETURN die_resolve_conflict(const char *me);
 void NORETURN die_conclude_merge(void);
 void detach_advice(const char *new_name);
 
index dd022a6b46bc339d19b1c49ebc20214dd137685f..e60e3dd31c79f1c04b7afcae8eb5623238e1234f 100644 (file)
--- a/archive.h
+++ b/archive.h
@@ -23,9 +23,9 @@ struct archiver_args {
 
 /* main api */
 
-extern int write_archive(int argc, const char **argv, const char *prefix,
-                        struct repository *repo,
-                        const char *name_hint, int remote);
+int write_archive(int argc, const char **argv, const char *prefix,
+                 struct repository *repo,
+                 const char *name_hint, int remote);
 
 const char *archive_format_from_filename(const char *filename);
 
@@ -39,21 +39,21 @@ struct archiver {
        unsigned flags;
        void *data;
 };
-extern void register_archiver(struct archiver *);
+void register_archiver(struct archiver *);
 
-extern void init_tar_archiver(void);
-extern void init_zip_archiver(void);
-extern void init_archivers(void);
+void init_tar_archiver(void);
+void init_zip_archiver(void);
+void init_archivers(void);
 
 typedef int (*write_archive_entry_fn_t)(struct archiver_args *args,
                                        const struct object_id *oid,
                                        const char *path, size_t pathlen,
                                        unsigned int mode);
 
-extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
-extern void *object_file_to_archive(const struct archiver_args *args,
-                                   const char *path, const struct object_id *oid,
-                                   unsigned int mode, enum object_type *type,
-                                   unsigned long *sizep);
+int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
+void *object_file_to_archive(const struct archiver_args *args,
+                            const char *path, const struct object_id *oid,
+                            unsigned int mode, enum object_type *type,
+                            unsigned long *sizep);
 
 #endif /* ARCHIVE_H */
index 821d16e4ddad71d177190a0e05012c5a509fa17b..4e69a11ea8f3c60fe0c273fc4af98760fd236f09 100644 (file)
--- a/bisect.h
+++ b/bisect.h
@@ -11,14 +11,14 @@ struct repository;
  * Otherwise, it will be either all non-SAMETREE commits or the single
  * best commit, as chosen by `find_all`.
  */
-extern void find_bisection(struct commit_list **list, int *reaches, int *all,
-                          int find_all);
+void find_bisection(struct commit_list **list, int *reaches, int *all,
+                   int find_all);
 
-extern struct commit_list *filter_skipped(struct commit_list *list,
-                                         struct commit_list **tried,
-                                         int show_all,
-                                         int *count,
-                                         int *skipped_first);
+struct commit_list *filter_skipped(struct commit_list *list,
+                                  struct commit_list **tried,
+                                  int show_all,
+                                  int *count,
+                                  int *skipped_first);
 
 #define BISECT_SHOW_ALL                (1<<0)
 #define REV_LIST_QUIET         (1<<1)
@@ -31,14 +31,14 @@ struct rev_list_info {
        const char *header_prefix;
 };
 
-extern int bisect_next_all(struct repository *r,
-                          const char *prefix,
-                          int no_checkout);
+int bisect_next_all(struct repository *r,
+                   const char *prefix,
+                   int no_checkout);
 
-extern int estimate_bisect_steps(int all);
+int estimate_bisect_steps(int all);
 
-extern void read_bisect_terms(const char **bad, const char **good);
+void read_bisect_terms(const char **bad, const char **good);
 
-extern int bisect_clean_state(void);
+int bisect_clean_state(void);
 
 #endif
diff --git a/blame.h b/blame.h
index 2a285eb027bf1a82b3b1b53f2bc04caebef86924..d62f80fa74c44011f8cdaea7a4baec3d8cae03e6 100644 (file)
--- a/blame.h
+++ b/blame.h
@@ -177,6 +177,6 @@ struct blame_entry *blame_entry_prepend(struct blame_entry *head,
                                        long start, long end,
                                        struct blame_origin *o);
 
-extern struct blame_origin *get_blame_suspects(struct commit *commit);
+struct blame_origin *get_blame_suspects(struct commit *commit);
 
 #endif /* BLAME_H */
index 28b81a7e0256b2923c0fe296d9618d130821cdc4..a594cc23e25458250885244f477a5d4879df2537 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -5,6 +5,7 @@
 #include "refs.h"
 #include "refspec.h"
 #include "remote.h"
+#include "sequencer.h"
 #include "commit.h"
 #include "worktree.h"
 
@@ -268,7 +269,7 @@ void create_branch(struct repository *r,
        }
 
        real_ref = NULL;
-       if (get_oid(start_name, &oid)) {
+       if (get_oid_mb(start_name, &oid)) {
                if (explicit_tracking) {
                        if (advice_set_upstream_failure) {
                                error(_(upstream_missing), start_name);
@@ -339,8 +340,7 @@ void create_branch(struct repository *r,
 
 void remove_branch_state(struct repository *r)
 {
-       unlink(git_path_cherry_pick_head(r));
-       unlink(git_path_revert_head(r));
+       sequencer_post_commit_cleanup(r);
        unlink(git_path_merge_head(r));
        unlink(git_path_merge_rr(r));
        unlink(git_path_merge_msg(r));
index 29c1afa4d0ce5d1639b81d3d652d5b16085218e9..6f38db14e9c496c55e204791e5ab0a5243186118 100644 (file)
--- a/branch.h
+++ b/branch.h
@@ -50,7 +50,7 @@ void create_branch(struct repository *r,
  * Return 1 if the named branch already exists; return 0 otherwise.
  * Fill ref with the full refname for the branch.
  */
-extern int validate_branchname(const char *name, struct strbuf *ref);
+int validate_branchname(const char *name, struct strbuf *ref);
 
 /*
  * Check if a branch 'name' can be created as a new branch; die otherwise.
@@ -58,7 +58,7 @@ extern int validate_branchname(const char *name, struct strbuf *ref);
  * Return 1 if the named branch already exists; return 0 otherwise.
  * Fill ref with the full refname for the branch.
  */
-extern int validate_new_branchname(const char *name, struct strbuf *ref, int force);
+int validate_new_branchname(const char *name, struct strbuf *ref, int force);
 
 /*
  * Remove information about the state of working on the current
@@ -72,26 +72,26 @@ void remove_branch_state(struct repository *r);
  * Returns 0 on success.
  */
 #define BRANCH_CONFIG_VERBOSE 01
-extern int install_branch_config(int flag, const char *local, const char *origin, const char *remote);
+int install_branch_config(int flag, const char *local, const char *origin, const char *remote);
 
 /*
  * Read branch description
  */
-extern int read_branch_desc(struct strbuf *, const char *branch_name);
+int read_branch_desc(struct strbuf *, const char *branch_name);
 
 /*
  * Check if a branch is checked out in the main worktree or any linked
  * worktree and die (with a message describing its checkout location) if
  * it is.
  */
-extern void die_if_checked_out(const char *branch, int ignore_current_worktree);
+void die_if_checked_out(const char *branch, int ignore_current_worktree);
 
 /*
  * Update all per-worktree HEADs pointing at the old ref to point the new ref.
  * This will be used when renaming a branch. Returns 0 if successful, non-zero
  * otherwise.
  */
-extern int replace_each_worktree_head_symref(const char *oldref, const char *newref,
-                                            const char *logmsg);
+int replace_each_worktree_head_symref(const char *oldref, const char *newref,
+                                     const char *logmsg);
 
 #endif
index ac552ff0d2ce1cfb2d0036cc599d54311ebd3fb7..ec7e0954c4c8a1da896392bd28158abb74667898 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -102,7 +102,7 @@ extern const char git_more_info_string[];
 #define PRUNE_PACKED_DRY_RUN 01
 #define PRUNE_PACKED_VERBOSE 02
 
-extern void prune_packed_objects(int);
+void prune_packed_objects(int);
 
 struct fmt_merge_msg_opts {
        unsigned add_title:1,
@@ -110,8 +110,8 @@ struct fmt_merge_msg_opts {
        int shortlog_len;
 };
 
-extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
-                        struct fmt_merge_msg_opts *);
+int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
+                 struct fmt_merge_msg_opts *);
 
 /**
  * If a built-in has DELAY_PAGER_CONFIG set, the built-in should call this early
@@ -123,131 +123,131 @@ extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
  * You should most likely use a default of 0 or 1. "Punt" (-1) could be useful
  * to be able to fall back to some historical compatibility name.
  */
-extern void setup_auto_pager(const char *cmd, int def);
+void setup_auto_pager(const char *cmd, int def);
 
-extern int is_builtin(const char *s);
+int is_builtin(const char *s);
 
-extern int cmd_add(int argc, const char **argv, const char *prefix);
-extern int cmd_am(int argc, const char **argv, const char *prefix);
-extern int cmd_annotate(int argc, const char **argv, const char *prefix);
-extern int cmd_apply(int argc, const char **argv, const char *prefix);
-extern int cmd_archive(int argc, const char **argv, const char *prefix);
-extern int cmd_bisect__helper(int argc, const char **argv, const char *prefix);
-extern int cmd_blame(int argc, const char **argv, const char *prefix);
-extern int cmd_branch(int argc, const char **argv, const char *prefix);
-extern int cmd_bundle(int argc, const char **argv, const char *prefix);
-extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
-extern int cmd_checkout(int argc, const char **argv, const char *prefix);
-extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);
-extern int cmd_check_attr(int argc, const char **argv, const char *prefix);
-extern int cmd_check_ignore(int argc, const char **argv, const char *prefix);
-extern int cmd_check_mailmap(int argc, const char **argv, const char *prefix);
-extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
-extern int cmd_cherry(int argc, const char **argv, const char *prefix);
-extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix);
-extern int cmd_clone(int argc, const char **argv, const char *prefix);
-extern int cmd_clean(int argc, const char **argv, const char *prefix);
-extern int cmd_column(int argc, const char **argv, const char *prefix);
-extern int cmd_commit(int argc, const char **argv, const char *prefix);
-extern int cmd_commit_graph(int argc, const char **argv, const char *prefix);
-extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);
-extern int cmd_config(int argc, const char **argv, const char *prefix);
-extern int cmd_count_objects(int argc, const char **argv, const char *prefix);
-extern int cmd_credential(int argc, const char **argv, const char *prefix);
-extern int cmd_describe(int argc, const char **argv, const char *prefix);
-extern int cmd_diff_files(int argc, const char **argv, const char *prefix);
-extern int cmd_diff_index(int argc, const char **argv, const char *prefix);
-extern int cmd_diff(int argc, const char **argv, const char *prefix);
-extern int cmd_diff_tree(int argc, const char **argv, const char *prefix);
-extern int cmd_difftool(int argc, const char **argv, const char *prefix);
-extern int cmd_fast_export(int argc, const char **argv, const char *prefix);
-extern int cmd_fetch(int argc, const char **argv, const char *prefix);
-extern int cmd_fetch_pack(int argc, const char **argv, const char *prefix);
-extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
-extern int cmd_for_each_ref(int argc, const char **argv, const char *prefix);
-extern int cmd_format_patch(int argc, const char **argv, const char *prefix);
-extern int cmd_fsck(int argc, const char **argv, const char *prefix);
-extern int cmd_gc(int argc, const char **argv, const char *prefix);
-extern int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
-extern int cmd_grep(int argc, const char **argv, const char *prefix);
-extern int cmd_hash_object(int argc, const char **argv, const char *prefix);
-extern int cmd_help(int argc, const char **argv, const char *prefix);
-extern int cmd_index_pack(int argc, const char **argv, const char *prefix);
-extern int cmd_init_db(int argc, const char **argv, const char *prefix);
-extern int cmd_interpret_trailers(int argc, const char **argv, const char *prefix);
-extern int cmd_log(int argc, const char **argv, const char *prefix);
-extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);
-extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
-extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);
-extern int cmd_ls_remote(int argc, const char **argv, const char *prefix);
-extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);
-extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);
-extern int cmd_merge(int argc, const char **argv, const char *prefix);
-extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
-extern int cmd_merge_index(int argc, const char **argv, const char *prefix);
-extern int cmd_merge_ours(int argc, const char **argv, const char *prefix);
-extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
-extern int cmd_merge_recursive(int argc, const char **argv, const char *prefix);
-extern int cmd_merge_tree(int argc, const char **argv, const char *prefix);
-extern int cmd_mktag(int argc, const char **argv, const char *prefix);
-extern int cmd_mktree(int argc, const char **argv, const char *prefix);
-extern int cmd_multi_pack_index(int argc, const char **argv, const char *prefix);
-extern int cmd_mv(int argc, const char **argv, const char *prefix);
-extern int cmd_name_rev(int argc, const char **argv, const char *prefix);
-extern int cmd_notes(int argc, const char **argv, const char *prefix);
-extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);
-extern int cmd_pack_redundant(int argc, const char **argv, const char *prefix);
-extern int cmd_patch_id(int argc, const char **argv, const char *prefix);
-extern int cmd_prune(int argc, const char **argv, const char *prefix);
-extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);
-extern int cmd_pull(int argc, const char **argv, const char *prefix);
-extern int cmd_push(int argc, const char **argv, const char *prefix);
-extern int cmd_range_diff(int argc, const char **argv, const char *prefix);
-extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
-extern int cmd_rebase(int argc, const char **argv, const char *prefix);
-extern int cmd_rebase__interactive(int argc, const char **argv, const char *prefix);
-extern int cmd_receive_pack(int argc, const char **argv, const char *prefix);
-extern int cmd_reflog(int argc, const char **argv, const char *prefix);
-extern int cmd_remote(int argc, const char **argv, const char *prefix);
-extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
-extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
-extern int cmd_repack(int argc, const char **argv, const char *prefix);
-extern int cmd_rerere(int argc, const char **argv, const char *prefix);
-extern int cmd_reset(int argc, const char **argv, const char *prefix);
-extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
-extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
-extern int cmd_revert(int argc, const char **argv, const char *prefix);
-extern int cmd_rm(int argc, const char **argv, const char *prefix);
-extern int cmd_send_pack(int argc, const char **argv, const char *prefix);
-extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
-extern int cmd_show(int argc, const char **argv, const char *prefix);
-extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
-extern int cmd_show_index(int argc, const char **argv, const char *prefix);
-extern int cmd_status(int argc, const char **argv, const char *prefix);
-extern int cmd_stash(int argc, const char **argv, const char *prefix);
-extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
-extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
-extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
-extern int cmd_tag(int argc, const char **argv, const char *prefix);
-extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
-extern int cmd_unpack_file(int argc, const char **argv, const char *prefix);
-extern int cmd_unpack_objects(int argc, const char **argv, const char *prefix);
-extern int cmd_update_index(int argc, const char **argv, const char *prefix);
-extern int cmd_update_ref(int argc, const char **argv, const char *prefix);
-extern int cmd_update_server_info(int argc, const char **argv, const char *prefix);
-extern int cmd_upload_archive(int argc, const char **argv, const char *prefix);
-extern int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix);
-extern int cmd_upload_pack(int argc, const char **argv, const char *prefix);
-extern int cmd_var(int argc, const char **argv, const char *prefix);
-extern int cmd_verify_commit(int argc, const char **argv, const char *prefix);
-extern int cmd_verify_tag(int argc, const char **argv, const char *prefix);
-extern int cmd_version(int argc, const char **argv, const char *prefix);
-extern int cmd_whatchanged(int argc, const char **argv, const char *prefix);
-extern int cmd_worktree(int argc, const char **argv, const char *prefix);
-extern int cmd_write_tree(int argc, const char **argv, const char *prefix);
-extern int cmd_verify_pack(int argc, const char **argv, const char *prefix);
-extern int cmd_show_ref(int argc, const char **argv, const char *prefix);
-extern int cmd_pack_refs(int argc, const char **argv, const char *prefix);
-extern int cmd_replace(int argc, const char **argv, const char *prefix);
+int cmd_add(int argc, const char **argv, const char *prefix);
+int cmd_am(int argc, const char **argv, const char *prefix);
+int cmd_annotate(int argc, const char **argv, const char *prefix);
+int cmd_apply(int argc, const char **argv, const char *prefix);
+int cmd_archive(int argc, const char **argv, const char *prefix);
+int cmd_bisect__helper(int argc, const char **argv, const char *prefix);
+int cmd_blame(int argc, const char **argv, const char *prefix);
+int cmd_branch(int argc, const char **argv, const char *prefix);
+int cmd_bundle(int argc, const char **argv, const char *prefix);
+int cmd_cat_file(int argc, const char **argv, const char *prefix);
+int cmd_checkout(int argc, const char **argv, const char *prefix);
+int cmd_checkout_index(int argc, const char **argv, const char *prefix);
+int cmd_check_attr(int argc, const char **argv, const char *prefix);
+int cmd_check_ignore(int argc, const char **argv, const char *prefix);
+int cmd_check_mailmap(int argc, const char **argv, const char *prefix);
+int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
+int cmd_cherry(int argc, const char **argv, const char *prefix);
+int cmd_cherry_pick(int argc, const char **argv, const char *prefix);
+int cmd_clone(int argc, const char **argv, const char *prefix);
+int cmd_clean(int argc, const char **argv, const char *prefix);
+int cmd_column(int argc, const char **argv, const char *prefix);
+int cmd_commit(int argc, const char **argv, const char *prefix);
+int cmd_commit_graph(int argc, const char **argv, const char *prefix);
+int cmd_commit_tree(int argc, const char **argv, const char *prefix);
+int cmd_config(int argc, const char **argv, const char *prefix);
+int cmd_count_objects(int argc, const char **argv, const char *prefix);
+int cmd_credential(int argc, const char **argv, const char *prefix);
+int cmd_describe(int argc, const char **argv, const char *prefix);
+int cmd_diff_files(int argc, const char **argv, const char *prefix);
+int cmd_diff_index(int argc, const char **argv, const char *prefix);
+int cmd_diff(int argc, const char **argv, const char *prefix);
+int cmd_diff_tree(int argc, const char **argv, const char *prefix);
+int cmd_difftool(int argc, const char **argv, const char *prefix);
+int cmd_fast_export(int argc, const char **argv, const char *prefix);
+int cmd_fetch(int argc, const char **argv, const char *prefix);
+int cmd_fetch_pack(int argc, const char **argv, const char *prefix);
+int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
+int cmd_for_each_ref(int argc, const char **argv, const char *prefix);
+int cmd_format_patch(int argc, const char **argv, const char *prefix);
+int cmd_fsck(int argc, const char **argv, const char *prefix);
+int cmd_gc(int argc, const char **argv, const char *prefix);
+int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
+int cmd_grep(int argc, const char **argv, const char *prefix);
+int cmd_hash_object(int argc, const char **argv, const char *prefix);
+int cmd_help(int argc, const char **argv, const char *prefix);
+int cmd_index_pack(int argc, const char **argv, const char *prefix);
+int cmd_init_db(int argc, const char **argv, const char *prefix);
+int cmd_interpret_trailers(int argc, const char **argv, const char *prefix);
+int cmd_log(int argc, const char **argv, const char *prefix);
+int cmd_log_reflog(int argc, const char **argv, const char *prefix);
+int cmd_ls_files(int argc, const char **argv, const char *prefix);
+int cmd_ls_tree(int argc, const char **argv, const char *prefix);
+int cmd_ls_remote(int argc, const char **argv, const char *prefix);
+int cmd_mailinfo(int argc, const char **argv, const char *prefix);
+int cmd_mailsplit(int argc, const char **argv, const char *prefix);
+int cmd_merge(int argc, const char **argv, const char *prefix);
+int cmd_merge_base(int argc, const char **argv, const char *prefix);
+int cmd_merge_index(int argc, const char **argv, const char *prefix);
+int cmd_merge_ours(int argc, const char **argv, const char *prefix);
+int cmd_merge_file(int argc, const char **argv, const char *prefix);
+int cmd_merge_recursive(int argc, const char **argv, const char *prefix);
+int cmd_merge_tree(int argc, const char **argv, const char *prefix);
+int cmd_mktag(int argc, const char **argv, const char *prefix);
+int cmd_mktree(int argc, const char **argv, const char *prefix);
+int cmd_multi_pack_index(int argc, const char **argv, const char *prefix);
+int cmd_mv(int argc, const char **argv, const char *prefix);
+int cmd_name_rev(int argc, const char **argv, const char *prefix);
+int cmd_notes(int argc, const char **argv, const char *prefix);
+int cmd_pack_objects(int argc, const char **argv, const char *prefix);
+int cmd_pack_redundant(int argc, const char **argv, const char *prefix);
+int cmd_patch_id(int argc, const char **argv, const char *prefix);
+int cmd_prune(int argc, const char **argv, const char *prefix);
+int cmd_prune_packed(int argc, const char **argv, const char *prefix);
+int cmd_pull(int argc, const char **argv, const char *prefix);
+int cmd_push(int argc, const char **argv, const char *prefix);
+int cmd_range_diff(int argc, const char **argv, const char *prefix);
+int cmd_read_tree(int argc, const char **argv, const char *prefix);
+int cmd_rebase(int argc, const char **argv, const char *prefix);
+int cmd_rebase__interactive(int argc, const char **argv, const char *prefix);
+int cmd_receive_pack(int argc, const char **argv, const char *prefix);
+int cmd_reflog(int argc, const char **argv, const char *prefix);
+int cmd_remote(int argc, const char **argv, const char *prefix);
+int cmd_remote_ext(int argc, const char **argv, const char *prefix);
+int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+int cmd_repack(int argc, const char **argv, const char *prefix);
+int cmd_rerere(int argc, const char **argv, const char *prefix);
+int cmd_reset(int argc, const char **argv, const char *prefix);
+int cmd_rev_list(int argc, const char **argv, const char *prefix);
+int cmd_rev_parse(int argc, const char **argv, const char *prefix);
+int cmd_revert(int argc, const char **argv, const char *prefix);
+int cmd_rm(int argc, const char **argv, const char *prefix);
+int cmd_send_pack(int argc, const char **argv, const char *prefix);
+int cmd_shortlog(int argc, const char **argv, const char *prefix);
+int cmd_show(int argc, const char **argv, const char *prefix);
+int cmd_show_branch(int argc, const char **argv, const char *prefix);
+int cmd_show_index(int argc, const char **argv, const char *prefix);
+int cmd_status(int argc, const char **argv, const char *prefix);
+int cmd_stash(int argc, const char **argv, const char *prefix);
+int cmd_stripspace(int argc, const char **argv, const char *prefix);
+int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
+int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
+int cmd_tag(int argc, const char **argv, const char *prefix);
+int cmd_tar_tree(int argc, const char **argv, const char *prefix);
+int cmd_unpack_file(int argc, const char **argv, const char *prefix);
+int cmd_unpack_objects(int argc, const char **argv, const char *prefix);
+int cmd_update_index(int argc, const char **argv, const char *prefix);
+int cmd_update_ref(int argc, const char **argv, const char *prefix);
+int cmd_update_server_info(int argc, const char **argv, const char *prefix);
+int cmd_upload_archive(int argc, const char **argv, const char *prefix);
+int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix);
+int cmd_upload_pack(int argc, const char **argv, const char *prefix);
+int cmd_var(int argc, const char **argv, const char *prefix);
+int cmd_verify_commit(int argc, const char **argv, const char *prefix);
+int cmd_verify_tag(int argc, const char **argv, const char *prefix);
+int cmd_version(int argc, const char **argv, const char *prefix);
+int cmd_whatchanged(int argc, const char **argv, const char *prefix);
+int cmd_worktree(int argc, const char **argv, const char *prefix);
+int cmd_write_tree(int argc, const char **argv, const char *prefix);
+int cmd_verify_pack(int argc, const char **argv, const char *prefix);
+int cmd_show_ref(int argc, const char **argv, const char *prefix);
+int cmd_pack_refs(int argc, const char **argv, const char *prefix);
+int cmd_replace(int argc, const char **argv, const char *prefix);
 
 #endif
index 31a47d190a96a4bb7ea47eae28434456226cd8d2..85b0d3155de0d9ee9257ac44acc699c004022836 100644 (file)
@@ -99,10 +99,7 @@ static struct option builtin_clone_options[] = {
                    N_("don't use local hardlinks, always copy")),
        OPT_BOOL('s', "shared", &option_shared,
                    N_("setup as shared repository")),
-       { OPTION_CALLBACK, 0, "recursive", &option_recurse_submodules,
-         N_("pathspec"), N_("initialize submodules in the clone"),
-         PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, recurse_submodules_cb,
-         (intptr_t)"." },
+       OPT_ALIAS(0, "recursive", "recurse-submodules"),
        { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules,
          N_("pathspec"), N_("initialize submodules in the clone"),
          PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." },
@@ -660,7 +657,8 @@ static void update_remote_refs(const struct ref *refs,
                               const char *branch_top,
                               const char *msg,
                               struct transport *transport,
-                              int check_connectivity)
+                              int check_connectivity,
+                              int check_refs_only)
 {
        const struct ref *rm = mapped_refs;
 
@@ -669,6 +667,7 @@ static void update_remote_refs(const struct ref *refs,
 
                opt.transport = transport;
                opt.progress = transport->progress;
+               opt.check_refs_only = !!check_refs_only;
 
                if (check_connected(iterate_ref_map, &rm, &opt))
                        die(_("remote did not send all necessary objects"));
@@ -1230,7 +1229,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
        update_remote_refs(refs, mapped_refs, remote_head_points_at,
                           branch_top.buf, reflog_msg.buf, transport,
-                          !is_local);
+                          !is_local, filter_options.choice);
 
        update_head(our_head_points_at, remote_head, reflog_msg.buf);
 
index bd4b180c43f51b73da04894f88754b843cd2d0d1..1c9e8e2228c7ce58375bc247c4ad5850a1bd7d2d 100644 (file)
@@ -1658,8 +1658,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                die("%s", err.buf);
        }
 
-       unlink(git_path_cherry_pick_head(the_repository));
-       unlink(git_path_revert_head(the_repository));
+       sequencer_post_commit_cleanup(the_repository);
        unlink(git_path_merge_head(the_repository));
        unlink(git_path_merge_msg(the_repository));
        unlink(git_path_merge_mode(the_repository));
index 04ffa1d943d6e3a22eb919a21ad775c0bb29a6db..53188df71438ad83186bcae37a8742704ae048a5 100644 (file)
@@ -24,7 +24,6 @@
 #include "object-store.h"
 #include "dir.h"
 
-static char *diff_gui_tool;
 static int trust_exit_code;
 
 static const char *const builtin_difftool_usage[] = {
@@ -34,11 +33,6 @@ static const char *const builtin_difftool_usage[] = {
 
 static int difftool_config(const char *var, const char *value, void *cb)
 {
-       if (!strcmp(var, "diff.guitool")) {
-               diff_gui_tool = xstrdup(value);
-               return 0;
-       }
-
        if (!strcmp(var, "difftool.trustexitcode")) {
                trust_exit_code = git_config_bool(var, value);
                return 0;
@@ -735,8 +729,11 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
                setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
        }
 
-       if (use_gui_tool && diff_gui_tool && *diff_gui_tool)
-               setenv("GIT_DIFF_TOOL", diff_gui_tool, 1);
+       if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
+               die(_("--gui, --tool and --extcmd are mutually exclusive"));
+
+       if (use_gui_tool)
+               setenv("GIT_MERGETOOL_GUI", "true", 1);
        else if (difftool_cmd) {
                if (*difftool_cmd)
                        setenv("GIT_DIFF_TOOL", difftool_cmd, 1);
index ae6e476ad567e57e5a1e308d7901b0a0c331640f..72dfd3dadc7bf8037d4bd11d24aabca6a56a5fa8 100644 (file)
@@ -46,7 +46,7 @@ int cmd_multi_pack_index(int argc, const char **argv,
        if (!strcmp(argv[0], "write"))
                return write_midx_file(opts.object_dir);
        if (!strcmp(argv[0], "verify"))
-               return verify_midx_file(opts.object_dir);
+               return verify_midx_file(the_repository, opts.object_dir);
 
        die(_("unrecognized verb: %s"), argv[0]);
 }
index d7743f110bce610a20fd7089d8181a8c36f60e80..41d7fc59830c090d8b0422980528e4ea429c9e6b 100644 (file)
@@ -97,7 +97,7 @@ static off_t reuse_packfile_offset;
 static int use_bitmap_index_default = 1;
 static int use_bitmap_index = -1;
 static int write_bitmap_index;
-static uint16_t write_bitmap_options;
+static uint16_t write_bitmap_options = BITMAP_OPT_HASH_CACHE;
 
 static int exclude_promisor_objects;
 
@@ -1080,7 +1080,7 @@ static int want_object_in_pack(const struct object_id *oid,
 
        for (m = get_multi_pack_index(the_repository); m; m = m->next) {
                struct pack_entry e;
-               if (fill_midx_entry(oid, &e, m)) {
+               if (fill_midx_entry(the_repository, oid, &e, m)) {
                        struct packed_git *p = e.p;
                        off_t offset;
 
index f3353564f99205b278362484abcdf1537058ef29..cfbd5c36c7640bc841a68bb5a524f025c43212fd 100644 (file)
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "parse-options.h"
 #include "refs.h"
 #include "repository.h"
@@ -16,6 +17,7 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
                OPT_BIT(0, "prune", &flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE),
                OPT_END(),
        };
+       git_config(git_default_config, NULL);
        if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
                usage_with_options(pack_refs_usage, opts);
        return refs_pack_refs(get_main_ref_store(the_repository), flags);
diff --git a/builtin/rebase--interactive.c b/builtin/rebase--interactive.c
deleted file mode 100644 (file)
index 4535523..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "parse-options.h"
-#include "sequencer.h"
-#include "rebase-interactive.h"
-#include "argv-array.h"
-#include "refs.h"
-#include "rerere.h"
-#include "run-command.h"
-
-static GIT_PATH_FUNC(path_state_dir, "rebase-merge/")
-static GIT_PATH_FUNC(path_squash_onto, "rebase-merge/squash-onto")
-static GIT_PATH_FUNC(path_interactive, "rebase-merge/interactive")
-
-static int add_exec_commands(struct string_list *commands)
-{
-       const char *todo_file = rebase_path_todo();
-       struct todo_list todo_list = TODO_LIST_INIT;
-       int res;
-
-       if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
-               return error_errno(_("could not read '%s'."), todo_file);
-
-       if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
-                                       &todo_list)) {
-               todo_list_release(&todo_list);
-               return error(_("unusable todo list: '%s'"), todo_file);
-       }
-
-       todo_list_add_exec_commands(&todo_list, commands);
-       res = todo_list_write_to_file(the_repository, &todo_list,
-                                     todo_file, NULL, NULL, -1, 0);
-       todo_list_release(&todo_list);
-
-       if (res)
-               return error_errno(_("could not write '%s'."), todo_file);
-       return 0;
-}
-
-static int rearrange_squash_in_todo_file(void)
-{
-       const char *todo_file = rebase_path_todo();
-       struct todo_list todo_list = TODO_LIST_INIT;
-       int res = 0;
-
-       if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
-               return error_errno(_("could not read '%s'."), todo_file);
-       if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
-                                       &todo_list)) {
-               todo_list_release(&todo_list);
-               return error(_("unusable todo list: '%s'"), todo_file);
-       }
-
-       res = todo_list_rearrange_squash(&todo_list);
-       if (!res)
-               res = todo_list_write_to_file(the_repository, &todo_list,
-                                             todo_file, NULL, NULL, -1, 0);
-
-       todo_list_release(&todo_list);
-
-       if (res)
-               return error_errno(_("could not write '%s'."), todo_file);
-       return 0;
-}
-
-static int transform_todo_file(unsigned flags)
-{
-       const char *todo_file = rebase_path_todo();
-       struct todo_list todo_list = TODO_LIST_INIT;
-       int res;
-
-       if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
-               return error_errno(_("could not read '%s'."), todo_file);
-
-       if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
-                                       &todo_list)) {
-               todo_list_release(&todo_list);
-               return error(_("unusable todo list: '%s'"), todo_file);
-       }
-
-       res = todo_list_write_to_file(the_repository, &todo_list, todo_file,
-                                     NULL, NULL, -1, flags);
-       todo_list_release(&todo_list);
-
-       if (res)
-               return error_errno(_("could not write '%s'."), todo_file);
-       return 0;
-}
-
-static int edit_todo_file(unsigned flags)
-{
-       const char *todo_file = rebase_path_todo();
-       struct todo_list todo_list = TODO_LIST_INIT,
-               new_todo = TODO_LIST_INIT;
-       int res = 0;
-
-       if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
-               return error_errno(_("could not read '%s'."), todo_file);
-
-       strbuf_stripspace(&todo_list.buf, 1);
-       res = edit_todo_list(the_repository, &todo_list, &new_todo, NULL, NULL, flags);
-       if (!res && todo_list_write_to_file(the_repository, &new_todo, todo_file,
-                                           NULL, NULL, -1, flags & ~(TODO_LIST_SHORTEN_IDS)))
-               res = error_errno(_("could not write '%s'"), todo_file);
-
-       todo_list_release(&todo_list);
-       todo_list_release(&new_todo);
-
-       return res;
-}
-
-static int get_revision_ranges(const char *upstream, const char *onto,
-                              const char **head_hash,
-                              char **revisions, char **shortrevisions)
-{
-       const char *base_rev = upstream ? upstream : onto, *shorthead;
-       struct object_id orig_head;
-
-       if (get_oid("HEAD", &orig_head))
-               return error(_("no HEAD?"));
-
-       *head_hash = find_unique_abbrev(&orig_head, GIT_MAX_HEXSZ);
-       *revisions = xstrfmt("%s...%s", base_rev, *head_hash);
-
-       shorthead = find_unique_abbrev(&orig_head, DEFAULT_ABBREV);
-
-       if (upstream) {
-               const char *shortrev;
-               struct object_id rev_oid;
-
-               get_oid(base_rev, &rev_oid);
-               shortrev = find_unique_abbrev(&rev_oid, DEFAULT_ABBREV);
-
-               *shortrevisions = xstrfmt("%s..%s", shortrev, shorthead);
-       } else
-               *shortrevisions = xstrdup(shorthead);
-
-       return 0;
-}
-
-static int init_basic_state(struct replay_opts *opts, const char *head_name,
-                           const char *onto, const char *orig_head)
-{
-       FILE *interactive;
-
-       if (!is_directory(path_state_dir()) && mkdir_in_gitdir(path_state_dir()))
-               return error_errno(_("could not create temporary %s"), path_state_dir());
-
-       delete_reflog("REBASE_HEAD");
-
-       interactive = fopen(path_interactive(), "w");
-       if (!interactive)
-               return error_errno(_("could not mark as interactive"));
-       fclose(interactive);
-
-       return write_basic_state(opts, head_name, onto, orig_head);
-}
-
-static int do_interactive_rebase(struct replay_opts *opts, unsigned flags,
-                                const char *switch_to, const char *upstream,
-                                const char *onto, const char *onto_name,
-                                const char *squash_onto, const char *head_name,
-                                const char *restrict_revision, char *raw_strategies,
-                                struct string_list *commands, unsigned autosquash)
-{
-       int ret;
-       const char *head_hash = NULL;
-       char *revisions = NULL, *shortrevisions = NULL;
-       struct argv_array make_script_args = ARGV_ARRAY_INIT;
-       struct todo_list todo_list = TODO_LIST_INIT;
-
-       if (prepare_branch_to_be_rebased(opts, switch_to))
-               return -1;
-
-       if (get_revision_ranges(upstream, onto, &head_hash,
-                               &revisions, &shortrevisions))
-               return -1;
-
-       if (raw_strategies)
-               parse_strategy_opts(opts, raw_strategies);
-
-       if (init_basic_state(opts, head_name, onto, head_hash)) {
-               free(revisions);
-               free(shortrevisions);
-
-               return -1;
-       }
-
-       if (!upstream && squash_onto)
-               write_file(path_squash_onto(), "%s\n", squash_onto);
-
-       argv_array_pushl(&make_script_args, "", revisions, NULL);
-       if (restrict_revision)
-               argv_array_push(&make_script_args, restrict_revision);
-
-       ret = sequencer_make_script(the_repository, &todo_list.buf,
-                                   make_script_args.argc, make_script_args.argv,
-                                   flags);
-
-       if (ret)
-               error(_("could not generate todo list"));
-       else {
-               discard_cache();
-               if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
-                                               &todo_list))
-                       BUG("unusable todo list");
-
-               ret = complete_action(the_repository, opts, flags, shortrevisions, onto_name,
-                                     onto, head_hash, commands, autosquash, &todo_list);
-       }
-
-       free(revisions);
-       free(shortrevisions);
-       todo_list_release(&todo_list);
-       argv_array_clear(&make_script_args);
-
-       return ret;
-}
-
-static const char * const builtin_rebase_interactive_usage[] = {
-       N_("git rebase--interactive [<options>]"),
-       NULL
-};
-
-int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
-{
-       struct replay_opts opts = REPLAY_OPTS_INIT;
-       unsigned flags = 0, keep_empty = 0, rebase_merges = 0, autosquash = 0;
-       int abbreviate_commands = 0, rebase_cousins = -1, ret = 0;
-       const char *onto = NULL, *onto_name = NULL, *restrict_revision = NULL,
-               *squash_onto = NULL, *upstream = NULL, *head_name = NULL,
-               *switch_to = NULL, *cmd = NULL;
-       struct string_list commands = STRING_LIST_INIT_DUP;
-       char *raw_strategies = NULL;
-       enum {
-               NONE = 0, CONTINUE, SKIP, EDIT_TODO, SHOW_CURRENT_PATCH,
-               SHORTEN_OIDS, EXPAND_OIDS, CHECK_TODO_LIST, REARRANGE_SQUASH, ADD_EXEC
-       } command = 0;
-       struct option options[] = {
-               OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")),
-               OPT_BOOL(0, "keep-empty", &keep_empty, N_("keep empty commits")),
-               OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message,
-                        N_("allow commits with empty messages")),
-               OPT_BOOL(0, "rebase-merges", &rebase_merges, N_("rebase merge commits")),
-               OPT_BOOL(0, "rebase-cousins", &rebase_cousins,
-                        N_("keep original branch points of cousins")),
-               OPT_BOOL(0, "autosquash", &autosquash,
-                        N_("move commits that begin with squash!/fixup!")),
-               OPT_BOOL(0, "signoff", &opts.signoff, N_("sign commits")),
-               OPT__VERBOSE(&opts.verbose, N_("be verbose")),
-               OPT_CMDMODE(0, "continue", &command, N_("continue rebase"),
-                           CONTINUE),
-               OPT_CMDMODE(0, "skip", &command, N_("skip commit"), SKIP),
-               OPT_CMDMODE(0, "edit-todo", &command, N_("edit the todo list"),
-                           EDIT_TODO),
-               OPT_CMDMODE(0, "show-current-patch", &command, N_("show the current patch"),
-                           SHOW_CURRENT_PATCH),
-               OPT_CMDMODE(0, "shorten-ids", &command,
-                       N_("shorten commit ids in the todo list"), SHORTEN_OIDS),
-               OPT_CMDMODE(0, "expand-ids", &command,
-                       N_("expand commit ids in the todo list"), EXPAND_OIDS),
-               OPT_CMDMODE(0, "check-todo-list", &command,
-                       N_("check the todo list"), CHECK_TODO_LIST),
-               OPT_CMDMODE(0, "rearrange-squash", &command,
-                       N_("rearrange fixup/squash lines"), REARRANGE_SQUASH),
-               OPT_CMDMODE(0, "add-exec-commands", &command,
-                       N_("insert exec commands in todo list"), ADD_EXEC),
-               OPT_STRING(0, "onto", &onto, N_("onto"), N_("onto")),
-               OPT_STRING(0, "restrict-revision", &restrict_revision,
-                          N_("restrict-revision"), N_("restrict revision")),
-               OPT_STRING(0, "squash-onto", &squash_onto, N_("squash-onto"),
-                          N_("squash onto")),
-               OPT_STRING(0, "upstream", &upstream, N_("upstream"),
-                          N_("the upstream commit")),
-               OPT_STRING(0, "head-name", &head_name, N_("head-name"), N_("head name")),
-               { OPTION_STRING, 'S', "gpg-sign", &opts.gpg_sign, N_("key-id"),
-                       N_("GPG-sign commits"),
-                       PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-               OPT_STRING(0, "strategy", &opts.strategy, N_("strategy"),
-                          N_("rebase strategy")),
-               OPT_STRING(0, "strategy-opts", &raw_strategies, N_("strategy-opts"),
-                          N_("strategy options")),
-               OPT_STRING(0, "switch-to", &switch_to, N_("switch-to"),
-                          N_("the branch or commit to checkout")),
-               OPT_STRING(0, "onto-name", &onto_name, N_("onto-name"), N_("onto name")),
-               OPT_STRING(0, "cmd", &cmd, N_("cmd"), N_("the command to run")),
-               OPT_RERERE_AUTOUPDATE(&opts.allow_rerere_auto),
-               OPT_BOOL(0, "reschedule-failed-exec", &opts.reschedule_failed_exec,
-                        N_("automatically re-schedule any `exec` that fails")),
-               OPT_END()
-       };
-
-       sequencer_init_config(&opts);
-       git_config_get_bool("rebase.abbreviatecommands", &abbreviate_commands);
-
-       opts.action = REPLAY_INTERACTIVE_REBASE;
-       opts.allow_ff = 1;
-       opts.allow_empty = 1;
-
-       if (argc == 1)
-               usage_with_options(builtin_rebase_interactive_usage, options);
-
-       argc = parse_options(argc, argv, NULL, options,
-                       builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
-
-       opts.gpg_sign = xstrdup_or_null(opts.gpg_sign);
-
-       flags |= keep_empty ? TODO_LIST_KEEP_EMPTY : 0;
-       flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
-       flags |= rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
-       flags |= rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
-       flags |= command == SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
-
-       if (rebase_cousins >= 0 && !rebase_merges)
-               warning(_("--[no-]rebase-cousins has no effect without "
-                         "--rebase-merges"));
-
-       if (cmd && *cmd) {
-               string_list_split(&commands, cmd, '\n', -1);
-
-               /* rebase.c adds a new line to cmd after every command,
-                * so here the last command is always empty */
-               string_list_remove_empty_items(&commands, 0);
-       }
-
-       switch (command) {
-       case NONE:
-               if (!onto && !upstream)
-                       die(_("a base commit must be provided with --upstream or --onto"));
-
-               ret = do_interactive_rebase(&opts, flags, switch_to, upstream, onto,
-                                           onto_name, squash_onto, head_name, restrict_revision,
-                                           raw_strategies, &commands, autosquash);
-               break;
-       case SKIP: {
-               struct string_list merge_rr = STRING_LIST_INIT_DUP;
-
-               rerere_clear(the_repository, &merge_rr);
-               /* fallthrough */
-       case CONTINUE:
-               ret = sequencer_continue(the_repository, &opts);
-               break;
-       }
-       case EDIT_TODO:
-               ret = edit_todo_file(flags);
-               break;
-       case SHOW_CURRENT_PATCH: {
-               struct child_process cmd = CHILD_PROCESS_INIT;
-
-               cmd.git_cmd = 1;
-               argv_array_pushl(&cmd.args, "show", "REBASE_HEAD", "--", NULL);
-               ret = run_command(&cmd);
-
-               break;
-       }
-       case SHORTEN_OIDS:
-       case EXPAND_OIDS:
-               ret = transform_todo_file(flags);
-               break;
-       case CHECK_TODO_LIST:
-               ret = check_todo_list_from_file(the_repository);
-               break;
-       case REARRANGE_SQUASH:
-               ret = rearrange_squash_in_todo_file();
-               break;
-       case ADD_EXEC:
-               ret = add_exec_commands(&commands);
-               break;
-       default:
-               BUG("invalid command '%d'", command);
-       }
-
-       string_list_clear(&commands, 0);
-       return !!ret;
-}
index 966b953e86cc90c3683e4de01ef4b18a21229c74..ba3a574e4022c3dbd0e037782f520b1a199da42e 100644 (file)
@@ -25,6 +25,8 @@
 #include "commit-reach.h"
 #include "rerere.h"
 #include "branch.h"
+#include "sequencer.h"
+#include "rebase-interactive.h"
 
 static char const * const builtin_rebase_usage[] = {
        N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
@@ -35,6 +37,8 @@ static char const * const builtin_rebase_usage[] = {
        NULL
 };
 
+static GIT_PATH_FUNC(path_squash_onto, "rebase-merge/squash-onto")
+static GIT_PATH_FUNC(path_interactive, "rebase-merge/interactive")
 static GIT_PATH_FUNC(apply_dir, "rebase-apply")
 static GIT_PATH_FUNC(merge_dir, "rebase-merge")
 
@@ -86,6 +90,437 @@ struct rebase_options {
        int use_legacy_rebase;
 };
 
+#define REBASE_OPTIONS_INIT {                          \
+               .type = REBASE_UNSPECIFIED,             \
+               .flags = REBASE_NO_QUIET,               \
+               .git_am_opts = ARGV_ARRAY_INIT,         \
+               .git_format_patch_opt = STRBUF_INIT     \
+       }
+
+static struct replay_opts get_replay_opts(const struct rebase_options *opts)
+{
+       struct replay_opts replay = REPLAY_OPTS_INIT;
+
+       replay.action = REPLAY_INTERACTIVE_REBASE;
+       sequencer_init_config(&replay);
+
+       replay.signoff = opts->signoff;
+       replay.allow_ff = !(opts->flags & REBASE_FORCE);
+       if (opts->allow_rerere_autoupdate)
+               replay.allow_rerere_auto = opts->allow_rerere_autoupdate;
+       replay.allow_empty = 1;
+       replay.allow_empty_message = opts->allow_empty_message;
+       replay.verbose = opts->flags & REBASE_VERBOSE;
+       replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+       replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
+       replay.strategy = opts->strategy;
+       if (opts->strategy_opts)
+               parse_strategy_opts(&replay, opts->strategy_opts);
+
+       return replay;
+}
+
+enum action {
+       ACTION_NONE = 0,
+       ACTION_CONTINUE,
+       ACTION_SKIP,
+       ACTION_ABORT,
+       ACTION_QUIT,
+       ACTION_EDIT_TODO,
+       ACTION_SHOW_CURRENT_PATCH,
+       ACTION_SHORTEN_OIDS,
+       ACTION_EXPAND_OIDS,
+       ACTION_CHECK_TODO_LIST,
+       ACTION_REARRANGE_SQUASH,
+       ACTION_ADD_EXEC
+};
+
+static const char *action_names[] = { "undefined",
+                                     "continue",
+                                     "skip",
+                                     "abort",
+                                     "quit",
+                                     "edit_todo",
+                                     "show_current_patch" };
+
+static int add_exec_commands(struct string_list *commands)
+{
+       const char *todo_file = rebase_path_todo();
+       struct todo_list todo_list = TODO_LIST_INIT;
+       int res;
+
+       if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
+               return error_errno(_("could not read '%s'."), todo_file);
+
+       if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
+                                       &todo_list)) {
+               todo_list_release(&todo_list);
+               return error(_("unusable todo list: '%s'"), todo_file);
+       }
+
+       todo_list_add_exec_commands(&todo_list, commands);
+       res = todo_list_write_to_file(the_repository, &todo_list,
+                                     todo_file, NULL, NULL, -1, 0);
+       todo_list_release(&todo_list);
+
+       if (res)
+               return error_errno(_("could not write '%s'."), todo_file);
+       return 0;
+}
+
+static int rearrange_squash_in_todo_file(void)
+{
+       const char *todo_file = rebase_path_todo();
+       struct todo_list todo_list = TODO_LIST_INIT;
+       int res = 0;
+
+       if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
+               return error_errno(_("could not read '%s'."), todo_file);
+       if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
+                                       &todo_list)) {
+               todo_list_release(&todo_list);
+               return error(_("unusable todo list: '%s'"), todo_file);
+       }
+
+       res = todo_list_rearrange_squash(&todo_list);
+       if (!res)
+               res = todo_list_write_to_file(the_repository, &todo_list,
+                                             todo_file, NULL, NULL, -1, 0);
+
+       todo_list_release(&todo_list);
+
+       if (res)
+               return error_errno(_("could not write '%s'."), todo_file);
+       return 0;
+}
+
+static int transform_todo_file(unsigned flags)
+{
+       const char *todo_file = rebase_path_todo();
+       struct todo_list todo_list = TODO_LIST_INIT;
+       int res;
+
+       if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
+               return error_errno(_("could not read '%s'."), todo_file);
+
+       if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
+                                       &todo_list)) {
+               todo_list_release(&todo_list);
+               return error(_("unusable todo list: '%s'"), todo_file);
+       }
+
+       res = todo_list_write_to_file(the_repository, &todo_list, todo_file,
+                                     NULL, NULL, -1, flags);
+       todo_list_release(&todo_list);
+
+       if (res)
+               return error_errno(_("could not write '%s'."), todo_file);
+       return 0;
+}
+
+static int edit_todo_file(unsigned flags)
+{
+       const char *todo_file = rebase_path_todo();
+       struct todo_list todo_list = TODO_LIST_INIT,
+               new_todo = TODO_LIST_INIT;
+       int res = 0;
+
+       if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
+               return error_errno(_("could not read '%s'."), todo_file);
+
+       strbuf_stripspace(&todo_list.buf, 1);
+       res = edit_todo_list(the_repository, &todo_list, &new_todo, NULL, NULL, flags);
+       if (!res && todo_list_write_to_file(the_repository, &new_todo, todo_file,
+                                           NULL, NULL, -1, flags & ~(TODO_LIST_SHORTEN_IDS)))
+               res = error_errno(_("could not write '%s'"), todo_file);
+
+       todo_list_release(&todo_list);
+       todo_list_release(&new_todo);
+
+       return res;
+}
+
+static int get_revision_ranges(struct commit *upstream, struct commit *onto,
+                              const char **head_hash,
+                              char **revisions, char **shortrevisions)
+{
+       struct commit *base_rev = upstream ? upstream : onto;
+       const char *shorthead;
+       struct object_id orig_head;
+
+       if (get_oid("HEAD", &orig_head))
+               return error(_("no HEAD?"));
+
+       *head_hash = find_unique_abbrev(&orig_head, GIT_MAX_HEXSZ);
+       *revisions = xstrfmt("%s...%s", oid_to_hex(&base_rev->object.oid),
+                                                  *head_hash);
+
+       shorthead = find_unique_abbrev(&orig_head, DEFAULT_ABBREV);
+
+       if (upstream) {
+               const char *shortrev;
+
+               shortrev = find_unique_abbrev(&base_rev->object.oid,
+                                             DEFAULT_ABBREV);
+
+               *shortrevisions = xstrfmt("%s..%s", shortrev, shorthead);
+       } else
+               *shortrevisions = xstrdup(shorthead);
+
+       return 0;
+}
+
+static int init_basic_state(struct replay_opts *opts, const char *head_name,
+                           struct commit *onto, const char *orig_head)
+{
+       FILE *interactive;
+
+       if (!is_directory(merge_dir()) && mkdir_in_gitdir(merge_dir()))
+               return error_errno(_("could not create temporary %s"), merge_dir());
+
+       delete_reflog("REBASE_HEAD");
+
+       interactive = fopen(path_interactive(), "w");
+       if (!interactive)
+               return error_errno(_("could not mark as interactive"));
+       fclose(interactive);
+
+       return write_basic_state(opts, head_name, onto, orig_head);
+}
+
+static void split_exec_commands(const char *cmd, struct string_list *commands)
+{
+       if (cmd && *cmd) {
+               string_list_split(commands, cmd, '\n', -1);
+
+               /* rebase.c adds a new line to cmd after every command,
+                * so here the last command is always empty */
+               string_list_remove_empty_items(commands, 0);
+       }
+}
+
+static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
+{
+       int ret;
+       const char *head_hash = NULL;
+       char *revisions = NULL, *shortrevisions = NULL;
+       struct argv_array make_script_args = ARGV_ARRAY_INIT;
+       struct todo_list todo_list = TODO_LIST_INIT;
+       struct replay_opts replay = get_replay_opts(opts);
+       struct string_list commands = STRING_LIST_INIT_DUP;
+
+       if (prepare_branch_to_be_rebased(the_repository, &replay,
+                                        opts->switch_to))
+               return -1;
+
+       if (get_revision_ranges(opts->upstream, opts->onto, &head_hash,
+                               &revisions, &shortrevisions))
+               return -1;
+
+       if (init_basic_state(&replay,
+                            opts->head_name ? opts->head_name : "detached HEAD",
+                            opts->onto, head_hash)) {
+               free(revisions);
+               free(shortrevisions);
+
+               return -1;
+       }
+
+       if (!opts->upstream && opts->squash_onto)
+               write_file(path_squash_onto(), "%s\n",
+                          oid_to_hex(opts->squash_onto));
+
+       argv_array_pushl(&make_script_args, "", revisions, NULL);
+       if (opts->restrict_revision)
+               argv_array_push(&make_script_args,
+                               oid_to_hex(&opts->restrict_revision->object.oid));
+
+       ret = sequencer_make_script(the_repository, &todo_list.buf,
+                                   make_script_args.argc, make_script_args.argv,
+                                   flags);
+
+       if (ret)
+               error(_("could not generate todo list"));
+       else {
+               discard_cache();
+               if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
+                                               &todo_list))
+                       BUG("unusable todo list");
+
+               split_exec_commands(opts->cmd, &commands);
+               ret = complete_action(the_repository, &replay, flags,
+                       shortrevisions, opts->onto_name, opts->onto, head_hash,
+                       &commands, opts->autosquash, &todo_list);
+       }
+
+       string_list_clear(&commands, 0);
+       free(revisions);
+       free(shortrevisions);
+       todo_list_release(&todo_list);
+       argv_array_clear(&make_script_args);
+
+       return ret;
+}
+
+static int run_rebase_interactive(struct rebase_options *opts,
+                                 enum action command)
+{
+       unsigned flags = 0;
+       int abbreviate_commands = 0, ret = 0;
+
+       git_config_get_bool("rebase.abbreviatecommands", &abbreviate_commands);
+
+       flags |= opts->keep_empty ? TODO_LIST_KEEP_EMPTY : 0;
+       flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
+       flags |= opts->rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
+       flags |= opts->rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
+       flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
+
+       switch (command) {
+       case ACTION_NONE: {
+               if (!opts->onto && !opts->upstream)
+                       die(_("a base commit must be provided with --upstream or --onto"));
+
+               ret = do_interactive_rebase(opts, flags);
+               break;
+       }
+       case ACTION_SKIP: {
+               struct string_list merge_rr = STRING_LIST_INIT_DUP;
+
+               rerere_clear(the_repository, &merge_rr);
+       }
+               /* fallthrough */
+       case ACTION_CONTINUE: {
+               struct replay_opts replay_opts = get_replay_opts(opts);
+
+               ret = sequencer_continue(the_repository, &replay_opts);
+               break;
+       }
+       case ACTION_EDIT_TODO:
+               ret = edit_todo_file(flags);
+               break;
+       case ACTION_SHOW_CURRENT_PATCH: {
+               struct child_process cmd = CHILD_PROCESS_INIT;
+
+               cmd.git_cmd = 1;
+               argv_array_pushl(&cmd.args, "show", "REBASE_HEAD", "--", NULL);
+               ret = run_command(&cmd);
+
+               break;
+       }
+       case ACTION_SHORTEN_OIDS:
+       case ACTION_EXPAND_OIDS:
+               ret = transform_todo_file(flags);
+               break;
+       case ACTION_CHECK_TODO_LIST:
+               ret = check_todo_list_from_file(the_repository);
+               break;
+       case ACTION_REARRANGE_SQUASH:
+               ret = rearrange_squash_in_todo_file();
+               break;
+       case ACTION_ADD_EXEC: {
+               struct string_list commands = STRING_LIST_INIT_DUP;
+
+               split_exec_commands(opts->cmd, &commands);
+               ret = add_exec_commands(&commands);
+               string_list_clear(&commands, 0);
+               break;
+       }
+       default:
+               BUG("invalid command '%d'", command);
+       }
+
+       return ret;
+}
+
+static const char * const builtin_rebase_interactive_usage[] = {
+       N_("git rebase--interactive [<options>]"),
+       NULL
+};
+
+int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
+{
+       struct rebase_options opts = REBASE_OPTIONS_INIT;
+       struct object_id squash_onto = null_oid;
+       enum action command = ACTION_NONE;
+       struct option options[] = {
+               OPT_NEGBIT(0, "ff", &opts.flags, N_("allow fast-forward"),
+                          REBASE_FORCE),
+               OPT_BOOL(0, "keep-empty", &opts.keep_empty, N_("keep empty commits")),
+               OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message,
+                        N_("allow commits with empty messages")),
+               OPT_BOOL(0, "rebase-merges", &opts.rebase_merges, N_("rebase merge commits")),
+               OPT_BOOL(0, "rebase-cousins", &opts.rebase_cousins,
+                        N_("keep original branch points of cousins")),
+               OPT_BOOL(0, "autosquash", &opts.autosquash,
+                        N_("move commits that begin with squash!/fixup!")),
+               OPT_BOOL(0, "signoff", &opts.signoff, N_("sign commits")),
+               OPT_BIT('v', "verbose", &opts.flags,
+                       N_("display a diffstat of what changed upstream"),
+                       REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
+               OPT_CMDMODE(0, "continue", &command, N_("continue rebase"),
+                           ACTION_CONTINUE),
+               OPT_CMDMODE(0, "skip", &command, N_("skip commit"), ACTION_SKIP),
+               OPT_CMDMODE(0, "edit-todo", &command, N_("edit the todo list"),
+                           ACTION_EDIT_TODO),
+               OPT_CMDMODE(0, "show-current-patch", &command, N_("show the current patch"),
+                           ACTION_SHOW_CURRENT_PATCH),
+               OPT_CMDMODE(0, "shorten-ids", &command,
+                       N_("shorten commit ids in the todo list"), ACTION_SHORTEN_OIDS),
+               OPT_CMDMODE(0, "expand-ids", &command,
+                       N_("expand commit ids in the todo list"), ACTION_EXPAND_OIDS),
+               OPT_CMDMODE(0, "check-todo-list", &command,
+                       N_("check the todo list"), ACTION_CHECK_TODO_LIST),
+               OPT_CMDMODE(0, "rearrange-squash", &command,
+                       N_("rearrange fixup/squash lines"), ACTION_REARRANGE_SQUASH),
+               OPT_CMDMODE(0, "add-exec-commands", &command,
+                       N_("insert exec commands in todo list"), ACTION_ADD_EXEC),
+               { OPTION_CALLBACK, 0, "onto", &opts.onto, N_("onto"), N_("onto"),
+                 PARSE_OPT_NONEG, parse_opt_commit, 0 },
+               { OPTION_CALLBACK, 0, "restrict-revision", &opts.restrict_revision,
+                 N_("restrict-revision"), N_("restrict revision"),
+                 PARSE_OPT_NONEG, parse_opt_commit, 0 },
+               { OPTION_CALLBACK, 0, "squash-onto", &squash_onto, N_("squash-onto"),
+                 N_("squash onto"), PARSE_OPT_NONEG, parse_opt_object_id, 0 },
+               { OPTION_CALLBACK, 0, "upstream", &opts.upstream, N_("upstream"),
+                 N_("the upstream commit"), PARSE_OPT_NONEG, parse_opt_commit,
+                 0 },
+               OPT_STRING(0, "head-name", &opts.head_name, N_("head-name"), N_("head name")),
+               { OPTION_STRING, 'S', "gpg-sign", &opts.gpg_sign_opt, N_("key-id"),
+                       N_("GPG-sign commits"),
+                       PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+               OPT_STRING(0, "strategy", &opts.strategy, N_("strategy"),
+                          N_("rebase strategy")),
+               OPT_STRING(0, "strategy-opts", &opts.strategy_opts, N_("strategy-opts"),
+                          N_("strategy options")),
+               OPT_STRING(0, "switch-to", &opts.switch_to, N_("switch-to"),
+                          N_("the branch or commit to checkout")),
+               OPT_STRING(0, "onto-name", &opts.onto_name, N_("onto-name"), N_("onto name")),
+               OPT_STRING(0, "cmd", &opts.cmd, N_("cmd"), N_("the command to run")),
+               OPT_RERERE_AUTOUPDATE(&opts.allow_rerere_autoupdate),
+               OPT_BOOL(0, "reschedule-failed-exec", &opts.reschedule_failed_exec,
+                        N_("automatically re-schedule any `exec` that fails")),
+               OPT_END()
+       };
+
+       opts.rebase_cousins = -1;
+
+       if (argc == 1)
+               usage_with_options(builtin_rebase_interactive_usage, options);
+
+       argc = parse_options(argc, argv, NULL, options,
+                       builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
+
+       if (!is_null_oid(&squash_onto))
+               opts.squash_onto = &squash_onto;
+
+       if (opts.rebase_cousins >= 0 && !opts.rebase_merges)
+               warning(_("--[no-]rebase-cousins has no effect without "
+                         "--rebase-merges"));
+
+       return !!run_rebase_interactive(&opts, command);
+}
+
 static int is_interactive(struct rebase_options *opts)
 {
        return opts->type == REBASE_INTERACTIVE ||
@@ -184,14 +619,13 @@ static int read_basic_state(struct rebase_options *opts)
                            &buf))
                        return -1;
                if (!strcmp(buf.buf, "--rerere-autoupdate"))
-                       opts->allow_rerere_autoupdate = 1;
+                       opts->allow_rerere_autoupdate = RERERE_AUTOUPDATE;
                else if (!strcmp(buf.buf, "--no-rerere-autoupdate"))
-                       opts->allow_rerere_autoupdate = 0;
+                       opts->allow_rerere_autoupdate = RERERE_NOAUTOUPDATE;
                else
                        warning(_("ignoring invalid allow_rerere_autoupdate: "
                                  "'%s'"), buf.buf);
-       } else
-               opts->allow_rerere_autoupdate = -1;
+       }
 
        if (file_exists(state_dir_path("gpg_sign_opt", opts))) {
                strbuf_reset(&buf);
@@ -223,7 +657,7 @@ static int read_basic_state(struct rebase_options *opts)
        return 0;
 }
 
-static int write_basic_state(struct rebase_options *opts)
+static int rebase_write_basic_state(struct rebase_options *opts)
 {
        write_file(state_dir_path("head-name", opts), "%s",
                   opts->head_name ? opts->head_name : "detached HEAD");
@@ -241,10 +675,11 @@ static int write_basic_state(struct rebase_options *opts)
        if (opts->strategy_opts)
                write_file(state_dir_path("strategy_opts", opts), "%s",
                           opts->strategy_opts);
-       if (opts->allow_rerere_autoupdate >= 0)
+       if (opts->allow_rerere_autoupdate > 0)
                write_file(state_dir_path("allow_rerere_autoupdate", opts),
                           "-%s-rerere-autoupdate",
-                          opts->allow_rerere_autoupdate ? "" : "-no");
+                          opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE ?
+                               "" : "-no");
        if (opts->gpg_sign_opt)
                write_file(state_dir_path("gpg_sign_opt", opts), "%s",
                           opts->gpg_sign_opt);
@@ -608,9 +1043,9 @@ static int run_am(struct rebase_options *opts)
        argv_array_push(&am.args, "--rebasing");
        argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
        argv_array_push(&am.args, "--patch-format=mboxrd");
-       if (opts->allow_rerere_autoupdate > 0)
+       if (opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE)
                argv_array_push(&am.args, "--rerere-autoupdate");
-       else if (opts->allow_rerere_autoupdate == 0)
+       else if (opts->allow_rerere_autoupdate == RERERE_NOAUTOUPDATE)
                argv_array_push(&am.args, "--no-rerere-autoupdate");
        if (opts->gpg_sign_opt)
                argv_array_push(&am.args, opts->gpg_sign_opt);
@@ -623,12 +1058,12 @@ static int run_am(struct rebase_options *opts)
        }
 
        if (is_directory(opts->state_dir))
-               write_basic_state(opts);
+               rebase_write_basic_state(opts);
 
        return status;
 }
 
-static int run_specific_rebase(struct rebase_options *opts)
+static int run_specific_rebase(struct rebase_options *opts, enum action action)
 {
        const char *argv[] = { NULL, NULL };
        struct strbuf script_snippet = STRBUF_INIT, buf = STRBUF_INIT;
@@ -637,77 +1072,19 @@ static int run_specific_rebase(struct rebase_options *opts)
 
        if (opts->type == REBASE_INTERACTIVE) {
                /* Run builtin interactive rebase */
-               struct child_process child = CHILD_PROCESS_INIT;
-
-               argv_array_pushf(&child.env_array, "GIT_CHERRY_PICK_HELP=%s",
-                                resolvemsg);
+               setenv("GIT_CHERRY_PICK_HELP", resolvemsg, 1);
                if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
-                       argv_array_push(&child.env_array,
-                                       "GIT_SEQUENCE_EDITOR=:");
+                       setenv("GIT_SEQUENCE_EDITOR", ":", 1);
                        opts->autosquash = 0;
                }
+               if (opts->gpg_sign_opt) {
+                       /* remove the leading "-S" */
+                       char *tmp = xstrdup(opts->gpg_sign_opt + 2);
+                       free(opts->gpg_sign_opt);
+                       opts->gpg_sign_opt = tmp;
+               }
 
-               child.git_cmd = 1;
-               argv_array_push(&child.args, "rebase--interactive");
-
-               if (opts->action)
-                       argv_array_pushf(&child.args, "--%s", opts->action);
-               if (opts->keep_empty)
-                       argv_array_push(&child.args, "--keep-empty");
-               if (opts->rebase_merges)
-                       argv_array_push(&child.args, "--rebase-merges");
-               if (opts->rebase_cousins)
-                       argv_array_push(&child.args, "--rebase-cousins");
-               if (opts->autosquash)
-                       argv_array_push(&child.args, "--autosquash");
-               if (opts->flags & REBASE_VERBOSE)
-                       argv_array_push(&child.args, "--verbose");
-               if (opts->flags & REBASE_FORCE)
-                       argv_array_push(&child.args, "--no-ff");
-               if (opts->restrict_revision)
-                       argv_array_pushf(&child.args,
-                                        "--restrict-revision=^%s",
-                                        oid_to_hex(&opts->restrict_revision->object.oid));
-               if (opts->upstream)
-                       argv_array_pushf(&child.args, "--upstream=%s",
-                                        oid_to_hex(&opts->upstream->object.oid));
-               if (opts->onto)
-                       argv_array_pushf(&child.args, "--onto=%s",
-                                        oid_to_hex(&opts->onto->object.oid));
-               if (opts->squash_onto)
-                       argv_array_pushf(&child.args, "--squash-onto=%s",
-                                        oid_to_hex(opts->squash_onto));
-               if (opts->onto_name)
-                       argv_array_pushf(&child.args, "--onto-name=%s",
-                                        opts->onto_name);
-               argv_array_pushf(&child.args, "--head-name=%s",
-                                opts->head_name ?
-                                opts->head_name : "detached HEAD");
-               if (opts->strategy)
-                       argv_array_pushf(&child.args, "--strategy=%s",
-                                        opts->strategy);
-               if (opts->strategy_opts)
-                       argv_array_pushf(&child.args, "--strategy-opts=%s",
-                                        opts->strategy_opts);
-               if (opts->switch_to)
-                       argv_array_pushf(&child.args, "--switch-to=%s",
-                                        opts->switch_to);
-               if (opts->cmd)
-                       argv_array_pushf(&child.args, "--cmd=%s", opts->cmd);
-               if (opts->allow_empty_message)
-                       argv_array_push(&child.args, "--allow-empty-message");
-               if (opts->allow_rerere_autoupdate > 0)
-                       argv_array_push(&child.args, "--rerere-autoupdate");
-               else if (opts->allow_rerere_autoupdate == 0)
-                       argv_array_push(&child.args, "--no-rerere-autoupdate");
-               if (opts->gpg_sign_opt)
-                       argv_array_push(&child.args, opts->gpg_sign_opt);
-               if (opts->signoff)
-                       argv_array_push(&child.args, "--signoff");
-               if (opts->reschedule_failed_exec)
-                       argv_array_push(&child.args, "--reschedule-failed-exec");
-
-               status = run_command(&child);
+               status = run_rebase_interactive(opts, action);
                goto finished_rebase;
        }
 
@@ -747,9 +1124,9 @@ static int run_specific_rebase(struct rebase_options *opts)
        add_var(&script_snippet, "action", opts->action ? opts->action : "");
        add_var(&script_snippet, "signoff", opts->signoff ? "--signoff" : "");
        add_var(&script_snippet, "allow_rerere_autoupdate",
-               opts->allow_rerere_autoupdate < 0 ? "" :
                opts->allow_rerere_autoupdate ?
-               "--rerere-autoupdate" : "--no-rerere-autoupdate");
+                       opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE ?
+                       "--rerere-autoupdate" : "--no-rerere-autoupdate" : "");
        add_var(&script_snippet, "keep_empty", opts->keep_empty ? "yes" : "");
        add_var(&script_snippet, "autosquash", opts->autosquash ? "t" : "");
        add_var(&script_snippet, "gpg_sign_opt", opts->gpg_sign_opt);
@@ -991,14 +1368,7 @@ static int check_exec_cmd(const char *cmd)
 
 int cmd_rebase(int argc, const char **argv, const char *prefix)
 {
-       struct rebase_options options = {
-               .type = REBASE_UNSPECIFIED,
-               .flags = REBASE_NO_QUIET,
-               .git_am_opts = ARGV_ARRAY_INIT,
-               .allow_rerere_autoupdate  = -1,
-               .allow_empty_message = 1,
-               .git_format_patch_opt = STRBUF_INIT,
-       };
+       struct rebase_options options = REBASE_OPTIONS_INIT;
        const char *branch_name;
        int ret, flags, total_argc, in_progress = 0;
        int ok_to_skip_pre_rebase = 0;
@@ -1006,23 +1376,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
        struct strbuf revisions = STRBUF_INIT;
        struct strbuf buf = STRBUF_INIT;
        struct object_id merge_base;
-       enum {
-               NO_ACTION,
-               ACTION_CONTINUE,
-               ACTION_SKIP,
-               ACTION_ABORT,
-               ACTION_QUIT,
-               ACTION_EDIT_TODO,
-               ACTION_SHOW_CURRENT_PATCH,
-       } action = NO_ACTION;
-       static const char *action_names[] = { N_("undefined"),
-                                             N_("continue"),
-                                             N_("skip"),
-                                             N_("abort"),
-                                             N_("quit"),
-                                             N_("edit_todo"),
-                                             N_("show_current_patch"),
-                                             NULL };
+       enum action action = ACTION_NONE;
        const char *gpg_sign = NULL;
        struct string_list exec = STRING_LIST_INIT_NODUP;
        const char *rebase_merges = NULL;
@@ -1090,10 +1444,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                OPT_SET_INT('p', "preserve-merges", &options.type,
                            N_("(DEPRECATED) try to recreate merges instead of "
                               "ignoring them"), REBASE_PRESERVE_MERGES),
-               OPT_BOOL(0, "rerere-autoupdate",
-                        &options.allow_rerere_autoupdate,
-                        N_("allow rerere to update index with resolved "
-                           "conflict")),
+               OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate),
                OPT_BOOL('k', "keep-empty", &options.keep_empty,
                         N_("preserve empty commits during rebase")),
                OPT_BOOL(0, "autosquash", &options.autosquash,
@@ -1139,6 +1490,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
        trace_repo_setup(prefix);
        setup_work_tree();
 
+       options.allow_empty_message = 1;
        git_config(rebase_config, &options);
 
        if (options.use_legacy_rebase ||
@@ -1180,7 +1532,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                             builtin_rebase_options,
                             builtin_rebase_usage, 0);
 
-       if (action != NO_ACTION && total_argc != 2) {
+       if (action != ACTION_NONE && total_argc != 2) {
                usage_with_options(builtin_rebase_usage,
                                   builtin_rebase_options);
        }
@@ -1193,7 +1545,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                warning(_("git rebase --preserve-merges is deprecated. "
                          "Use --rebase-merges instead."));
 
-       if (action != NO_ACTION && !in_progress)
+       if (action != ACTION_NONE && !in_progress)
                die(_("No rebase in progress?"));
        setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
 
@@ -1293,7 +1645,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                options.action = "show-current-patch";
                options.dont_finish_rebase = 1;
                goto run_rebase;
-       case NO_ACTION:
+       case ACTION_NONE:
                break;
        default:
                BUG("action: %d", action);
@@ -1791,7 +2143,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
        options.revisions = revisions.buf;
 
 run_rebase:
-       ret = !!run_specific_rebase(&options);
+       ret = !!run_specific_rebase(&options, action);
 
 cleanup:
        strbuf_release(&revisions);
index 67f8978043a43988d653092f83f21bd5baad9751..caca11392713eb92816d1e503f286bfe0d9be78a 100644 (file)
@@ -14,7 +14,7 @@
 
 static int delta_base_offset = 1;
 static int pack_kept_objects = -1;
-static int write_bitmaps;
+static int write_bitmaps = -1;
 static int use_delta_islands;
 static char *packdir, *packtmp;
 
@@ -343,6 +343,9 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
            (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
                die(_("--keep-unreachable and -A are incompatible"));
 
+       if (write_bitmaps < 0)
+               write_bitmaps = (pack_everything & ALL_INTO_ONE) &&
+                                is_bare_repository();
        if (pack_kept_objects < 0)
                pack_kept_objects = write_bitmaps;
 
index 6a706c02a6f9782ee4abb289cfafe468253aca1f..6456da70cc2c4d6a86c2466c483dd815b15bbb45 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "object-store.h"
 #include "object.h"
@@ -182,6 +183,8 @@ static const struct option show_ref_options[] = {
 
 int cmd_show_ref(int argc, const char **argv, const char *prefix)
 {
+       git_config(git_default_config, NULL);
+
        argc = parse_options(argc, argv, prefix, show_ref_options,
                             show_ref_usage, 0);
 
index 8c72ea864c81d8763ac48ee7e1e7795e1323ddb3..0bf4aa088e0ca4bf6378d121cfc23e0f42ac3af4 100644 (file)
@@ -1301,7 +1301,7 @@ static int add_possible_reference_from_superproject(
                                die(_("submodule '%s' cannot add alternate: %s"),
                                    sas->submodule_name, err.buf);
                        case SUBMODULE_ALTERNATE_ERROR_INFO:
-                               fprintf(stderr, _("submodule '%s' cannot add alternate: %s"),
+                               fprintf_ln(stderr, _("submodule '%s' cannot add alternate: %s"),
                                        sas->submodule_name, err.buf);
                        case SUBMODULE_ALTERNATE_ERROR_IGNORE:
                                ; /* nothing */
index 1debd3a11c2ec0aa44fa75ebd908f78a46f371a1..ef37dccf864932a31c019775cdad6d33207941a1 100644 (file)
@@ -207,7 +207,7 @@ struct create_tag_options {
 };
 
 static const char message_advice_nested_tag[] =
-       N_("You have created a nested tag. The object referred to by your new is\n"
+       N_("You have created a nested tag. The object referred to by your new tag is\n"
           "already a tag. If you meant to tag the object that it points to, use:\n"
           "\n"
           "\tgit tag -f %s %s^{}");
index f438f93811bfc62aa79a9ba6f9476240100e286f..b26f3dc3b74cb9ccb4ea630fafe8cd0cdcf5a012 100644 (file)
@@ -6,11 +6,11 @@
 
 #include "cache.h"
 
-extern int index_bulk_checkin(struct object_id *oid,
-                             int fd, size_t size, enum object_type type,
-                             const char *path, unsigned flags);
+int index_bulk_checkin(struct object_id *oid,
+                      int fd, size_t size, enum object_type type,
+                      const char *path, unsigned flags);
 
-extern void plug_bulk_checkin(void);
-extern void unplug_bulk_checkin(void);
+void plug_bulk_checkin(void);
+void unplug_bulk_checkin(void);
 
 #endif
diff --git a/cache.h b/cache.h
index 67cc2e1806ab4fabd4b34c0e1b4ca5cd1abafd82..b4bb2e2c11adff0061065fa975874c7c4a2a318b 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -341,7 +341,8 @@ struct index_state {
                 initialized : 1,
                 drop_cache_tree : 1,
                 updated_workdir : 1,
-                updated_skipworktree : 1;
+                updated_skipworktree : 1,
+                fsmonitor_has_run_once : 1;
        struct hashmap name_hash;
        struct hashmap dir_hash;
        struct object_id oid;
@@ -352,10 +353,10 @@ struct index_state {
 };
 
 /* Name hashing */
-extern int test_lazy_init_name_hash(struct index_state *istate, int try_threaded);
-extern void add_name_hash(struct index_state *istate, struct cache_entry *ce);
-extern void remove_name_hash(struct index_state *istate, struct cache_entry *ce);
-extern void free_name_hash(struct index_state *istate);
+int test_lazy_init_name_hash(struct index_state *istate, int try_threaded);
+void add_name_hash(struct index_state *istate, struct cache_entry *ce);
+void remove_name_hash(struct index_state *istate, struct cache_entry *ce);
+void free_name_hash(struct index_state *istate);
 
 
 /* Cache entry creation and cleanup */
@@ -545,7 +546,7 @@ static inline enum object_type object_type(unsigned int mode)
  */
 extern const char * const local_repo_env[];
 
-extern void setup_git_env(const char *git_dir);
+void setup_git_env(const char *git_dir);
 
 /*
  * Returns true iff we have a configured git repository (either via
@@ -554,29 +555,29 @@ extern void setup_git_env(const char *git_dir);
 int have_git_dir(void);
 
 extern int is_bare_repository_cfg;
-extern int is_bare_repository(void);
-extern int is_inside_git_dir(void);
+int is_bare_repository(void);
+int is_inside_git_dir(void);
 extern char *git_work_tree_cfg;
-extern int is_inside_work_tree(void);
-extern const char *get_git_dir(void);
-extern const char *get_git_common_dir(void);
-extern char *get_object_directory(void);
-extern char *get_index_file(void);
-extern char *get_graft_file(struct repository *r);
-extern void set_git_dir(const char *path);
-extern int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
-extern int get_common_dir(struct strbuf *sb, const char *gitdir);
-extern const char *get_git_namespace(void);
-extern const char *strip_namespace(const char *namespaced_ref);
-extern const char *get_super_prefix(void);
-extern const char *get_git_work_tree(void);
+int is_inside_work_tree(void);
+const char *get_git_dir(void);
+const char *get_git_common_dir(void);
+char *get_object_directory(void);
+char *get_index_file(void);
+char *get_graft_file(struct repository *r);
+void set_git_dir(const char *path);
+int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
+int get_common_dir(struct strbuf *sb, const char *gitdir);
+const char *get_git_namespace(void);
+const char *strip_namespace(const char *namespaced_ref);
+const char *get_super_prefix(void);
+const char *get_git_work_tree(void);
 
 /*
  * Return true if the given path is a git directory; note that this _just_
  * looks at the directory itself. If you want to know whether "foo/.git"
  * is a repository, you must feed that path, not just "foo".
  */
-extern int is_git_directory(const char *path);
+int is_git_directory(const char *path);
 
 /*
  * Return 1 if the given path is the root of a git repository or
@@ -588,7 +589,7 @@ extern int is_git_directory(const char *path);
  * as we usually consider sub-repos precious, and would prefer to err on the
  * side of not disrupting or deleting them.
  */
-extern int is_nonbare_repository_dir(struct strbuf *path);
+int is_nonbare_repository_dir(struct strbuf *path);
 
 #define READ_GITFILE_ERR_STAT_FAILED 1
 #define READ_GITFILE_ERR_NOT_A_FILE 2
@@ -598,17 +599,17 @@ extern int is_nonbare_repository_dir(struct strbuf *path);
 #define READ_GITFILE_ERR_NO_PATH 6
 #define READ_GITFILE_ERR_NOT_A_REPO 7
 #define READ_GITFILE_ERR_TOO_LARGE 8
-extern void read_gitfile_error_die(int error_code, const char *path, const char *dir);
-extern const char *read_gitfile_gently(const char *path, int *return_error_code);
+void read_gitfile_error_die(int error_code, const char *path, const char *dir);
+const char *read_gitfile_gently(const char *path, int *return_error_code);
 #define read_gitfile(path) read_gitfile_gently((path), NULL)
-extern const char *resolve_gitdir_gently(const char *suspect, int *return_error_code);
+const char *resolve_gitdir_gently(const char *suspect, int *return_error_code);
 #define resolve_gitdir(path) resolve_gitdir_gently((path), NULL)
 
-extern void set_git_work_tree(const char *tree);
+void set_git_work_tree(const char *tree);
 
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
-extern void setup_work_tree(void);
+void setup_work_tree(void);
 /*
  * Find the commondir and gitdir of the repository that contains the current
  * working directory, without changing the working directory or other global
@@ -617,12 +618,12 @@ extern void setup_work_tree(void);
  * both have the same result appended to the buffer.  The return value is
  * either 0 upon success and non-zero if no repository was found.
  */
-extern int discover_git_directory(struct strbuf *commondir,
-                                 struct strbuf *gitdir);
-extern const char *setup_git_directory_gently(int *);
-extern const char *setup_git_directory(void);
-extern char *prefix_path(const char *prefix, int len, const char *path);
-extern char *prefix_path_gently(const char *prefix, int len, int *remaining, const char *path);
+int discover_git_directory(struct strbuf *commondir,
+                          struct strbuf *gitdir);
+const char *setup_git_directory_gently(int *);
+const char *setup_git_directory(void);
+char *prefix_path(const char *prefix, int len, const char *path);
+char *prefix_path_gently(const char *prefix, int len, int *remaining, const char *path);
 
 /*
  * Concatenate "prefix" (if len is non-zero) and "path", with no
@@ -634,23 +635,23 @@ extern char *prefix_path_gently(const char *prefix, int len, int *remaining, con
  * The return value is always a newly allocated string (even if the
  * prefix was empty).
  */
-extern char *prefix_filename(const char *prefix, const char *path);
+char *prefix_filename(const char *prefix, const char *path);
 
-extern int check_filename(const char *prefix, const char *name);
-extern void verify_filename(const char *prefix,
-                           const char *name,
-                           int diagnose_misspelt_rev);
-extern void verify_non_filename(const char *prefix, const char *name);
-extern int path_inside_repo(const char *prefix, const char *path);
+int check_filename(const char *prefix, const char *name);
+void verify_filename(const char *prefix,
+                    const char *name,
+                    int diagnose_misspelt_rev);
+void verify_non_filename(const char *prefix, const char *name);
+int path_inside_repo(const char *prefix, const char *path);
 
 #define INIT_DB_QUIET 0x0001
 #define INIT_DB_EXIST_OK 0x0002
 
-extern int init_db(const char *git_dir, const char *real_git_dir,
-                  const char *template_dir, unsigned int flags);
+int init_db(const char *git_dir, const char *real_git_dir,
+           const char *template_dir, unsigned int flags);
 
-extern void sanitize_stdfds(void);
-extern int daemonize(void);
+void sanitize_stdfds(void);
+int daemonize(void);
 
 #define alloc_nr(x) (((x)+16)*3/2)
 
@@ -674,14 +675,14 @@ extern int daemonize(void);
 
 /* Initialize and use the cache information */
 struct lock_file;
-extern void preload_index(struct index_state *index,
-                         const struct pathspec *pathspec,
-                         unsigned int refresh_flags);
-extern int do_read_index(struct index_state *istate, const char *path,
-                        int must_exist); /* for testting only! */
-extern int read_index_from(struct index_state *, const char *path,
-                          const char *gitdir);
-extern int is_index_unborn(struct index_state *);
+void preload_index(struct index_state *index,
+                  const struct pathspec *pathspec,
+                  unsigned int refresh_flags);
+int do_read_index(struct index_state *istate, const char *path,
+                 int must_exist); /* for testting only! */
+int read_index_from(struct index_state *, const char *path,
+                   const char *gitdir);
+int is_index_unborn(struct index_state *);
 
 /* For use with `write_locked_index()`. */
 #define COMMIT_LOCK            (1 << 0)
@@ -706,11 +707,11 @@ extern int is_index_unborn(struct index_state *);
  * If `SKIP_IF_UNCHANGED` is given and the index is unchanged, nothing
  * is written (and the lock is rolled back if `COMMIT_LOCK` is given).
  */
-extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
+int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 
-extern int discard_index(struct index_state *);
-extern void move_index_extensions(struct index_state *dst, struct index_state *src);
-extern int unmerged_index(const struct index_state *);
+int discard_index(struct index_state *);
+void move_index_extensions(struct index_state *dst, struct index_state *src);
+int unmerged_index(const struct index_state *);
 
 /**
  * Returns 1 if istate differs from tree, 0 otherwise.  If tree is NULL,
@@ -719,15 +720,15 @@ extern int unmerged_index(const struct index_state *);
  * provided, the space-separated list of files that differ will be appended
  * to it.
  */
-extern int repo_index_has_changes(struct repository *repo,
-                                 struct tree *tree,
-                                 struct strbuf *sb);
+int repo_index_has_changes(struct repository *repo,
+                          struct tree *tree,
+                          struct strbuf *sb);
 
-extern int verify_path(const char *path, unsigned mode);
-extern int strcmp_offset(const char *s1, const char *s2, size_t *first_change);
-extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
-extern void adjust_dirname_case(struct index_state *istate, char *name);
-extern struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int igncase);
+int verify_path(const char *path, unsigned mode);
+int strcmp_offset(const char *s1, const char *s2, size_t *first_change);
+int index_dir_exists(struct index_state *istate, const char *name, int namelen);
+void adjust_dirname_case(struct index_state *istate, char *name);
+struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int igncase);
 
 /*
  * Searches for an entry defined by name and namelen in the given index.
@@ -746,7 +747,7 @@ extern struct cache_entry *index_file_exists(struct index_state *istate, const c
  * index_name_pos(&index, "f", 1) -> -3
  * index_name_pos(&index, "g", 1) -> -5
  */
-extern int index_name_pos(const struct index_state *, const char *name, int namelen);
+int index_name_pos(const struct index_state *, const char *name, int namelen);
 
 #define ADD_CACHE_OK_TO_ADD 1          /* Ok to add */
 #define ADD_CACHE_OK_TO_REPLACE 2      /* Ok to replace file/directory */
@@ -755,14 +756,14 @@ extern int index_name_pos(const struct index_state *, const char *name, int name
 #define ADD_CACHE_NEW_ONLY 16          /* Do not replace existing ones */
 #define ADD_CACHE_KEEP_CACHE_TREE 32   /* Do not invalidate cache-tree */
 #define ADD_CACHE_RENORMALIZE 64        /* Pass along HASH_RENORMALIZE */
-extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
-extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
+int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
+void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
 
 /* Remove entry, return true if there are more entries to go. */
-extern int remove_index_entry_at(struct index_state *, int pos);
+int remove_index_entry_at(struct index_state *, int pos);
 
-extern void remove_marked_cache_entries(struct index_state *istate, int invalidate);
-extern int remove_file_from_index(struct index_state *, const char *path);
+void remove_marked_cache_entries(struct index_state *istate, int invalidate);
+int remove_file_from_index(struct index_state *, const char *path);
 #define ADD_CACHE_VERBOSE 1
 #define ADD_CACHE_PRETEND 2
 #define ADD_CACHE_IGNORE_ERRORS        4
@@ -777,14 +778,14 @@ extern int remove_file_from_index(struct index_state *, const char *path);
  * the latter will do necessary lstat(2) internally before
  * calling the former.
  */
-extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
-extern int add_file_to_index(struct index_state *, const char *path, int flags);
+int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
+int add_file_to_index(struct index_state *, const char *path, int flags);
 
-extern int chmod_index_entry(struct index_state *, struct cache_entry *ce, char flip);
-extern int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
-extern void set_object_name_for_intent_to_add_entry(struct cache_entry *ce);
-extern int index_name_is_other(const struct index_state *, const char *, int);
-extern void *read_blob_data_from_index(const struct index_state *, const char *, unsigned long *);
+int chmod_index_entry(struct index_state *, struct cache_entry *ce, char flip);
+int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
+void set_object_name_for_intent_to_add_entry(struct cache_entry *ce);
+int index_name_is_other(const struct index_state *, const char *, int);
+void *read_blob_data_from_index(const struct index_state *, const char *, unsigned long *);
 
 /* do stat comparison even if CE_VALID is true */
 #define CE_MATCH_IGNORE_VALID          01
@@ -798,22 +799,22 @@ extern void *read_blob_data_from_index(const struct index_state *, const char *,
 #define CE_MATCH_REFRESH               0x10
 /* don't refresh_fsmonitor state or do stat comparison even if CE_FSMONITOR_VALID is true */
 #define CE_MATCH_IGNORE_FSMONITOR 0X20
-extern int is_racy_timestamp(const struct index_state *istate,
-                            const struct cache_entry *ce);
-extern int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
-extern int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
+int is_racy_timestamp(const struct index_state *istate,
+                     const struct cache_entry *ce);
+int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
+int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
 
 #define HASH_WRITE_OBJECT 1
 #define HASH_FORMAT_CHECK 2
 #define HASH_RENORMALIZE  4
-extern int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
-extern int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
+int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
+int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
 
 /*
  * Record to sd the data from st that we use to check whether a file
  * might have changed.
  */
-extern void fill_stat_data(struct stat_data *sd, struct stat *st);
+void fill_stat_data(struct stat_data *sd, struct stat *st);
 
 /*
  * Return 0 if st is consistent with a file not having been changed
@@ -821,11 +822,11 @@ extern void fill_stat_data(struct stat_data *sd, struct stat *st);
  * combination of MTIME_CHANGED, CTIME_CHANGED, OWNER_CHANGED,
  * INODE_CHANGED, and DATA_CHANGED.
  */
-extern int match_stat_data(const struct stat_data *sd, struct stat *st);
-extern int match_stat_data_racy(const struct index_state *istate,
-                               const struct stat_data *sd, struct stat *st);
+int match_stat_data(const struct stat_data *sd, struct stat *st);
+int match_stat_data_racy(const struct index_state *istate,
+                        const struct stat_data *sd, struct stat *st);
 
-extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
+void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
 
 #define REFRESH_REALLY         0x0001  /* ignore_valid */
 #define REFRESH_UNMERGED       0x0002  /* allow unmerged */
@@ -834,10 +835,10 @@ extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
 #define REFRESH_IGNORE_SUBMODULES      0x0010  /* ignore submodules */
 #define REFRESH_IN_PORCELAIN   0x0020  /* user friendly output, not "needs update" */
 #define REFRESH_PROGRESS       0x0040  /* show progress bar if stderr is tty */
-extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
-extern struct cache_entry *refresh_cache_entry(struct index_state *, struct cache_entry *, unsigned int);
+int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
+struct cache_entry *refresh_cache_entry(struct index_state *, struct cache_entry *, unsigned int);
 
-extern void set_alternate_index_output(const char *);
+void set_alternate_index_output(const char *);
 
 extern int verify_index_checksum;
 extern int verify_ce_order;
@@ -1022,7 +1023,7 @@ int verify_repository_format(const struct repository_format *format,
  * set_git_dir() before calling this, and use it only for "are we in a valid
  * repo?".
  */
-extern void check_repository_format(void);
+void check_repository_format(void);
 
 #define MTIME_CHANGED  0x0001
 #define CTIME_CHANGED  0x0002
@@ -1246,7 +1247,7 @@ typedef int create_file_fn(const char *path, void *cb);
 int raceproof_create_file(const char *path, create_file_fn fn, void *cb);
 
 int mkdir_in_gitdir(const char *path);
-extern char *expand_user_path(const char *path, int real_home);
+char *expand_user_path(const char *path, int real_home);
 const char *enter_repo(const char *path, int strict);
 static inline int is_absolute_path(const char *path)
 {
@@ -1290,26 +1291,26 @@ int looks_like_command_line_option(const char *str);
  * "$XDG_CONFIG_HOME/git/$filename" if $XDG_CONFIG_HOME is non-empty, otherwise
  * "$HOME/.config/git/$filename". Return NULL upon error.
  */
-extern char *xdg_config_home(const char *filename);
+char *xdg_config_home(const char *filename);
 
 /**
  * Return a newly allocated string with the evaluation of
  * "$XDG_CACHE_HOME/git/$filename" if $XDG_CACHE_HOME is non-empty, otherwise
  * "$HOME/.cache/git/$filename". Return NULL upon error.
  */
-extern char *xdg_cache_home(const char *filename);
+char *xdg_cache_home(const char *filename);
 
-extern int git_open_cloexec(const char *name, int flags);
+int git_open_cloexec(const char *name, int flags);
 #define git_open(name) git_open_cloexec(name, O_RDONLY)
-extern int unpack_loose_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
-extern int parse_loose_header(const char *hdr, unsigned long *sizep);
+int unpack_loose_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
+int parse_loose_header(const char *hdr, unsigned long *sizep);
 
-extern int check_object_signature(const struct object_id *oid, void *buf, unsigned long size, const char *type);
+int check_object_signature(const struct object_id *oid, void *buf, unsigned long size, const char *type);
 
-extern int finalize_object_file(const char *tmpfile, const char *filename);
+int finalize_object_file(const char *tmpfile, const char *filename);
 
 /* Helper to check and "touch" a file */
-extern int check_and_freshen_file(const char *fn, int freshen);
+int check_and_freshen_file(const char *fn, int freshen);
 
 extern const signed char hexval_table[256];
 static inline unsigned int hexval(unsigned char c)
@@ -1393,9 +1394,9 @@ int repo_get_oid_mb(struct repository *r, const char *str, struct object_id *oid
 void maybe_die_on_misspelt_object_name(struct repository *repo,
                                       const char *name,
                                       const char *prefix);
-extern enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
-                               unsigned flags, struct object_id *oid,
-                               struct object_context *oc);
+enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
+                                        unsigned flags, struct object_id *oid,
+                                        struct object_context *oc);
 
 #define get_oid(str, oid)              repo_get_oid(the_repository, str, oid)
 #define get_oid_commit(str, oid)       repo_get_oid_commit(the_repository, str, oid)
@@ -1409,7 +1410,7 @@ typedef int each_abbrev_fn(const struct object_id *oid, void *);
 int repo_for_each_abbrev(struct repository *r, const char *prefix, each_abbrev_fn, void *);
 #define for_each_abbrev(prefix, fn, data) repo_for_each_abbrev(the_repository, prefix, fn, data)
 
-extern int set_disambiguate_hint_config(const char *var, const char *value);
+int set_disambiguate_hint_config(const char *var, const char *value);
 
 /*
  * Try to read a SHA1 in hexadecimal format from the 40 characters
@@ -1418,15 +1419,15 @@ extern int set_disambiguate_hint_config(const char *var, const char *value);
  * input, so it is safe to pass this function an arbitrary
  * null-terminated string.
  */
-extern int get_sha1_hex(const char *hex, unsigned char *sha1);
-extern int get_oid_hex(const char *hex, struct object_id *sha1);
+int get_sha1_hex(const char *hex, unsigned char *sha1);
+int get_oid_hex(const char *hex, struct object_id *sha1);
 
 /*
  * Read `len` pairs of hexadecimal digits from `hex` and write the
  * values to `binary` as `len` bytes. Return 0 on success, or -1 if
  * the input does not consist of hex digits).
  */
-extern int hex_to_bytes(unsigned char *binary, const char *hex, size_t len);
+int hex_to_bytes(unsigned char *binary, const char *hex, size_t len);
 
 /*
  * Convert a binary hash to its hex equivalent. The `_r` variant is reentrant,
@@ -1454,7 +1455,7 @@ char *oid_to_hex(const struct object_id *oid);                                            /* same static buffer */
  * other invalid character.  end is only updated on success; otherwise, it is
  * unmodified.
  */
-extern int parse_oid_hex(const char *hex, struct object_id *oid, const char **end);
+int parse_oid_hex(const char *hex, struct object_id *oid, const char **end);
 
 /*
  * This reads short-hand syntax that not only evaluates to a commit
@@ -1492,17 +1493,17 @@ int repo_interpret_branch_name(struct repository *r,
 #define interpret_branch_name(str, len, buf, allowed) \
        repo_interpret_branch_name(the_repository, str, len, buf, allowed)
 
-extern int validate_headref(const char *ref);
+int validate_headref(const char *ref);
 
-extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);
-extern int df_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);
-extern int name_compare(const char *name1, size_t len1, const char *name2, size_t len2);
-extern int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2);
+int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);
+int df_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);
+int name_compare(const char *name1, size_t len1, const char *name2, size_t len2);
+int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2);
 
-extern void *read_object_with_reference(const struct object_id *oid,
-                                       const char *required_type,
-                                       unsigned long *size,
-                                       struct object_id *oid_ret);
+void *read_object_with_reference(const struct object_id *oid,
+                                const char *required_type,
+                                unsigned long *size,
+                                struct object_id *oid_ret);
 
 struct object *repo_peel_to_type(struct repository *r,
                                 const char *name, int namelen,
@@ -1562,24 +1563,24 @@ enum want_ident {
        WANT_COMMITTER_IDENT
 };
 
-extern const char *git_author_info(int);
-extern const char *git_committer_info(int);
-extern const char *fmt_ident(const char *name, const char *email,
-               enum want_ident whose_ident,
-               const char *date_str, int);
-extern const char *fmt_name(enum want_ident);
-extern const char *ident_default_name(void);
-extern const char *ident_default_email(void);
-extern const char *git_editor(void);
-extern const char *git_sequence_editor(void);
-extern const char *git_pager(int stdout_is_tty);
-extern int is_terminal_dumb(void);
-extern int git_ident_config(const char *, const char *, void *);
+const char *git_author_info(int);
+const char *git_committer_info(int);
+const char *fmt_ident(const char *name, const char *email,
+                     enum want_ident whose_ident,
+                     const char *date_str, int);
+const char *fmt_name(enum want_ident);
+const char *ident_default_name(void);
+const char *ident_default_email(void);
+const char *git_editor(void);
+const char *git_sequence_editor(void);
+const char *git_pager(int stdout_is_tty);
+int is_terminal_dumb(void);
+int git_ident_config(const char *, const char *, void *);
 /*
  * Prepare an ident to fall back on if the user didn't configure it.
  */
 void prepare_fallback_ident(const char *name, const char *email);
-extern void reset_ident_date(void);
+void reset_ident_date(void);
 
 struct ident_split {
        const char *name_begin;
@@ -1595,7 +1596,7 @@ struct ident_split {
  * Signals an success with 0, but time part of the result may be NULL
  * if the input lacks timestamp and zone
  */
-extern int split_ident_line(struct ident_split *, const char *, int);
+int split_ident_line(struct ident_split *, const char *, int);
 
 /*
  * Like show_date, but pull the timestamp and tz parameters from
@@ -1612,7 +1613,7 @@ const char *show_ident_date(const struct ident_split *id,
  * Because there are two fields, we must choose one as the primary key; we
  * currently arbitrarily pick the email.
  */
-extern int ident_cmp(const struct ident_split *, const struct ident_split *);
+int ident_cmp(const struct ident_split *, const struct ident_split *);
 
 struct checkout {
        struct index_state *istate;
@@ -1628,14 +1629,14 @@ struct checkout {
 #define CHECKOUT_INIT { NULL, "" }
 
 #define TEMPORARY_FILENAME_LENGTH 25
-extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath, int *nr_checkouts);
-extern void enable_delayed_checkout(struct checkout *state);
-extern int finish_delayed_checkout(struct checkout *state, int *nr_checkouts);
+int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath, int *nr_checkouts);
+void enable_delayed_checkout(struct checkout *state);
+int finish_delayed_checkout(struct checkout *state, int *nr_checkouts);
 /*
  * Unlink the last component and schedule the leading directories for
  * removal, such that empty directories get removed.
  */
-extern void unlink_entry(const struct cache_entry *ce);
+void unlink_entry(const struct cache_entry *ce);
 
 struct cache_def {
        struct strbuf path;
@@ -1649,12 +1650,12 @@ static inline void cache_def_clear(struct cache_def *cache)
        strbuf_release(&cache->path);
 }
 
-extern int has_symlink_leading_path(const char *name, int len);
-extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
-extern int check_leading_path(const char *name, int len);
-extern int has_dirs_only_path(const char *name, int len, int prefix_len);
-extern void schedule_dir_for_removal(const char *name, int len);
-extern void remove_scheduled_dirs(void);
+int has_symlink_leading_path(const char *name, int len);
+int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
+int check_leading_path(const char *name, int len);
+int has_dirs_only_path(const char *name, int len, int prefix_len);
+void schedule_dir_for_removal(const char *name, int len);
+void remove_scheduled_dirs(void);
 
 struct pack_window {
        struct pack_window *next;
@@ -1676,14 +1677,14 @@ struct pack_entry {
  * usual "XXXXXX" trailer, and the resulting filename is written into the
  * "template" buffer. Returns the open descriptor.
  */
-extern int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);
+int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);
 
 /*
  * Create a pack .keep file named "name" (which should generally be the output
  * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on
  * error.
  */
-extern int odb_pack_keep(const char *name);
+int odb_pack_keep(const char *name);
 
 /*
  * Set this to 0 to prevent oid_object_info_extended() from fetching missing
@@ -1694,10 +1695,10 @@ extern int odb_pack_keep(const char *name);
 extern int fetch_if_missing;
 
 /* Dumb servers support */
-extern int update_server_info(int);
+int update_server_info(int);
 
-extern const char *get_log_output_encoding(void);
-extern const char *get_commit_output_encoding(void);
+const char *get_log_output_encoding(void);
+const char *get_commit_output_encoding(void);
 
 /*
  * This is a hack for test programs like test-dump-untracked-cache to
@@ -1706,8 +1707,8 @@ extern const char *get_commit_output_encoding(void);
  */
 extern int ignore_untracked_cache_config;
 
-extern int committer_ident_sufficiently_given(void);
-extern int author_ident_sufficiently_given(void);
+int committer_ident_sufficiently_given(void);
+int author_ident_sufficiently_given(void);
 
 extern const char *git_commit_encoding;
 extern const char *git_log_output_encoding;
@@ -1715,22 +1716,22 @@ extern const char *git_mailmap_file;
 extern const char *git_mailmap_blob;
 
 /* IO helper functions */
-extern void maybe_flush_or_die(FILE *, const char *);
+void maybe_flush_or_die(FILE *, const char *);
 __attribute__((format (printf, 2, 3)))
-extern void fprintf_or_die(FILE *, const char *fmt, ...);
+void fprintf_or_die(FILE *, const char *fmt, ...);
 
 #define COPY_READ_ERROR (-2)
 #define COPY_WRITE_ERROR (-3)
-extern int copy_fd(int ifd, int ofd);
-extern int copy_file(const char *dst, const char *src, int mode);
-extern int copy_file_with_time(const char *dst, const char *src, int mode);
+int copy_fd(int ifd, int ofd);
+int copy_file(const char *dst, const char *src, int mode);
+int copy_file_with_time(const char *dst, const char *src, int mode);
 
-extern void write_or_die(int fd, const void *buf, size_t count);
-extern void fsync_or_die(int fd, const char *);
+void write_or_die(int fd, const void *buf, size_t count);
+void fsync_or_die(int fd, const char *);
 
-extern ssize_t read_in_full(int fd, void *buf, size_t count);
-extern ssize_t write_in_full(int fd, const void *buf, size_t count);
-extern ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
+ssize_t read_in_full(int fd, void *buf, size_t count);
+ssize_t write_in_full(int fd, const void *buf, size_t count);
+ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
 
 static inline ssize_t write_str_in_full(int fd, const char *str)
 {
@@ -1741,7 +1742,7 @@ static inline ssize_t write_str_in_full(int fd, const char *str)
  * Open (and truncate) the file at path, write the contents of buf to it,
  * and close it. Dies if any errors are encountered.
  */
-extern void write_file_buf(const char *path, const char *buf, size_t len);
+void write_file_buf(const char *path, const char *buf, size_t len);
 
 /**
  * Like write_file_buf(), but format the contents into a buffer first.
@@ -1751,16 +1752,16 @@ extern void write_file_buf(const char *path, const char *buf, size_t len);
  *   write_file(path, "counter: %d", ctr);
  */
 __attribute__((format (printf, 2, 3)))
-extern void write_file(const char *path, const char *fmt, ...);
+void write_file(const char *path, const char *fmt, ...);
 
 /* pager.c */
-extern void setup_pager(void);
-extern int pager_in_use(void);
+void setup_pager(void);
+int pager_in_use(void);
 extern int pager_use_color;
-extern int term_columns(void);
-extern int decimal_width(uintmax_t);
-extern int check_pager_config(const char *cmd);
-extern void prepare_pager_args(struct child_process *, const char *pager);
+int term_columns(void);
+int decimal_width(uintmax_t);
+int check_pager_config(const char *cmd);
+void prepare_pager_args(struct child_process *, const char *pager);
 
 extern const char *editor_program;
 extern const char *askpass_program;
@@ -1804,13 +1805,13 @@ void shift_tree_by(const struct object_id *, const struct object_id *, struct ob
 /* All WS_* -- when extended, adapt diff.c emit_symbol */
 #define WS_RULE_MASK           07777
 extern unsigned whitespace_rule_cfg;
-extern unsigned whitespace_rule(struct index_state *, const char *);
-extern unsigned parse_whitespace_rule(const char *);
-extern unsigned ws_check(const char *line, int len, unsigned ws_rule);
-extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
-extern char *whitespace_error_string(unsigned ws);
-extern void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
-extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
+unsigned whitespace_rule(struct index_state *, const char *);
+unsigned parse_whitespace_rule(const char *);
+unsigned ws_check(const char *line, int len, unsigned ws_rule);
+void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
+char *whitespace_error_string(unsigned ws);
+void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
+int ws_blank_line(const char *line, int len, unsigned ws_rule);
 #define ws_tab_width(rule)     ((rule) & WS_TAB_WIDTH_MASK)
 
 /* ls-files */
@@ -1880,9 +1881,9 @@ void safe_create_dir(const char *dir, int share);
  * Should we print an ellipsis after an abbreviated SHA-1 value
  * when doing diff-raw output or indicating a detached HEAD?
  */
-extern int print_sha1_ellipsis(void);
+int print_sha1_ellipsis(void);
 
 /* Return 1 if the file is empty or does not exists, 0 otherwise. */
-extern int is_empty_or_missing_file(const char *filename);
+int is_empty_or_missing_file(const char *filename);
 
 #endif /* CACHE_H */
index 6b2073310c4a6a735a557ab0883c7bb045c2c458..1152133bd77a773f40afd6c3477224e051318e0c 100644 (file)
@@ -8,8 +8,8 @@
  * tracking branch.  Return the name of the remote if such a branch
  * exists, NULL otherwise.
  */
-extern const char *unique_tracking_name(const char *name,
-                                       struct object_id *oid,
-                                       int *dwim_remotes_matched);
+const char *unique_tracking_name(const char *name,
+                                struct object_id *oid,
+                                int *dwim_remotes_matched);
 
 #endif /* CHECKOUT_H */
index 52a44c690a7a38850e77eb1525e6f8c56e782369..7f6acdd803c33bc43200804ecec5d99f6d404224 100755 (executable)
@@ -12,7 +12,7 @@ case "$jobname" in
 linux-clang|linux-gcc)
        sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
        sudo apt-get -q update
-       sudo apt-get -q -y install language-pack-is git-svn apache2
+       sudo apt-get -q -y install language-pack-is libsvn-perl apache2
        case "$jobname" in
        linux-gcc)
                sudo apt-get -q -y install gcc-8
index 2567a5cf4dff99bcaf0e507168e1d4cbaba05bce..448c7440b3f0eb6a3c7e86fb775e3506b079b452 100644 (file)
--- a/column.h
+++ b/column.h
@@ -27,20 +27,20 @@ struct column_options {
 };
 
 struct option;
-extern int parseopt_column_callback(const struct option *, const char *, int);
-extern int git_column_config(const char *var, const char *value,
-                            const char *command, unsigned int *colopts);
-extern int finalize_colopts(unsigned int *colopts, int stdout_is_tty);
+int parseopt_column_callback(const struct option *, const char *, int);
+int git_column_config(const char *var, const char *value,
+                     const char *command, unsigned int *colopts);
+int finalize_colopts(unsigned int *colopts, int stdout_is_tty);
 static inline int column_active(unsigned int colopts)
 {
        return (colopts & COL_ENABLE_MASK) == COL_ENABLED;
 }
 
 struct string_list;
-extern void print_columns(const struct string_list *list, unsigned int colopts,
-                         const struct column_options *opts);
+void print_columns(const struct string_list *list, unsigned int colopts,
+                  const struct column_options *opts);
 
-extern int run_column_filter(int colopts, const struct column_options *);
-extern int stop_column_filter(void);
+int run_column_filter(int colopts, const struct column_options *);
+int stop_column_filter(void);
 
 #endif
index 7bcc9bb7e0f9965a2ab3176c0416943430c6a6aa..7c5e54875fdacdf77235a077c9928f7d3bf0d001 100644 (file)
@@ -267,8 +267,10 @@ struct commit_graph *parse_commit_graph(void *graph_map, int fd,
                last_chunk_offset = chunk_offset;
        }
 
-       if (verify_commit_graph_lite(graph))
+       if (verify_commit_graph_lite(graph)) {
+               free(graph);
                return NULL;
+       }
 
        return graph;
 }
index cc19cb53148ecdd6ce39d6836d8d52cbc0db5042..f5295ca7f3efe9b7665d1c6728814bfe2901d059 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -184,10 +184,10 @@ void free_commit_list(struct commit_list *list);
 
 struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
 
-extern int has_non_ascii(const char *text);
-extern const char *logmsg_reencode(const struct commit *commit,
-                                  char **commit_encoding,
-                                  const char *output_encoding);
+int has_non_ascii(const char *text);
+const char *logmsg_reencode(const struct commit *commit,
+                           char **commit_encoding,
+                           const char *output_encoding);
 const char *repo_logmsg_reencode(struct repository *r,
                                 const struct commit *commit,
                                 char **commit_encoding,
@@ -196,7 +196,7 @@ const char *repo_logmsg_reencode(struct repository *r,
 #define logmsg_reencode(c, enc, out) repo_logmsg_reencode(the_repository, c, enc, out)
 #endif
 
-extern const char *skip_blank_lines(const char *msg);
+const char *skip_blank_lines(const char *msg);
 
 /** Removes the first commit from a list sorted by date, and adds all
  * of its parents.
@@ -247,22 +247,22 @@ struct commit *get_fork_point(const char *refname, struct commit *commit);
 
 struct oid_array;
 struct ref;
-extern int register_shallow(struct repository *r, const struct object_id *oid);
-extern int unregister_shallow(const struct object_id *oid);
-extern int for_each_commit_graft(each_commit_graft_fn, void *);
-extern int is_repository_shallow(struct repository *r);
-extern struct commit_list *get_shallow_commits(struct object_array *heads,
-               int depth, int shallow_flag, int not_shallow_flag);
-extern struct commit_list *get_shallow_commits_by_rev_list(
+int register_shallow(struct repository *r, const struct object_id *oid);
+int unregister_shallow(const struct object_id *oid);
+int for_each_commit_graft(each_commit_graft_fn, void *);
+int is_repository_shallow(struct repository *r);
+struct commit_list *get_shallow_commits(struct object_array *heads,
+                                       int depth, int shallow_flag, int not_shallow_flag);
+struct commit_list *get_shallow_commits_by_rev_list(
                int ac, const char **av, int shallow_flag, int not_shallow_flag);
-extern void set_alternate_shallow_file(struct repository *r, const char *path, int override);
-extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
-                                const struct oid_array *extra);
-extern void setup_alternate_shallow(struct lock_file *shallow_lock,
-                                   const char **alternate_shallow_file,
-                                   const struct oid_array *extra);
-extern const char *setup_temporary_shallow(const struct oid_array *extra);
-extern void advertise_shallow_grafts(int);
+void set_alternate_shallow_file(struct repository *r, const char *path, int override);
+int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
+                         const struct oid_array *extra);
+void setup_alternate_shallow(struct lock_file *shallow_lock,
+                            const char **alternate_shallow_file,
+                            const struct oid_array *extra);
+const char *setup_temporary_shallow(const struct oid_array *extra);
+void advertise_shallow_grafts(int);
 
 /*
  * Initialize with prepare_shallow_info() or zero-initialize (equivalent to
@@ -283,21 +283,21 @@ struct shallow_info {
        int nr_commits;
 };
 
-extern void prepare_shallow_info(struct shallow_info *, struct oid_array *);
-extern void clear_shallow_info(struct shallow_info *);
-extern void remove_nonexistent_theirs_shallow(struct shallow_info *);
-extern void assign_shallow_commits_to_refs(struct shallow_info *info,
-                                          uint32_t **used,
-                                          int *ref_status);
-extern int delayed_reachability_test(struct shallow_info *si, int c);
+void prepare_shallow_info(struct shallow_info *, struct oid_array *);
+void clear_shallow_info(struct shallow_info *);
+void remove_nonexistent_theirs_shallow(struct shallow_info *);
+void assign_shallow_commits_to_refs(struct shallow_info *info,
+                                   uint32_t **used,
+                                   int *ref_status);
+int delayed_reachability_test(struct shallow_info *si, int c);
 #define PRUNE_SHOW_ONLY 1
 #define PRUNE_QUICK 2
-extern void prune_shallow(unsigned options);
+void prune_shallow(unsigned options);
 extern struct trace_key trace_shallow;
 
-extern int interactive_add(int argc, const char **argv, const char *prefix, int patch);
-extern int run_add_interactive(const char *revision, const char *patch_mode,
-                              const struct pathspec *pathspec);
+int interactive_add(int argc, const char **argv, const char *prefix, int patch);
+int run_add_interactive(const char *revision, const char *patch_mode,
+                       const struct pathspec *pathspec);
 
 struct commit_extra_header {
        struct commit_extra_header *next;
@@ -306,24 +306,24 @@ struct commit_extra_header {
        size_t len;
 };
 
-extern void append_merge_tag_headers(struct commit_list *parents,
-                                    struct commit_extra_header ***tail);
+void append_merge_tag_headers(struct commit_list *parents,
+                             struct commit_extra_header ***tail);
 
-extern int commit_tree(const char *msg, size_t msg_len,
-                      const struct object_id *tree,
-                      struct commit_list *parents, struct object_id *ret,
-                      const char *author, const char *sign_commit);
+int commit_tree(const char *msg, size_t msg_len,
+               const struct object_id *tree,
+               struct commit_list *parents, struct object_id *ret,
+               const char *author, const char *sign_commit);
 
-extern int commit_tree_extended(const char *msg, size_t msg_len,
-                               const struct object_id *tree,
-                               struct commit_list *parents,
-                               struct object_id *ret, const char *author,
-                               const char *sign_commit,
-                               struct commit_extra_header *);
+int commit_tree_extended(const char *msg, size_t msg_len,
+                        const struct object_id *tree,
+                        struct commit_list *parents,
+                        struct object_id *ret, const char *author,
+                        const char *sign_commit,
+                        struct commit_extra_header *);
 
-extern struct commit_extra_header *read_commit_extra_headers(struct commit *, const char **);
+struct commit_extra_header *read_commit_extra_headers(struct commit *, const char **);
 
-extern void free_commit_extra_headers(struct commit_extra_header *extra);
+void free_commit_extra_headers(struct commit_extra_header *extra);
 
 /*
  * Search the commit object contents given by "msg" for the header "key".
@@ -333,24 +333,24 @@ extern void free_commit_extra_headers(struct commit_extra_header *extra);
  * Note that some headers (like mergetag) may be multi-line. It is the caller's
  * responsibility to parse further in this case!
  */
-extern const char *find_commit_header(const char *msg, const char *key,
-                                     size_t *out_len);
+const char *find_commit_header(const char *msg, const char *key,
+                              size_t *out_len);
 
 /* Find the end of the log message, the right place for a new trailer. */
-extern size_t ignore_non_trailer(const char *buf, size_t len);
+size_t ignore_non_trailer(const char *buf, size_t len);
 
 typedef int (*each_mergetag_fn)(struct commit *commit, struct commit_extra_header *extra,
-                                void *cb_data);
+                               void *cb_data);
 
-extern int for_each_mergetag(each_mergetag_fn fn, struct commit *commit, void *data);
+int for_each_mergetag(each_mergetag_fn fn, struct commit *commit, void *data);
 
 struct merge_remote_desc {
        struct object *obj; /* the named object, could be a tag */
        char name[FLEX_ARRAY];
 };
-extern struct merge_remote_desc *merge_remote_util(struct commit *);
-extern void set_merge_remote_desc(struct commit *commit,
-                                 const char *name, struct object *obj);
+struct merge_remote_desc *merge_remote_util(struct commit *);
+void set_merge_remote_desc(struct commit *commit,
+                          const char *name, struct object *obj);
 
 /*
  * Given "name" from the command line to merge, find the commit object
@@ -359,9 +359,9 @@ extern void set_merge_remote_desc(struct commit *commit,
  */
 struct commit *get_merge_parent(const char *name);
 
-extern int parse_signed_commit(const struct commit *commit,
-                              struct strbuf *message, struct strbuf *signature);
-extern int remove_signature(struct strbuf *buf);
+int parse_signed_commit(const struct commit *commit,
+                       struct strbuf *message, struct strbuf *signature);
+int remove_signature(struct strbuf *buf);
 
 /*
  * Check the signature of the given commit. The result of the check is stored
@@ -370,7 +370,7 @@ extern int remove_signature(struct strbuf *buf);
  * at all.  This may allocate memory for sig->gpg_output, sig->gpg_status,
  * sig->signer and sig->key.
  */
-extern int check_commit_signature(const struct commit *commit, struct signature_check *sigc);
+int check_commit_signature(const struct commit *commit, struct signature_check *sigc);
 
 /* record author-date for each commit object */
 struct author_date_slab;
@@ -390,6 +390,6 @@ int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused)
 int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_, void *unused);
 
 LAST_ARG_MUST_BE_NULL
-extern int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...);
+int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...);
 
 #endif /* COMMIT_H */
index d484aec20979ac9a1ea6d49b166f51436a24dfad..582a7b18869fb80c94b3a0057e4cb9ced4c6f1c2 100644 (file)
@@ -27,6 +27,8 @@ int main(int argc, const char **argv)
 {
        int result;
 
+       trace2_initialize_clock();
+
        /*
         * Always open file descriptors 0/1/2 to avoid clobbering files
         * in die().  It also avoids messing up when the pipes are dup'ed
@@ -35,11 +37,11 @@ int main(int argc, const char **argv)
        sanitize_stdfds();
        restore_sigpipe_to_default();
 
+       git_resolve_executable_dir(argv[0]);
+
        trace2_initialize();
        trace2_cmd_start(argv);
-       trace2_collect_process_info();
-
-       git_resolve_executable_dir(argv[0]);
+       trace2_collect_process_info(TRACE2_PROCESS_INFO_STARTUP);
 
        git_setup_gettext();
 
diff --git a/compat/access.c b/compat/access.c
new file mode 100644 (file)
index 0000000..19fda3e
--- /dev/null
@@ -0,0 +1,31 @@
+#define COMPAT_CODE_ACCESS
+#include "../git-compat-util.h"
+
+/* Do the same thing access(2) does, but use the effective uid,
+ * and don't make the mistake of telling root that any file is
+ * executable.  This version uses stat(2).
+ */
+int git_access(const char *path, int mode)
+{
+       struct stat st;
+
+       /* do not interfere a normal user */
+       if (geteuid())
+               return access(path, mode);
+
+       if (stat(path, &st) < 0)
+               return -1;
+
+       /* Root can read or write any file. */
+       if (!(mode & X_OK))
+               return 0;
+
+       /* Root can execute any file that has any one of the execute
+        * bits set.
+        */
+       if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
+               return 0;
+
+       errno = EACCES;
+       return -1;
+}
index 7b105f4cd71a4ea4c1ae9f537ef0fe3eea7d9dc3..8e80ef335d84ecf5ccec6c5994e684c3951cca17 100644 (file)
@@ -1,4 +1,4 @@
-#define COMPAT_CODE
+#define COMPAT_CODE_FILENO
 #include "../git-compat-util.h"
 
 int git_fileno(FILE *stream)
index 6b04514cdc62167da027b48bae816e72811f1584..9b6d2400e1107fa2a65f6ecd7d067809115930b9 100644 (file)
@@ -1714,142 +1714,10 @@ int mingw_putenv(const char *namevalue)
        return result ? 0 : -1;
 }
 
-/*
- * Note, this isn't a complete replacement for getaddrinfo. It assumes
- * that service contains a numerical port, or that it is null. It
- * does a simple search using gethostbyname, and returns one IPv4 host
- * if one was found.
- */
-static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
-                                  const struct addrinfo *hints,
-                                  struct addrinfo **res)
-{
-       struct hostent *h = NULL;
-       struct addrinfo *ai;
-       struct sockaddr_in *sin;
-
-       if (node) {
-               h = gethostbyname(node);
-               if (!h)
-                       return WSAGetLastError();
-       }
-
-       ai = xmalloc(sizeof(struct addrinfo));
-       *res = ai;
-       ai->ai_flags = 0;
-       ai->ai_family = AF_INET;
-       ai->ai_socktype = hints ? hints->ai_socktype : 0;
-       switch (ai->ai_socktype) {
-       case SOCK_STREAM:
-               ai->ai_protocol = IPPROTO_TCP;
-               break;
-       case SOCK_DGRAM:
-               ai->ai_protocol = IPPROTO_UDP;
-               break;
-       default:
-               ai->ai_protocol = 0;
-               break;
-       }
-       ai->ai_addrlen = sizeof(struct sockaddr_in);
-       if (hints && (hints->ai_flags & AI_CANONNAME))
-               ai->ai_canonname = h ? xstrdup(h->h_name) : NULL;
-       else
-               ai->ai_canonname = NULL;
-
-       sin = xcalloc(1, ai->ai_addrlen);
-       sin->sin_family = AF_INET;
-       /* Note: getaddrinfo is supposed to allow service to be a string,
-        * which should be looked up using getservbyname. This is
-        * currently not implemented */
-       if (service)
-               sin->sin_port = htons(atoi(service));
-       if (h)
-               sin->sin_addr = *(struct in_addr *)h->h_addr;
-       else if (hints && (hints->ai_flags & AI_PASSIVE))
-               sin->sin_addr.s_addr = INADDR_ANY;
-       else
-               sin->sin_addr.s_addr = INADDR_LOOPBACK;
-       ai->ai_addr = (struct sockaddr *)sin;
-       ai->ai_next = NULL;
-       return 0;
-}
-
-static void WSAAPI freeaddrinfo_stub(struct addrinfo *res)
-{
-       free(res->ai_canonname);
-       free(res->ai_addr);
-       free(res);
-}
-
-static int WSAAPI getnameinfo_stub(const struct sockaddr *sa, socklen_t salen,
-                                  char *host, DWORD hostlen,
-                                  char *serv, DWORD servlen, int flags)
-{
-       const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
-       if (sa->sa_family != AF_INET)
-               return EAI_FAMILY;
-       if (!host && !serv)
-               return EAI_NONAME;
-
-       if (host && hostlen > 0) {
-               struct hostent *ent = NULL;
-               if (!(flags & NI_NUMERICHOST))
-                       ent = gethostbyaddr((const char *)&sin->sin_addr,
-                                           sizeof(sin->sin_addr), AF_INET);
-
-               if (ent)
-                       snprintf(host, hostlen, "%s", ent->h_name);
-               else if (flags & NI_NAMEREQD)
-                       return EAI_NONAME;
-               else
-                       snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr));
-       }
-
-       if (serv && servlen > 0) {
-               struct servent *ent = NULL;
-               if (!(flags & NI_NUMERICSERV))
-                       ent = getservbyport(sin->sin_port,
-                                           flags & NI_DGRAM ? "udp" : "tcp");
-
-               if (ent)
-                       snprintf(serv, servlen, "%s", ent->s_name);
-               else
-                       snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
-       }
-
-       return 0;
-}
-
-static HMODULE ipv6_dll = NULL;
-static void (WSAAPI *ipv6_freeaddrinfo)(struct addrinfo *res);
-static int (WSAAPI *ipv6_getaddrinfo)(const char *node, const char *service,
-                                     const struct addrinfo *hints,
-                                     struct addrinfo **res);
-static int (WSAAPI *ipv6_getnameinfo)(const struct sockaddr *sa, socklen_t salen,
-                                     char *host, DWORD hostlen,
-                                     char *serv, DWORD servlen, int flags);
-/*
- * gai_strerror is an inline function in the ws2tcpip.h header, so we
- * don't need to try to load that one dynamically.
- */
-
-static void socket_cleanup(void)
-{
-       WSACleanup();
-       if (ipv6_dll)
-               FreeLibrary(ipv6_dll);
-       ipv6_dll = NULL;
-       ipv6_freeaddrinfo = freeaddrinfo_stub;
-       ipv6_getaddrinfo = getaddrinfo_stub;
-       ipv6_getnameinfo = getnameinfo_stub;
-}
-
 static void ensure_socket_initialization(void)
 {
        WSADATA wsa;
        static int initialized = 0;
-       const char *libraries[] = { "ws2_32.dll", "wship6.dll", NULL };
-       const char **name;
 
        if (initialized)
                return;
@@ -1858,35 +1726,7 @@ static void ensure_socket_initialization(void)
                die("unable to initialize winsock subsystem, error %d",
                        WSAGetLastError());
 
-       for (name = libraries; *name; name++) {
-               ipv6_dll = LoadLibraryExA(*name, NULL,
-                                         LOAD_LIBRARY_SEARCH_SYSTEM32);
-               if (!ipv6_dll)
-                       continue;
-
-               ipv6_freeaddrinfo = (void (WSAAPI *)(struct addrinfo *))
-                       GetProcAddress(ipv6_dll, "freeaddrinfo");
-               ipv6_getaddrinfo = (int (WSAAPI *)(const char *, const char *,
-                                                  const struct addrinfo *,
-                                                  struct addrinfo **))
-                       GetProcAddress(ipv6_dll, "getaddrinfo");
-               ipv6_getnameinfo = (int (WSAAPI *)(const struct sockaddr *,
-                                                  socklen_t, char *, DWORD,
-                                                  char *, DWORD, int))
-                       GetProcAddress(ipv6_dll, "getnameinfo");
-               if (!ipv6_freeaddrinfo || !ipv6_getaddrinfo || !ipv6_getnameinfo) {
-                       FreeLibrary(ipv6_dll);
-                       ipv6_dll = NULL;
-               } else
-                       break;
-       }
-       if (!ipv6_freeaddrinfo || !ipv6_getaddrinfo || !ipv6_getnameinfo) {
-               ipv6_freeaddrinfo = freeaddrinfo_stub;
-               ipv6_getaddrinfo = getaddrinfo_stub;
-               ipv6_getnameinfo = getnameinfo_stub;
-       }
-
-       atexit(socket_cleanup);
+       atexit((void(*)(void)) WSACleanup);
        initialized = 1;
 }
 
@@ -1904,24 +1744,12 @@ struct hostent *mingw_gethostbyname(const char *host)
        return gethostbyname(host);
 }
 
-void mingw_freeaddrinfo(struct addrinfo *res)
-{
-       ipv6_freeaddrinfo(res);
-}
-
+#undef getaddrinfo
 int mingw_getaddrinfo(const char *node, const char *service,
                      const struct addrinfo *hints, struct addrinfo **res)
 {
        ensure_socket_initialization();
-       return ipv6_getaddrinfo(node, service, hints, res);
-}
-
-int mingw_getnameinfo(const struct sockaddr *sa, socklen_t salen,
-                     char *host, DWORD hostlen, char *serv, DWORD servlen,
-                     int flags)
-{
-       ensure_socket_initialization();
-       return ipv6_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+       return getaddrinfo(node, service, hints, res);
 }
 
 int mingw_socket(int domain, int type, int protocol)
@@ -2569,6 +2397,8 @@ void mingw_startup(void)
        wchar_t **wenv, **wargv;
        _startupinfo si;
 
+       trace2_initialize_clock();
+
        maybe_redirect_std_handles();
 
        /* get wide char arguments and environment */
index 4d73f8aa9d0d0937b1fcbe8d854485327fc3896c..593bdbffe68060e3cfd73fc8e3b2b0ffbc5faf64 100644 (file)
@@ -295,18 +295,10 @@ int mingw_gethostname(char *host, int namelen);
 struct hostent *mingw_gethostbyname(const char *host);
 #define gethostbyname mingw_gethostbyname
 
-void mingw_freeaddrinfo(struct addrinfo *res);
-#define freeaddrinfo mingw_freeaddrinfo
-
 int mingw_getaddrinfo(const char *node, const char *service,
                      const struct addrinfo *hints, struct addrinfo **res);
 #define getaddrinfo mingw_getaddrinfo
 
-int mingw_getnameinfo(const struct sockaddr *sa, socklen_t salen,
-                     char *host, DWORD hostlen, char *serv, DWORD servlen,
-                     int flags);
-#define getnameinfo mingw_getnameinfo
-
 int mingw_socket(int domain, int type, int protocol);
 #define socket mingw_socket
 
index 52bd62034ba3fd47f6832961cb7d768af45212cf..8ccbd1c2c6f82d68e0c39f8ec77aa2bd4a899f2e 100644 (file)
@@ -1,5 +1,6 @@
 #include "../../cache.h"
 #include "../../json-writer.h"
+#include "lazyload.h"
 #include <Psapi.h>
 #include <tlHelp32.h>
 
@@ -137,11 +138,54 @@ static void get_is_being_debugged(void)
                                   "windows/debugger_present", 1);
 }
 
-void trace2_collect_process_info(void)
+/*
+ * Emit JSON data with the peak memory usage of the current process.
+ */
+static void get_peak_memory_info(void)
+{
+       DECLARE_PROC_ADDR(psapi.dll, BOOL, GetProcessMemoryInfo, HANDLE,
+                         PPROCESS_MEMORY_COUNTERS, DWORD);
+
+       if (INIT_PROC_ADDR(GetProcessMemoryInfo)) {
+               PROCESS_MEMORY_COUNTERS pmc;
+
+               if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc,
+                                        sizeof(pmc))) {
+                       struct json_writer jw = JSON_WRITER_INIT;
+
+                       jw_object_begin(&jw, 0);
+
+#define KV(kv) #kv, (intmax_t)pmc.kv
+
+                       jw_object_intmax(&jw, KV(PageFaultCount));
+                       jw_object_intmax(&jw, KV(PeakWorkingSetSize));
+                       jw_object_intmax(&jw, KV(PeakPagefileUsage));
+
+                       jw_end(&jw);
+
+                       trace2_data_json("process", the_repository,
+                                        "windows/memory", &jw);
+                       jw_release(&jw);
+               }
+       }
+}
+
+void trace2_collect_process_info(enum trace2_process_info_reason reason)
 {
        if (!trace2_is_enabled())
                return;
 
-       get_is_being_debugged();
-       get_ancestry();
+       switch (reason) {
+       case TRACE2_PROCESS_INFO_STARTUP:
+               get_is_being_debugged();
+               get_ancestry();
+               return;
+
+       case TRACE2_PROCESS_INFO_EXIT:
+               get_peak_memory_info();
+               return;
+
+       default:
+               BUG("trace2_collect_process_info: unknown reason '%d'", reason);
+       }
 }
index c2846df3f1d3be68b376ea154e2607726f32d01c..296a6d9cc4110bd7fcef542ac9cc9cfe04d4f4d4 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1676,7 +1676,9 @@ static int do_git_config_sequence(const struct config_options *opts,
                repo_config = NULL;
 
        current_parsing_scope = CONFIG_SCOPE_SYSTEM;
-       if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0))
+       if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK,
+                                                 opts->system_gently ?
+                                                 ACCESS_EACCES_OK : 0))
                ret += git_config_from_file(fn, git_etc_gitconfig(),
                                            data);
 
@@ -1688,14 +1690,15 @@ static int do_git_config_sequence(const struct config_options *opts,
                ret += git_config_from_file(fn, user_config, data);
 
        current_parsing_scope = CONFIG_SCOPE_REPO;
-       if (repo_config && !access_or_die(repo_config, R_OK, 0))
+       if (!opts->ignore_repo && repo_config &&
+           !access_or_die(repo_config, R_OK, 0))
                ret += git_config_from_file(fn, repo_config, data);
 
        /*
         * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
         * But let's not complicate things before it's actually needed.
         */
-       if (repository_format_worktree_config) {
+       if (!opts->ignore_worktree && repository_format_worktree_config) {
                char *path = git_pathdup("config.worktree");
                if (!access_or_die(path, R_OK, 0))
                        ret += git_config_from_file(fn, path, data);
@@ -1703,7 +1706,7 @@ static int do_git_config_sequence(const struct config_options *opts,
        }
 
        current_parsing_scope = CONFIG_SCOPE_CMDLINE;
-       if (git_config_from_parameters(fn, data) < 0)
+       if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
                die(_("unable to parse command-line config"));
 
        current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
@@ -1794,6 +1797,23 @@ void read_early_config(config_fn_t cb, void *data)
        strbuf_release(&gitdir);
 }
 
+/*
+ * Read config but only enumerate system and global settings.
+ * Omit any repo-local, worktree-local, or command-line settings.
+ */
+void read_very_early_config(config_fn_t cb, void *data)
+{
+       struct config_options opts = { 0 };
+
+       opts.respect_includes = 1;
+       opts.ignore_repo = 1;
+       opts.ignore_worktree = 1;
+       opts.ignore_cmdline = 1;
+       opts.system_gently = 1;
+
+       config_with_options(cb, data, NULL, &opts);
+}
+
 static struct config_set_element *configset_find_element(struct config_set *cs, const char *key)
 {
        struct config_set_element k;
@@ -2011,7 +2031,7 @@ int git_configset_get_pathname(struct config_set *cs, const char *key, const cha
 /* Functions use to read configuration from a repository */
 static void repo_read_config(struct repository *repo)
 {
-       struct config_options opts;
+       struct config_options opts = { 0 };
 
        opts.respect_includes = 1;
        opts.commondir = repo->commondir;
index ee5d3fa7b4264f24e8b36c2e1154546ae626c191..f0ed464004da601a26d574b1cdc158abb50ae2bc 100644 (file)
--- a/config.h
+++ b/config.h
@@ -55,6 +55,10 @@ typedef int (*config_parser_event_fn_t)(enum config_event_t type,
 
 struct config_options {
        unsigned int respect_includes : 1;
+       unsigned int ignore_repo : 1;
+       unsigned int ignore_worktree : 1;
+       unsigned int ignore_cmdline : 1;
+       unsigned int system_gently : 1;
        const char *commondir;
        const char *git_dir;
        config_parser_event_fn_t event_fn;
@@ -68,62 +72,63 @@ struct config_options {
 };
 
 typedef int (*config_fn_t)(const char *, const char *, void *);
-extern int git_default_config(const char *, const char *, void *);
-extern int git_config_from_file(config_fn_t fn, const char *, void *);
-extern int git_config_from_file_with_options(config_fn_t fn, const char *,
-                                            void *,
-                                            const struct config_options *);
-extern int git_config_from_mem(config_fn_t fn,
-                              const enum config_origin_type,
-                              const char *name,
-                              const char *buf, size_t len,
-                              void *data, const struct config_options *opts);
-extern int git_config_from_blob_oid(config_fn_t fn, const char *name,
-                                   const struct object_id *oid, void *data);
-extern void git_config_push_parameter(const char *text);
-extern int git_config_from_parameters(config_fn_t fn, void *data);
-extern void read_early_config(config_fn_t cb, void *data);
-extern void git_config(config_fn_t fn, void *);
-extern int config_with_options(config_fn_t fn, void *,
-                              struct git_config_source *config_source,
-                              const struct config_options *opts);
-extern int git_parse_ssize_t(const char *, ssize_t *);
-extern int git_parse_ulong(const char *, unsigned long *);
-extern int git_parse_maybe_bool(const char *);
-extern int git_config_int(const char *, const char *);
-extern int64_t git_config_int64(const char *, const char *);
-extern unsigned long git_config_ulong(const char *, const char *);
-extern ssize_t git_config_ssize_t(const char *, const char *);
-extern int git_config_bool_or_int(const char *, const char *, int *);
-extern int git_config_bool(const char *, const char *);
-extern int git_config_string(const char **, const char *, const char *);
-extern int git_config_pathname(const char **, const char *, const char *);
-extern int git_config_expiry_date(timestamp_t *, const char *, const char *);
-extern int git_config_color(char *, const char *, const char *);
-extern int git_config_set_in_file_gently(const char *, const char *, const char *);
-extern void git_config_set_in_file(const char *, const char *, const char *);
-extern int git_config_set_gently(const char *, const char *);
-extern void git_config_set(const char *, const char *);
-extern int git_config_parse_key(const char *, char **, int *);
-extern int git_config_key_is_valid(const char *key);
-extern int git_config_set_multivar_gently(const char *, const char *, const char *, int);
-extern void git_config_set_multivar(const char *, const char *, const char *, int);
-extern int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, int);
-extern void git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
-extern int git_config_rename_section(const char *, const char *);
-extern int git_config_rename_section_in_file(const char *, const char *, const char *);
-extern int git_config_copy_section(const char *, const char *);
-extern int git_config_copy_section_in_file(const char *, const char *, const char *);
-extern const char *git_etc_gitconfig(void);
-extern int git_env_bool(const char *, int);
-extern unsigned long git_env_ulong(const char *, unsigned long);
-extern int git_config_system(void);
-extern int config_error_nonbool(const char *);
+int git_default_config(const char *, const char *, void *);
+int git_config_from_file(config_fn_t fn, const char *, void *);
+int git_config_from_file_with_options(config_fn_t fn, const char *,
+                                     void *,
+                                     const struct config_options *);
+int git_config_from_mem(config_fn_t fn,
+                       const enum config_origin_type,
+                       const char *name,
+                       const char *buf, size_t len,
+                       void *data, const struct config_options *opts);
+int git_config_from_blob_oid(config_fn_t fn, const char *name,
+                            const struct object_id *oid, void *data);
+void git_config_push_parameter(const char *text);
+int git_config_from_parameters(config_fn_t fn, void *data);
+void read_early_config(config_fn_t cb, void *data);
+void read_very_early_config(config_fn_t cb, void *data);
+void git_config(config_fn_t fn, void *);
+int config_with_options(config_fn_t fn, void *,
+                       struct git_config_source *config_source,
+                       const struct config_options *opts);
+int git_parse_ssize_t(const char *, ssize_t *);
+int git_parse_ulong(const char *, unsigned long *);
+int git_parse_maybe_bool(const char *);
+int git_config_int(const char *, const char *);
+int64_t git_config_int64(const char *, const char *);
+unsigned long git_config_ulong(const char *, const char *);
+ssize_t git_config_ssize_t(const char *, const char *);
+int git_config_bool_or_int(const char *, const char *, int *);
+int git_config_bool(const char *, const char *);
+int git_config_string(const char **, const char *, const char *);
+int git_config_pathname(const char **, const char *, const char *);
+int git_config_expiry_date(timestamp_t *, const char *, const char *);
+int git_config_color(char *, const char *, const char *);
+int git_config_set_in_file_gently(const char *, const char *, const char *);
+void git_config_set_in_file(const char *, const char *, const char *);
+int git_config_set_gently(const char *, const char *);
+void git_config_set(const char *, const char *);
+int git_config_parse_key(const char *, char **, int *);
+int git_config_key_is_valid(const char *key);
+int git_config_set_multivar_gently(const char *, const char *, const char *, int);
+void git_config_set_multivar(const char *, const char *, const char *, int);
+int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, int);
+void git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
+int git_config_rename_section(const char *, const char *);
+int git_config_rename_section_in_file(const char *, const char *, const char *);
+int git_config_copy_section(const char *, const char *);
+int git_config_copy_section_in_file(const char *, const char *, const char *);
+const char *git_etc_gitconfig(void);
+int git_env_bool(const char *, int);
+unsigned long git_env_ulong(const char *, unsigned long);
+int git_config_system(void);
+int config_error_nonbool(const char *);
 #if defined(__GNUC__)
 #define config_error_nonbool(s) (config_error_nonbool(s), const_error())
 #endif
 
-extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
+int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 
 enum config_scope {
        CONFIG_SCOPE_UNKNOWN = 0,
@@ -133,9 +138,9 @@ enum config_scope {
        CONFIG_SCOPE_CMDLINE,
 };
 
-extern enum config_scope current_config_scope(void);
-extern const char *current_config_origin_type(void);
-extern const char *current_config_name(void);
+enum config_scope current_config_scope(void);
+const char *current_config_origin_type(void);
+const char *current_config_name(void);
 
 struct config_include_data {
        int depth;
@@ -144,7 +149,7 @@ struct config_include_data {
        const struct config_options *opts;
 };
 #define CONFIG_INCLUDE_INIT { 0 }
-extern int git_config_include(const char *name, const char *value, void *data);
+int git_config_include(const char *name, const char *value, void *data);
 
 /*
  * Match and parse a config key of the form:
@@ -159,10 +164,10 @@ extern int git_config_include(const char *name, const char *value, void *data);
  * If the subsection pointer-to-pointer passed in is NULL, returns 0 only if
  * there is no subsection at all.
  */
-extern int parse_config_key(const char *var,
-                           const char *section,
-                           const char **subsection, int *subsection_len,
-                           const char **key);
+int parse_config_key(const char *var,
+                    const char *section,
+                    const char **subsection, int *subsection_len,
+                    const char **key);
 
 struct config_set_element {
        struct hashmap_entry ent;
@@ -192,71 +197,71 @@ struct config_set {
        struct configset_list list;
 };
 
-extern void git_configset_init(struct config_set *cs);
-extern int git_configset_add_file(struct config_set *cs, const char *filename);
-extern const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);
-extern void git_configset_clear(struct config_set *cs);
+void git_configset_init(struct config_set *cs);
+int git_configset_add_file(struct config_set *cs, const char *filename);
+const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);
+void git_configset_clear(struct config_set *cs);
 
 /*
  * These functions return 1 if not found, and 0 if found, leaving the found
  * value in the 'dest' pointer.
  */
-extern int git_configset_get_value(struct config_set *cs, const char *key, const char **dest);
-extern int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest);
-extern int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
-extern int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
-extern int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest);
-extern int git_configset_get_bool(struct config_set *cs, const char *key, int *dest);
-extern int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *is_bool, int *dest);
-extern int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);
-extern int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest);
+int git_configset_get_value(struct config_set *cs, const char *key, const char **dest);
+int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest);
+int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
+int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
+int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest);
+int git_configset_get_bool(struct config_set *cs, const char *key, int *dest);
+int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *is_bool, int *dest);
+int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);
+int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest);
 
 /* Functions for reading a repository's config */
 struct repository;
-extern void repo_config(struct repository *repo, config_fn_t fn, void *data);
-extern int repo_config_get_value(struct repository *repo,
-                                const char *key, const char **value);
-extern const struct string_list *repo_config_get_value_multi(struct repository *repo,
-                                                            const char *key);
-extern int repo_config_get_string_const(struct repository *repo,
-                                       const char *key, const char **dest);
-extern int repo_config_get_string(struct repository *repo,
-                                 const char *key, char **dest);
-extern int repo_config_get_int(struct repository *repo,
+void repo_config(struct repository *repo, config_fn_t fn, void *data);
+int repo_config_get_value(struct repository *repo,
+                         const char *key, const char **value);
+const struct string_list *repo_config_get_value_multi(struct repository *repo,
+                                                     const char *key);
+int repo_config_get_string_const(struct repository *repo,
+                                const char *key, const char **dest);
+int repo_config_get_string(struct repository *repo,
+                          const char *key, char **dest);
+int repo_config_get_int(struct repository *repo,
+                       const char *key, int *dest);
+int repo_config_get_ulong(struct repository *repo,
+                         const char *key, unsigned long *dest);
+int repo_config_get_bool(struct repository *repo,
+                        const char *key, int *dest);
+int repo_config_get_bool_or_int(struct repository *repo,
+                               const char *key, int *is_bool, int *dest);
+int repo_config_get_maybe_bool(struct repository *repo,
                               const char *key, int *dest);
-extern int repo_config_get_ulong(struct repository *repo,
-                                const char *key, unsigned long *dest);
-extern int repo_config_get_bool(struct repository *repo,
-                               const char *key, int *dest);
-extern int repo_config_get_bool_or_int(struct repository *repo,
-                                      const char *key, int *is_bool, int *dest);
-extern int repo_config_get_maybe_bool(struct repository *repo,
-                                     const char *key, int *dest);
-extern int repo_config_get_pathname(struct repository *repo,
-                                   const char *key, const char **dest);
+int repo_config_get_pathname(struct repository *repo,
+                            const char *key, const char **dest);
 
-extern int git_config_get_value(const char *key, const char **value);
-extern const struct string_list *git_config_get_value_multi(const char *key);
-extern void git_config_clear(void);
-extern int git_config_get_string_const(const char *key, const char **dest);
-extern int git_config_get_string(const char *key, char **dest);
-extern int git_config_get_int(const char *key, int *dest);
-extern int git_config_get_ulong(const char *key, unsigned long *dest);
-extern int git_config_get_bool(const char *key, int *dest);
-extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
-extern int git_config_get_maybe_bool(const char *key, int *dest);
-extern int git_config_get_pathname(const char *key, const char **dest);
-extern int git_config_get_index_threads(int *dest);
-extern int git_config_get_untracked_cache(void);
-extern int git_config_get_split_index(void);
-extern int git_config_get_max_percent_split_change(void);
-extern int git_config_get_fsmonitor(void);
+int git_config_get_value(const char *key, const char **value);
+const struct string_list *git_config_get_value_multi(const char *key);
+void git_config_clear(void);
+int git_config_get_string_const(const char *key, const char **dest);
+int git_config_get_string(const char *key, char **dest);
+int git_config_get_int(const char *key, int *dest);
+int git_config_get_ulong(const char *key, unsigned long *dest);
+int git_config_get_bool(const char *key, int *dest);
+int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
+int git_config_get_maybe_bool(const char *key, int *dest);
+int git_config_get_pathname(const char *key, const char **dest);
+int git_config_get_index_threads(int *dest);
+int git_config_get_untracked_cache(void);
+int git_config_get_split_index(void);
+int git_config_get_max_percent_split_change(void);
+int git_config_get_fsmonitor(void);
 
 /* This dies if the configured or default date is in the future */
-extern int git_config_get_expiry(const char *key, const char **output);
+int git_config_get_expiry(const char *key, const char **output);
 
 /* parse either "this many days" integer, or "5.days.ago" approxidate */
-extern int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now);
+int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now);
 
 struct key_value_info {
        const char *filename;
@@ -265,8 +270,8 @@ struct key_value_info {
        enum config_scope scope;
 };
 
-extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
-extern NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr);
+NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
+NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr);
 
 #define LOOKUP_CONFIG(mapping, var) \
        lookup_config(mapping, ARRAY_SIZE(mapping), var)
index d916d1dc7ab90d954dcd25f89d09f7478053112a..b71688eeb73f10da004f3d16e3de9afd13eb9c7e 100644 (file)
@@ -272,6 +272,7 @@ ifeq ($(uname_S),AIX)
        NEEDS_LIBICONV = YesPlease
        BASIC_CFLAGS += -D_LARGE_FILES
        FILENO_IS_A_MACRO = UnfortunatelyYes
+       NEED_ACCESS_ROOT_HANDLER = UnfortunatelyYes
        ifeq ($(shell expr "$(uname_V)" : '[1234]'),1)
                NO_PTHREADS = YesPlease
        else
@@ -575,13 +576,21 @@ else
        ifneq ($(shell expr "$(uname_R)" : '1\.'),2)
                # MSys2
                prefix = /usr/
+               # Enable DEP
+               BASIC_LDFLAGS += -Wl,--nxcompat
+               # Enable ASLR (unless debugging)
+               ifneq (,$(findstring -O,$(filter-out -O0 -Og,$(CFLAGS))))
+                       BASIC_LDFLAGS += -Wl,--dynamicbase
+               endif
                ifeq (MINGW32,$(MSYSTEM))
                        prefix = /mingw32
                        HOST_CPU = i686
+                       BASIC_LDFLAGS += -Wl,--pic-executable,-e,_mainCRTStartup
                endif
                ifeq (MINGW64,$(MSYSTEM))
                        prefix = /mingw64
                        HOST_CPU = x86_64
+                       BASIC_LDFLAGS += -Wl,--pic-executable,-e,mainCRTStartup
                else
                        COMPAT_CFLAGS += -D_USE_32BIT_TIME_T
                        BASIC_LDFLAGS += -Wl,--large-address-aware
index 32aff60979512b7f1382482435a26c51882b9f16..5f2382e01868042757901a419b5e5f34ad8bb279 100644 (file)
--- a/connect.h
+++ b/connect.h
@@ -7,19 +7,19 @@
 #define CONNECT_DIAG_URL      (1u << 1)
 #define CONNECT_IPV4          (1u << 2)
 #define CONNECT_IPV6          (1u << 3)
-extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
-extern int finish_connect(struct child_process *conn);
-extern int git_connection_is_socket(struct child_process *conn);
-extern int server_supports(const char *feature);
-extern int parse_feature_request(const char *features, const char *feature);
-extern const char *server_feature_value(const char *feature, int *len_ret);
-extern int url_is_local_not_ssh(const char *url);
+struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
+int finish_connect(struct child_process *conn);
+int git_connection_is_socket(struct child_process *conn);
+int server_supports(const char *feature);
+int parse_feature_request(const char *features, const char *feature);
+const char *server_feature_value(const char *feature, int *len_ret);
+int url_is_local_not_ssh(const char *url);
 
 struct packet_reader;
-extern enum protocol_version discover_version(struct packet_reader *reader);
+enum protocol_version discover_version(struct packet_reader *reader);
 
-extern int server_supports_v2(const char *c, int die_on_error);
-extern int server_supports_feature(const char *c, const char *feature,
-                                  int die_on_error);
+int server_supports_v2(const char *c, int die_on_error);
+int server_supports_feature(const char *c, const char *feature,
+                           int die_on_error);
 
 #endif
index 1bba888eff90a23e586807fd02b274b8e7fac097..1ab481fed69b33b48bd95c282d2c0faff897123c 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "object-store.h"
 #include "run-command.h"
 #include "sigchain.h"
 #include "connected.h"
@@ -49,6 +50,22 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
                strbuf_release(&idx_file);
        }
 
+       if (opt->check_refs_only) {
+               /*
+                * For partial clones, we don't want to have to do a regular
+                * connectivity check because we have to enumerate and exclude
+                * all promisor objects (slow), and then the connectivity check
+                * itself becomes a no-op because in a partial clone every
+                * object is a promisor object. Instead, just make sure we
+                * received the objects pointed to by each wanted ref.
+                */
+               do {
+                       if (!repo_has_object_file(the_repository, &oid))
+                               return 1;
+               } while (!fn(cb_data, &oid));
+               return 0;
+       }
+
        if (opt->shallow_file) {
                argv_array_push(&rev_list.args, "--shallow-file");
                argv_array_push(&rev_list.args, opt->shallow_file);
index 8d5a6b3ad6fe4bb0f9ca0930f8eea82543968306..ce2e7d8f2e535aac72fb317448ad20fb2133429b 100644 (file)
@@ -46,6 +46,14 @@ struct check_connected_options {
         * during a fetch.
         */
        unsigned is_deepening_fetch : 1;
+
+       /*
+        * If non-zero, only check the top-level objects referenced by the
+        * wanted refs (passed in as cb_data). This is useful for partial
+        * clones, where enumerating and excluding all promisor objects is very
+        * slow and the commit-walk itself becomes a no-op.
+        */
+       unsigned check_refs_only : 1;
 };
 
 #define CHECK_CONNECTED_INIT { 0 }
index 536754583b59945e984ad487b6e524e5d1de7056..7440aa1c4638103c952c225f2c9b77d8c9451b08 100644 (file)
@@ -4,6 +4,11 @@ package DiffHighlight;
 use warnings FATAL => 'all';
 use strict;
 
+# Use the correct value for both UNIX and Windows (/dev/null vs nul)
+use File::Spec;
+
+my $NULL = File::Spec->devnull();
+
 # Highlight by reversing foreground and background. You could do
 # other things like bold or underline if you prefer.
 my @OLD_HIGHLIGHT = (
@@ -134,7 +139,7 @@ sub highlight_stdin {
 # fallback, which means we will work even if git can't be run.
 sub color_config {
        my ($key, $default) = @_;
-       my $s = `git config --get-color $key 2>/dev/null`;
+       my $s = `git config --get-color $key 2>$NULL`;
        return length($s) ? $s : $default;
 }
 
index 3bf7184736365c2034b6851ca4a1f3c9d052cb42..a98b1eee53f40367ad06c7aa82da7af0ca6ed6bc 100644 (file)
@@ -25,22 +25,22 @@ struct hashfile_checkpoint {
        git_hash_ctx ctx;
 };
 
-extern void hashfile_checkpoint(struct hashfile *, struct hashfile_checkpoint *);
-extern int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);
+void hashfile_checkpoint(struct hashfile *, struct hashfile_checkpoint *);
+int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);
 
 /* finalize_hashfile flags */
 #define CSUM_CLOSE             1
 #define CSUM_FSYNC             2
 #define CSUM_HASH_IN_STREAM    4
 
-extern struct hashfile *hashfd(int fd, const char *name);
-extern struct hashfile *hashfd_check(const char *name);
-extern struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);
-extern int finalize_hashfile(struct hashfile *, unsigned char *, unsigned int);
-extern void hashwrite(struct hashfile *, const void *, unsigned int);
-extern void hashflush(struct hashfile *f);
-extern void crc32_begin(struct hashfile *);
-extern uint32_t crc32_end(struct hashfile *);
+struct hashfile *hashfd(int fd, const char *name);
+struct hashfile *hashfd_check(const char *name);
+struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);
+int finalize_hashfile(struct hashfile *, unsigned char *, unsigned int);
+void hashwrite(struct hashfile *, const void *, unsigned int);
+void hashflush(struct hashfile *f);
+void crc32_begin(struct hashfile *);
+uint32_t crc32_end(struct hashfile *);
 
 static inline void hashwrite_u8(struct hashfile *f, uint8_t data)
 {
index 9014c1e996c60d9b3e1bd27ffa01b9c2d0c8ae80..ee43dee1f008882094ca9c85f6b28b86ec88fdf6 100644 (file)
@@ -50,12 +50,12 @@ struct decoration {
  * NULL), returning the previously associated pointer. If there is no previous
  * association, this function returns NULL.
  */
-extern void *add_decoration(struct decoration *n, const struct object *obj, void *decoration);
+void *add_decoration(struct decoration *n, const struct object *obj, void *decoration);
 
 /*
  * Return the pointer associated to the given object. If there is no
  * association, this function returns NULL.
  */
-extern void *lookup_decoration(struct decoration *n, const struct object *obj);
+void *lookup_decoration(struct decoration *n, const struct object *obj);
 
 #endif
diff --git a/delta.h b/delta.h
index 9b67531dfa4e6511d0c7a4d6d400a3d3719603bc..2df5fe13d954dfad4c6b1e80be7b45b281d7ef6d 100644 (file)
--- a/delta.h
+++ b/delta.h
@@ -13,7 +13,7 @@ struct delta_index;
  * before free_delta_index() is called.  The returned pointer must be freed
  * using free_delta_index().
  */
-extern struct delta_index *
+struct delta_index *
 create_delta_index(const void *buf, unsigned long bufsize);
 
 /*
@@ -21,14 +21,14 @@ create_delta_index(const void *buf, unsigned long bufsize);
  *
  * Given pointer must be what create_delta_index() returned, or NULL.
  */
-extern void free_delta_index(struct delta_index *index);
+void free_delta_index(struct delta_index *index);
 
 /*
  * sizeof_delta_index: returns memory usage of delta index
  *
  * Given pointer must be what create_delta_index() returned, or NULL.
  */
-extern unsigned long sizeof_delta_index(struct delta_index *index);
+unsigned long sizeof_delta_index(struct delta_index *index);
 
 /*
  * create_delta: create a delta from given index for the given buffer
@@ -40,7 +40,7 @@ extern unsigned long sizeof_delta_index(struct delta_index *index);
  * returned and *delta_size is updated with its size.  The returned buffer
  * must be freed by the caller.
  */
-extern void *
+void *
 create_delta(const struct delta_index *index,
             const void *buf, unsigned long bufsize,
             unsigned long *delta_size, unsigned long max_delta_size);
@@ -75,9 +75,9 @@ diff_delta(const void *src_buf, unsigned long src_bufsize,
  * *trg_bufsize is updated with its size.  On failure a NULL pointer is
  * returned.  The returned buffer must be freed by the caller.
  */
-extern void *patch_delta(const void *src_buf, unsigned long src_size,
-                        const void *delta_buf, unsigned long delta_size,
-                        unsigned long *dst_size);
+void *patch_delta(const void *src_buf, unsigned long src_size,
+                 const void *delta_buf, unsigned long delta_size,
+                 unsigned long *dst_size);
 
 /* the smallest possible delta size is 4 bytes */
 #define DELTA_SIZE_MIN 4
diff --git a/dir.h b/dir.h
index c23313b02126f97e63e5694bdc02907363fe077d..680079bbe3241ff84fc8260009515f03b6ba819e 100644 (file)
--- a/dir.h
+++ b/dir.h
@@ -202,7 +202,7 @@ struct dir_struct {
 };
 
 /*Count the number of slashes for string s*/
-extern int count_slashes(const char *s);
+int count_slashes(const char *s);
 
 /*
  * The ordering of these constants is significant, with
@@ -213,27 +213,27 @@ extern int count_slashes(const char *s);
 #define MATCHED_RECURSIVELY 1
 #define MATCHED_FNMATCH 2
 #define MATCHED_EXACTLY 3
-extern int simple_length(const char *match);
-extern int no_wildcard(const char *string);
-extern char *common_prefix(const struct pathspec *pathspec);
-extern int match_pathspec(const struct index_state *istate,
-                         const struct pathspec *pathspec,
-                         const char *name, int namelen,
-                         int prefix, char *seen, int is_dir);
-extern int report_path_error(const char *ps_matched, const struct pathspec *pathspec);
-extern int within_depth(const char *name, int namelen, int depth, int max_depth);
-
-extern int fill_directory(struct dir_struct *dir,
-                         struct index_state *istate,
-                         const struct pathspec *pathspec);
-extern int read_directory(struct dir_struct *, struct index_state *istate,
-                         const char *path, int len,
-                         const struct pathspec *pathspec);
-
-extern int is_excluded_from_list(const char *pathname, int pathlen,
-                                const char *basename, int *dtype,
-                                struct exclude_list *el,
-                                struct index_state *istate);
+int simple_length(const char *match);
+int no_wildcard(const char *string);
+char *common_prefix(const struct pathspec *pathspec);
+int match_pathspec(const struct index_state *istate,
+                  const struct pathspec *pathspec,
+                  const char *name, int namelen,
+                  int prefix, char *seen, int is_dir);
+int report_path_error(const char *ps_matched, const struct pathspec *pathspec);
+int within_depth(const char *name, int namelen, int depth, int max_depth);
+
+int fill_directory(struct dir_struct *dir,
+                  struct index_state *istate,
+                  const struct pathspec *pathspec);
+int read_directory(struct dir_struct *, struct index_state *istate,
+                  const char *path, int len,
+                  const struct pathspec *pathspec);
+
+int is_excluded_from_list(const char *pathname, int pathlen,
+                         const char *basename, int *dtype,
+                         struct exclude_list *el,
+                         struct index_state *istate);
 struct dir_entry *dir_add_ignored(struct dir_struct *dir,
                                  struct index_state *istate,
                                  const char *pathname, int len);
@@ -242,39 +242,39 @@ struct dir_entry *dir_add_ignored(struct dir_struct *dir,
  * these implement the matching logic for dir.c:excluded_from_list and
  * attr.c:path_matches()
  */
-extern int match_basename(const char *, int,
-                         const char *, int, int, unsigned);
-extern int match_pathname(const char *, int,
-                         const char *, int,
-                         const char *, int, int, unsigned);
-
-extern struct exclude *last_exclude_matching(struct dir_struct *dir,
-                                            struct index_state *istate,
-                                            const char *name, int *dtype);
-
-extern int is_excluded(struct dir_struct *dir,
-                      struct index_state *istate,
-                      const char *name, int *dtype);
-
-extern struct exclude_list *add_exclude_list(struct dir_struct *dir,
-                                            int group_type, const char *src);
-extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
-                                         struct exclude_list *el, struct  index_state *istate);
-extern void add_excludes_from_file(struct dir_struct *, const char *fname);
-extern int add_excludes_from_blob_to_list(struct object_id *oid,
-                                         const char *base, int baselen,
-                                         struct exclude_list *el);
-extern void parse_exclude_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen);
-extern void add_exclude(const char *string, const char *base,
-                       int baselen, struct exclude_list *el, int srcpos);
-extern void clear_exclude_list(struct exclude_list *el);
-extern void clear_directory(struct dir_struct *dir);
+int match_basename(const char *, int,
+                  const char *, int, int, unsigned);
+int match_pathname(const char *, int,
+                  const char *, int,
+                  const char *, int, int, unsigned);
+
+struct exclude *last_exclude_matching(struct dir_struct *dir,
+                                     struct index_state *istate,
+                                     const char *name, int *dtype);
+
+int is_excluded(struct dir_struct *dir,
+               struct index_state *istate,
+               const char *name, int *dtype);
+
+struct exclude_list *add_exclude_list(struct dir_struct *dir,
+                                     int group_type, const char *src);
+int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
+                                  struct exclude_list *el, struct  index_state *istate);
+void add_excludes_from_file(struct dir_struct *, const char *fname);
+int add_excludes_from_blob_to_list(struct object_id *oid,
+                                  const char *base, int baselen,
+                                  struct exclude_list *el);
+void parse_exclude_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen);
+void add_exclude(const char *string, const char *base,
+                int baselen, struct exclude_list *el, int srcpos);
+void clear_exclude_list(struct exclude_list *el);
+void clear_directory(struct dir_struct *dir);
 
 int repo_file_exists(struct repository *repo, const char *path);
 int file_exists(const char *);
 
-extern int is_inside_dir(const char *dir);
-extern int dir_inside_of(const char *subdir, const char *dir);
+int is_inside_dir(const char *dir);
+int dir_inside_of(const char *subdir, const char *dir);
 
 static inline int is_dot_or_dotdot(const char *name)
 {
@@ -283,9 +283,9 @@ static inline int is_dot_or_dotdot(const char *name)
                 (name[1] == '.' && name[2] == '\0')));
 }
 
-extern int is_empty_dir(const char *dir);
+int is_empty_dir(const char *dir);
 
-extern void setup_standard_excludes(struct dir_struct *dir);
+void setup_standard_excludes(struct dir_struct *dir);
 
 
 /* Constants for remove_dir_recursively: */
@@ -313,26 +313,26 @@ extern void setup_standard_excludes(struct dir_struct *dir);
  * This function uses path as temporary scratch space, but restores it
  * before returning.
  */
-extern int remove_dir_recursively(struct strbuf *path, int flag);
+int remove_dir_recursively(struct strbuf *path, int flag);
 
 /* tries to remove the path with empty directories along it, ignores ENOENT */
-extern int remove_path(const char *path);
+int remove_path(const char *path);
 
-extern int fspathcmp(const char *a, const char *b);
-extern int fspathncmp(const char *a, const char *b, size_t count);
+int fspathcmp(const char *a, const char *b);
+int fspathncmp(const char *a, const char *b, size_t count);
 
 /*
  * The prefix part of pattern must not contains wildcards.
  */
 struct pathspec_item;
-extern int git_fnmatch(const struct pathspec_item *item,
-                      const char *pattern, const char *string,
-                      int prefix);
+int git_fnmatch(const struct pathspec_item *item,
+               const char *pattern, const char *string,
+               int prefix);
 
-extern int submodule_path_match(const struct index_state *istate,
-                               const struct pathspec *ps,
-                               const char *submodule_name,
-                               char *seen);
+int submodule_path_match(const struct index_state *istate,
+                        const struct pathspec *ps,
+                        const char *submodule_name,
+                        char *seen);
 
 static inline int ce_path_match(const struct index_state *istate,
                                const struct cache_entry *ce,
@@ -374,10 +374,10 @@ void remove_untracked_cache(struct index_state *istate);
  * When `recurse_into_nested` is set, recurse into any nested submodules,
  * connecting them as well.
  */
-extern void connect_work_tree_and_git_dir(const char *work_tree,
-                                         const char *git_dir,
-                                         int recurse_into_nested);
-extern void relocate_gitdir(const char *path,
-                           const char *old_git_dir,
-                           const char *new_git_dir);
+void connect_work_tree_and_git_dir(const char *work_tree,
+                                  const char *git_dir,
+                                  int recurse_into_nested);
+void relocate_gitdir(const char *path,
+                    const char *old_git_dir,
+                    const char *new_git_dir);
 #endif
index 2522453cdaa74d9e9d806f20036518a394dd32e2..8cd1df28d3f11d165bc91fc34c90fc94802c9f61 100644 (file)
@@ -3,14 +3,14 @@
 
 struct argv_array;
 
-extern void git_set_exec_path(const char *exec_path);
-extern void git_resolve_executable_dir(const char *path);
-extern const char *git_exec_path(void);
-extern void setup_path(void);
-extern const char **prepare_git_cmd(struct argv_array *out, const char **argv);
-extern int execv_git_cmd(const char **argv); /* NULL terminated */
+void git_set_exec_path(const char *exec_path);
+void git_resolve_executable_dir(const char *path);
+const char *git_exec_path(void);
+void setup_path(void);
+const char **prepare_git_cmd(struct argv_array *out, const char **argv);
+int execv_git_cmd(const char **argv); /* NULL terminated */
 LAST_ARG_MUST_BE_NULL
-extern int execl_git_cmd(const char *cmd, ...);
-extern char *system_path(const char *path);
+int execl_git_cmd(const char *cmd, ...);
+char *system_path(const char *path);
 
 #endif /* GIT_EXEC_CMD_H */
index b28d3a6113dc671884e95cbbc3904e4b2d26d727..01e3aa88c50c1994065a99515bd13f484558b553 100644 (file)
@@ -2,6 +2,6 @@
 #define FMT_MERGE_MSG_H
 
 extern int merge_log_config;
-extern int fmt_merge_msg_config(const char *key, const char *value, void *cb);
+int fmt_merge_msg_config(const char *key, const char *value, void *cb);
 
 #endif /* FMT_MERGE_MSG_H */
index 665bd2d4254b12edf38e94cb0e8b2200ae3bf34a..1dee0aded1c433c7cfb90195328f270559c9b421 100644 (file)
@@ -129,7 +129,6 @@ static void fsmonitor_refresh_callback(struct index_state *istate, const char *n
 
 void refresh_fsmonitor(struct index_state *istate)
 {
-       static int has_run_once = 0;
        struct strbuf query_result = STRBUF_INIT;
        int query_success = 0;
        size_t bol; /* beginning of line */
@@ -137,9 +136,9 @@ void refresh_fsmonitor(struct index_state *istate)
        char *buf;
        int i;
 
-       if (!core_fsmonitor || has_run_once)
+       if (!core_fsmonitor || istate->fsmonitor_has_run_once)
                return;
-       has_run_once = 1;
+       istate->fsmonitor_has_run_once = 1;
 
        trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");
        /*
index 01017c43aa68be952ec6b89530fb5aa85c8a098b..8489fa3244976bb3e489c030e726cf06f0e4e9b3 100644 (file)
@@ -10,31 +10,31 @@ extern struct trace_key trace_fsmonitor;
  * Read the fsmonitor index extension and (if configured) restore the
  * CE_FSMONITOR_VALID state.
  */
-extern int read_fsmonitor_extension(struct index_state *istate, const void *data, unsigned long sz);
+int read_fsmonitor_extension(struct index_state *istate, const void *data, unsigned long sz);
 
 /*
  * Fill the fsmonitor_dirty ewah bits with their state from the index,
  * before it is split during writing.
  */
-extern void fill_fsmonitor_bitmap(struct index_state *istate);
+void fill_fsmonitor_bitmap(struct index_state *istate);
 
 /*
  * Write the CE_FSMONITOR_VALID state into the fsmonitor index
  * extension.  Reads from the fsmonitor_dirty ewah in the index.
  */
-extern void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate);
+void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate);
 
 /*
  * Add/remove the fsmonitor index extension
  */
-extern void add_fsmonitor(struct index_state *istate);
-extern void remove_fsmonitor(struct index_state *istate);
+void add_fsmonitor(struct index_state *istate);
+void remove_fsmonitor(struct index_state *istate);
 
 /*
  * Add/remove the fsmonitor index extension as necessary based on the current
  * core.fsmonitor setting.
  */
-extern void tweak_fsmonitor(struct index_state *istate);
+void tweak_fsmonitor(struct index_state *istate);
 
 /*
  * Run the configured fsmonitor integration script and clear the
@@ -42,7 +42,7 @@ extern void tweak_fsmonitor(struct index_state *istate);
  * any corresponding untracked cache directory structures. Optimized to only
  * run the first time it is called.
  */
-extern void refresh_fsmonitor(struct index_state *istate);
+void refresh_fsmonitor(struct index_state *istate);
 
 /*
  * Set the given cache entries CE_FSMONITOR_VALID bit. This should be
index 71255e503eeb70e691e03ac1be0e2a249244a096..bee52eb11347da9336e9f1906f7973aa0e224d3b 100644 (file)
--- a/gettext.h
+++ b/gettext.h
 
 #define FORMAT_PRESERVING(n) __attribute__((format_arg(n)))
 
-extern int use_gettext_poison(void);
+int use_gettext_poison(void);
 
 #ifndef NO_GETTEXT
-extern void git_setup_gettext(void);
-extern int gettext_width(const char *s);
+void git_setup_gettext(void);
+int gettext_width(const char *s);
 #else
 static inline void git_setup_gettext(void)
 {
@@ -87,6 +87,6 @@ const char *Q_(const char *msgid, const char *plu, unsigned long n)
 #endif
 
 const char *get_preferred_languages(void);
-extern int is_utf8_locale(void);
+int is_utf8_locale(void);
 
 #endif
index 4386b3e1c874b587d1bbc0e99394d6c9c016830e..cc0e7e97334ec90a355f9c8eb088c6810a91193c 100644 (file)
@@ -250,7 +250,7 @@ typedef unsigned long uintptr_t;
 
 #ifdef MKDIR_WO_TRAILING_SLASH
 #define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
-extern int compat_mkdir_wo_trailing_slash(const char*, mode_t);
+int compat_mkdir_wo_trailing_slash(const char*, mode_t);
 #endif
 
 #ifdef NO_STRUCT_ITIMERVAL
@@ -268,9 +268,9 @@ struct itimerval {
 #include <libgen.h>
 #else
 #define basename gitbasename
-extern char *gitbasename(char *);
+char *gitbasename(char *);
 #define dirname gitdirname
-extern char *gitdirname(char *);
+char *gitdirname(char *);
 #endif
 
 #ifndef NO_ICONV
@@ -447,15 +447,15 @@ static inline char *git_find_last_dir_sep(const char *path)
 struct strbuf;
 
 /* General helper functions */
-extern void vreportf(const char *prefix, const char *err, va_list params);
-extern NORETURN void usage(const char *err);
-extern NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2)));
-extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
-extern NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
-extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
-extern int error_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
-extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
-extern void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
+void vreportf(const char *prefix, const char *err, va_list params);
+NORETURN void usage(const char *err);
+NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2)));
+NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
+NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
+int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
+int error_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
+void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
+void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
 
 #ifndef NO_OPENSSL
 #ifdef APPLE_COMMON_CRYPTO
@@ -483,15 +483,15 @@ static inline int const_error(void)
 #define error_errno(...) (error_errno(__VA_ARGS__), const_error())
 #endif
 
-extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
-extern void set_error_routine(void (*routine)(const char *err, va_list params));
+void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
+void set_error_routine(void (*routine)(const char *err, va_list params));
 extern void (*get_error_routine(void))(const char *err, va_list params);
-extern void set_warn_routine(void (*routine)(const char *warn, va_list params));
+void set_warn_routine(void (*routine)(const char *warn, va_list params));
 extern void (*get_warn_routine(void))(const char *warn, va_list params);
-extern void set_die_is_recursing_routine(int (*routine)(void));
+void set_die_is_recursing_routine(int (*routine)(void));
 
-extern int starts_with(const char *str, const char *prefix);
-extern int istarts_with(const char *str, const char *prefix);
+int starts_with(const char *str, const char *prefix);
+int istarts_with(const char *str, const char *prefix);
 
 /*
  * If the string "str" begins with the string found in "prefix", return 1.
@@ -614,8 +614,8 @@ static inline int ends_with(const char *str, const char *suffix)
 
 #define mmap git_mmap
 #define munmap git_munmap
-extern void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-extern int git_munmap(void *start, size_t length);
+void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+int git_munmap(void *start, size_t length);
 
 #else /* NO_MMAP || USE_WIN32_MMAP */
 
@@ -669,17 +669,17 @@ extern int git_munmap(void *start, size_t length);
 #undef stat
 #endif
 #define stat(path, buf) git_stat(path, buf)
-extern int git_stat(const char *, struct stat *);
+int git_stat(const char *, struct stat *);
 #ifdef fstat
 #undef fstat
 #endif
 #define fstat(fd, buf) git_fstat(fd, buf)
-extern int git_fstat(int, struct stat *);
+int git_fstat(int, struct stat *);
 #ifdef lstat
 #undef lstat
 #endif
 #define lstat(path, buf) git_lstat(path, buf)
-extern int git_lstat(const char *, struct stat *);
+int git_lstat(const char *, struct stat *);
 #endif
 
 #define DEFAULT_PACKED_GIT_LIMIT \
@@ -687,50 +687,50 @@ extern int git_lstat(const char *, struct stat *);
 
 #ifdef NO_PREAD
 #define pread git_pread
-extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
+ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
 #endif
 /*
  * Forward decl that will remind us if its twin in cache.h changes.
  * This function is used in compat/pread.c.  But we can't include
  * cache.h there.
  */
-extern ssize_t read_in_full(int fd, void *buf, size_t count);
+ssize_t read_in_full(int fd, void *buf, size_t count);
 
 #ifdef NO_SETENV
 #define setenv gitsetenv
-extern int gitsetenv(const char *, const char *, int);
+int gitsetenv(const char *, const char *, int);
 #endif
 
 #ifdef NO_MKDTEMP
 #define mkdtemp gitmkdtemp
-extern char *gitmkdtemp(char *);
+char *gitmkdtemp(char *);
 #endif
 
 #ifdef NO_UNSETENV
 #define unsetenv gitunsetenv
-extern void gitunsetenv(const char *);
+void gitunsetenv(const char *);
 #endif
 
 #ifdef NO_STRCASESTR
 #define strcasestr gitstrcasestr
-extern char *gitstrcasestr(const char *haystack, const char *needle);
+char *gitstrcasestr(const char *haystack, const char *needle);
 #endif
 
 #ifdef NO_STRLCPY
 #define strlcpy gitstrlcpy
-extern size_t gitstrlcpy(char *, const char *, size_t);
+size_t gitstrlcpy(char *, const char *, size_t);
 #endif
 
 #ifdef NO_STRTOUMAX
 #define strtoumax gitstrtoumax
-extern uintmax_t gitstrtoumax(const char *, char **, int);
+uintmax_t gitstrtoumax(const char *, char **, int);
 #define strtoimax gitstrtoimax
-extern intmax_t gitstrtoimax(const char *, char **, int);
+intmax_t gitstrtoimax(const char *, char **, int);
 #endif
 
 #ifdef NO_HSTRERROR
 #define hstrerror githstrerror
-extern const char *githstrerror(int herror);
+const char *githstrerror(int herror);
 #endif
 
 #ifdef NO_MEMMEM
@@ -762,7 +762,7 @@ char *gitstrdup(const char *s);
 #  endif
 #  define fopen(a,b) git_fopen(a,b)
 # endif
-extern FILE *git_fopen(const char*, const char*);
+FILE *git_fopen(const char*, const char*);
 #endif
 
 #ifdef SNPRINTF_RETURNS_BOGUS
@@ -770,14 +770,14 @@ extern FILE *git_fopen(const char*, const char*);
 #undef snprintf
 #endif
 #define snprintf git_snprintf
-extern int git_snprintf(char *str, size_t maxsize,
-                       const char *format, ...);
+int git_snprintf(char *str, size_t maxsize,
+                const char *format, ...);
 #ifdef vsnprintf
 #undef vsnprintf
 #endif
 #define vsnprintf git_vsnprintf
-extern int git_vsnprintf(char *str, size_t maxsize,
-                        const char *format, va_list ap);
+int git_vsnprintf(char *str, size_t maxsize,
+                 const char *format, va_list ap);
 #endif
 
 #ifdef __GLIBC_PREREQ
@@ -806,11 +806,11 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size);
 
 #ifdef NO_PTHREADS
 #define atexit git_atexit
-extern int git_atexit(void (*handler)(void));
+int git_atexit(void (*handler)(void));
 #endif
 
 typedef void (*try_to_free_t)(size_t);
-extern try_to_free_t set_try_to_free_routine(try_to_free_t);
+try_to_free_t set_try_to_free_routine(try_to_free_t);
 
 static inline size_t st_add(size_t a, size_t b)
 {
@@ -846,28 +846,28 @@ static inline size_t st_sub(size_t a, size_t b)
 # define xalloca(size)      (xmalloc(size))
 # define xalloca_free(p)    (free(p))
 #endif
-extern char *xstrdup(const char *str);
-extern void *xmalloc(size_t size);
-extern void *xmallocz(size_t size);
-extern void *xmallocz_gently(size_t size);
-extern void *xmemdupz(const void *data, size_t len);
-extern char *xstrndup(const char *str, size_t len);
-extern void *xrealloc(void *ptr, size_t size);
-extern void *xcalloc(size_t nmemb, size_t size);
-extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-extern void *xmmap_gently(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-extern int xopen(const char *path, int flags, ...);
-extern ssize_t xread(int fd, void *buf, size_t len);
-extern ssize_t xwrite(int fd, const void *buf, size_t len);
-extern ssize_t xpread(int fd, void *buf, size_t len, off_t offset);
-extern int xdup(int fd);
-extern FILE *xfopen(const char *path, const char *mode);
-extern FILE *xfdopen(int fd, const char *mode);
-extern int xmkstemp(char *temp_filename);
-extern int xmkstemp_mode(char *temp_filename, 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);
+char *xstrdup(const char *str);
+void *xmalloc(size_t size);
+void *xmallocz(size_t size);
+void *xmallocz_gently(size_t size);
+void *xmemdupz(const void *data, size_t len);
+char *xstrndup(const char *str, size_t len);
+void *xrealloc(void *ptr, size_t size);
+void *xcalloc(size_t nmemb, size_t size);
+void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+void *xmmap_gently(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+int xopen(const char *path, int flags, ...);
+ssize_t xread(int fd, void *buf, size_t len);
+ssize_t xwrite(int fd, const void *buf, size_t len);
+ssize_t xpread(int fd, void *buf, size_t len, off_t offset);
+int xdup(int fd);
+FILE *xfopen(const char *path, const char *mode);
+FILE *xfdopen(int fd, const char *mode);
+int xmkstemp(char *temp_filename);
+int xmkstemp_mode(char *temp_filename, int mode);
+char *xgetcwd(void);
+FILE *fopen_for_writing(const char *path);
+FILE *fopen_or_warn(const char *path, const char *mode);
 
 /*
  * FREE_AND_NULL(ptr) is like free(ptr) followed by ptr = NULL. Note
@@ -967,13 +967,13 @@ static inline size_t xsize_t(off_t len)
 }
 
 __attribute__((format (printf, 3, 4)))
-extern int xsnprintf(char *dst, size_t max, const char *fmt, ...);
+int xsnprintf(char *dst, size_t max, const char *fmt, ...);
 
 #ifndef HOST_NAME_MAX
 #define HOST_NAME_MAX 256
 #endif
 
-extern int xgethostname(char *buf, size_t len);
+int xgethostname(char *buf, size_t len);
 
 /* in ctype.c, for kwset users */
 extern const unsigned char tolower_trans_tbl[256];
@@ -1237,12 +1237,22 @@ struct tm *git_gmtime_r(const time_t *, struct tm *);
 
 #ifdef FILENO_IS_A_MACRO
 int git_fileno(FILE *stream);
-# ifndef COMPAT_CODE
+# ifndef COMPAT_CODE_FILENO
 #  undef fileno
 #  define fileno(p) git_fileno(p)
 # endif
 #endif
 
+#ifdef NEED_ACCESS_ROOT_HANDLER
+int git_access(const char *path, int mode);
+# ifndef COMPAT_CODE_ACCESS
+#  ifdef access
+#  undef access
+#  endif
+#  define access(path, mode) git_access(path, mode)
+# endif
+#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
@@ -1258,7 +1268,7 @@ static inline int is_missing_file_error(int errno_)
        return (errno_ == ENOENT || errno_ == ENOTDIR);
 }
 
-extern int cmd_main(int, const char **);
+int cmd_main(int, const char **);
 
 /*
  * Intercept all calls to exit() and route them to trace2 to
@@ -1281,7 +1291,7 @@ int trace2_cmd_exit_fl(const char *file, int line, int code);
  * an annotation, and does nothing in non-leak-checking builds.
  */
 #ifdef SUPPRESS_ANNOTATED_LEAKS
-extern void unleak_memory(const void *ptr, size_t len);
+void unleak_memory(const void *ptr, size_t len);
 #define UNLEAK(var) unleak_memory(&(var), sizeof(var))
 #else
 #define UNLEAK(var) do {} while (0)
index d13f02da95f3b9b3921c3ccff9e3b6a7511cd666..fc00d5946af68e536876d42a1463b21924edefa5 100755 (executable)
@@ -431,6 +431,7 @@ END
 sub safe_pipe_capture {
     my @output;
     if (my $pid = open my $child, '-|') {
+       binmode($child, ":crlf");
        @output = (<$child>);
        close $child or die join(' ',@_).": $! $?";
     } else {
index 7bfb6737dfe7be46f3f29903bef844c3c2b1be11..46af3e60b7185b2767accbee3420903edaf53d6f 100755 (executable)
@@ -71,7 +71,7 @@ then
        then
                merge_tool="$GIT_DIFF_TOOL"
        else
-               merge_tool="$(get_merge_tool)" || exit
+               merge_tool="$(get_merge_tool)"
        fi
 fi
 
index aaa4eed0bc7fc2c5706853d39e4644c9d31e1e0d..204a5acd66f5444412f0088b8df6cb0ae2fd6b41 100644 (file)
@@ -80,14 +80,18 @@ show_tool_names () {
        }
 }
 
-diff_mode() {
+diff_mode () {
        test "$TOOL_MODE" = diff
 }
 
-merge_mode() {
+merge_mode () {
        test "$TOOL_MODE" = merge
 }
 
+gui_mode () {
+       test "$GIT_MERGETOOL_GUI" = true
+}
+
 translate_merge_tool_path () {
        echo "$1"
 }
@@ -351,20 +355,36 @@ guess_merge_tool () {
 }
 
 get_configured_merge_tool () {
-       # If first argument is true, find the guitool instead
-       if test "$1" = true
-       then
-               gui_prefix=gui
-       fi
-
-       # Diff mode first tries diff.(gui)tool and falls back to merge.(gui)tool.
-       # Merge mode only checks merge.(gui)tool
+       keys=
        if diff_mode
        then
-               merge_tool=$(git config diff.${gui_prefix}tool || git config merge.${gui_prefix}tool)
+               if gui_mode
+               then
+                       keys="diff.guitool merge.guitool diff.tool merge.tool"
+               else
+                       keys="diff.tool merge.tool"
+               fi
        else
-               merge_tool=$(git config merge.${gui_prefix}tool)
+               if gui_mode
+               then
+                       keys="merge.guitool merge.tool"
+               else
+                       keys="merge.tool"
+               fi
        fi
+
+       merge_tool=$(
+               IFS=' '
+               for key in $keys
+               do
+                       selected=$(git config $key)
+                       if test -n "$selected"
+                       then
+                               echo "$selected"
+                               return
+                       fi
+               done)
+
        if test -n "$merge_tool" && ! valid_tool "$merge_tool"
        then
                echo >&2 "git config option $TOOL_MODE.${gui_prefix}tool set to unknown tool: $merge_tool"
@@ -404,14 +424,17 @@ get_merge_tool_path () {
 }
 
 get_merge_tool () {
+       is_guessed=false
        # Check if a merge tool has been configured
        merge_tool=$(get_configured_merge_tool)
        # Try to guess an appropriate merge tool if no tool has been set.
        if test -z "$merge_tool"
        then
                merge_tool=$(guess_merge_tool) || exit
+               is_guessed=true
        fi
        echo "$merge_tool"
+       test "$is_guessed" = false
 }
 
 mergetool_find_win32_cmd () {
index 01b9ad59b24ff77221d5db4118c9d0265dc25fad..88fa6a914a172877991ae9890cae1a42ca51fb89 100755 (executable)
@@ -389,7 +389,7 @@ print_noop_and_exit () {
 
 main () {
        prompt=$(git config --bool mergetool.prompt)
-       gui_tool=false
+       GIT_MERGETOOL_GUI=false
        guessed_merge_tool=false
        orderfile=
 
@@ -416,10 +416,10 @@ main () {
                        esac
                        ;;
                --no-gui)
-                       gui_tool=false
+                       GIT_MERGETOOL_GUI=false
                        ;;
                -g|--gui)
-                       gui_tool=true
+                       GIT_MERGETOOL_GUI=true
                        ;;
                -y|--no-prompt)
                        prompt=false
@@ -449,12 +449,8 @@ main () {
 
        if test -z "$merge_tool"
        then
-               # Check if a merge tool has been configured
-               merge_tool=$(get_configured_merge_tool $gui_tool)
-               # Try to guess an appropriate merge tool if no tool has been set.
-               if test -z "$merge_tool"
+               if ! merge_tool=$(get_merge_tool)
                then
-                       merge_tool=$(guess_merge_tool) || exit
                        guessed_merge_tool=true
                fi
        fi
diff --git a/grep.h b/grep.h
index fb0489372169d7f1563a09e050c8715542ce5963..1875880f37990f981865b0fab332cc6c6c4e5971 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -186,17 +186,17 @@ struct grep_opt {
        void *output_priv;
 };
 
-extern void init_grep_defaults(struct repository *);
-extern int grep_config(const char *var, const char *value, void *);
-extern void grep_init(struct grep_opt *, struct repository *repo, const char *prefix);
+void init_grep_defaults(struct repository *);
+int grep_config(const char *var, const char *value, void *);
+void grep_init(struct grep_opt *, struct repository *repo, const char *prefix);
 void grep_commit_pattern_type(enum grep_pattern_type, struct grep_opt *opt);
 
-extern void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t);
-extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
-extern void append_header_grep_pattern(struct grep_opt *, enum grep_header_field, const char *);
-extern void compile_grep_patterns(struct grep_opt *opt);
-extern void free_grep_patterns(struct grep_opt *opt);
-extern int grep_buffer(struct grep_opt *opt, char *buf, unsigned long size);
+void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t);
+void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
+void append_header_grep_pattern(struct grep_opt *, enum grep_header_field, const char *);
+void compile_grep_patterns(struct grep_opt *opt);
+void free_grep_patterns(struct grep_opt *opt);
+int grep_buffer(struct grep_opt *opt, char *buf, unsigned long size);
 
 struct grep_source {
        char *name;
@@ -226,8 +226,8 @@ void grep_source_load_driver(struct grep_source *gs,
 
 int grep_source(struct grep_opt *opt, struct grep_source *gs);
 
-extern struct grep_opt *grep_opt_dup(const struct grep_opt *opt);
-extern int grep_threads_ok(const struct grep_opt *opt);
+struct grep_opt *grep_opt_dup(const struct grep_opt *opt);
+int grep_threads_ok(const struct grep_opt *opt);
 
 /*
  * Mutex used around access to the attributes machinery if
index d375d9cce779952057e3c5dc6340edd12fb3f99d..f95593b6cfd7cecfbcc4584d74ac040cb355c767 100644 (file)
--- a/hashmap.h
+++ b/hashmap.h
  * `memihash_cont` is a variant of `memihash` that allows a computation to be
  * continued with another chunk of data.
  */
-extern unsigned int strhash(const char *buf);
-extern unsigned int strihash(const char *buf);
-extern unsigned int memhash(const void *buf, size_t len);
-extern unsigned int memihash(const void *buf, size_t len);
-extern unsigned int memihash_cont(unsigned int hash_seed, const void *buf, size_t len);
+unsigned int strhash(const char *buf);
+unsigned int strihash(const char *buf);
+unsigned int memhash(const void *buf, size_t len);
+unsigned int memihash(const void *buf, size_t len);
+unsigned int memihash_cont(unsigned int hash_seed, const void *buf, size_t len);
 
 /*
  * Converts a cryptographic hash (e.g. SHA-1) into an int-sized hash code
@@ -216,7 +216,7 @@ struct hashmap {
  * parameter may be used to preallocate a sufficiently large table and thus
  * prevent expensive resizing. If 0, the table is dynamically resized.
  */
-extern void hashmap_init(struct hashmap *map,
+void hashmap_init(struct hashmap *map,
                         hashmap_cmp_fn equals_function,
                         const void *equals_function_data,
                         size_t initial_size);
@@ -227,7 +227,7 @@ extern void hashmap_init(struct hashmap *map,
  * If `free_entries` is true, each hashmap_entry in the map is freed as well
  * using stdlibs free().
  */
-extern void hashmap_free(struct hashmap *map, int free_entries);
+void hashmap_free(struct hashmap *map, int free_entries);
 
 /* hashmap_entry functions */
 
@@ -284,7 +284,7 @@ static inline unsigned int hashmap_get_size(struct hashmap *map)
  * If an entry with matching hash code is found, `key` and `keydata` are passed
  * to `hashmap_cmp_fn` to decide whether the entry matches the key.
  */
-extern void *hashmap_get(const struct hashmap *map, const void *key,
+void *hashmap_get(const struct hashmap *map, const void *key,
                         const void *keydata);
 
 /*
@@ -316,7 +316,7 @@ static inline void *hashmap_get_from_hash(const struct hashmap *map,
  * `entry` is the hashmap_entry to start the search from, obtained via a previous
  * call to `hashmap_get` or `hashmap_get_next`.
  */
-extern void *hashmap_get_next(const struct hashmap *map, const void *entry);
+void *hashmap_get_next(const struct hashmap *map, const void *entry);
 
 /*
  * Adds a hashmap entry. This allows to add duplicate entries (i.e.
@@ -325,7 +325,7 @@ extern void *hashmap_get_next(const struct hashmap *map, const void *entry);
  * `map` is the hashmap structure.
  * `entry` is the entry to add.
  */
-extern void hashmap_add(struct hashmap *map, void *entry);
+void hashmap_add(struct hashmap *map, void *entry);
 
 /*
  * Adds or replaces a hashmap entry. If the hashmap contains duplicate
@@ -335,7 +335,7 @@ extern void hashmap_add(struct hashmap *map, void *entry);
  * `entry` is the entry to add or replace.
  * Returns the replaced entry, or NULL if not found (i.e. the entry was added).
  */
-extern void *hashmap_put(struct hashmap *map, void *entry);
+void *hashmap_put(struct hashmap *map, void *entry);
 
 /*
  * Removes a hashmap entry matching the specified key. If the hashmap contains
@@ -344,7 +344,7 @@ extern void *hashmap_put(struct hashmap *map, void *entry);
  *
  * Argument explanation is the same as in `hashmap_get`.
  */
-extern void *hashmap_remove(struct hashmap *map, const void *key,
+void *hashmap_remove(struct hashmap *map, const void *key,
                const void *keydata);
 
 /*
@@ -365,10 +365,10 @@ struct hashmap_iter {
 };
 
 /* Initializes a `hashmap_iter` structure. */
-extern void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter);
+void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter);
 
 /* Returns the next hashmap_entry, or NULL if there are no more entries. */
-extern void *hashmap_iter_next(struct hashmap_iter *iter);
+void *hashmap_iter_next(struct hashmap_iter *iter);
 
 /* Initializes the iterator and returns the first entry, if any. */
 static inline void *hashmap_iter_first(struct hashmap *map,
@@ -429,7 +429,7 @@ static inline void hashmap_enable_item_counting(struct hashmap *map)
  *
  * Uses a hashmap to store the pool of interned strings.
  */
-extern const void *memintern(const void *data, size_t len);
+const void *memintern(const void *data, size_t len);
 static inline const char *strintern(const char *string)
 {
        return memintern(string, strlen(string));
diff --git a/help.h b/help.h
index a141e209aea22b19f12c5e27435c5ed773488177..b8780fbd0fc3d0daacf029b3c3fcdd9a41bc733e 100644 (file)
--- a/help.h
+++ b/help.h
@@ -19,31 +19,31 @@ static inline void mput_char(char c, unsigned int num)
                putchar(c);
 }
 
-extern void list_common_cmds_help(void);
-extern void list_all_cmds_help(void);
-extern void list_common_guides_help(void);
-extern void list_config_help(int for_human);
+void list_common_cmds_help(void);
+void list_all_cmds_help(void);
+void list_common_guides_help(void);
+void list_config_help(int for_human);
 
-extern void list_all_main_cmds(struct string_list *list);
-extern void list_all_other_cmds(struct string_list *list);
-extern void list_cmds_by_category(struct string_list *list,
-                                 const char *category);
-extern void list_cmds_by_config(struct string_list *list);
-extern const char *help_unknown_cmd(const char *cmd);
-extern void load_command_list(const char *prefix,
-                             struct cmdnames *main_cmds,
-                             struct cmdnames *other_cmds);
-extern void add_cmdname(struct cmdnames *cmds, const char *name, int len);
+void list_all_main_cmds(struct string_list *list);
+void list_all_other_cmds(struct string_list *list);
+void list_cmds_by_category(struct string_list *list,
+                          const char *category);
+void list_cmds_by_config(struct string_list *list);
+const char *help_unknown_cmd(const char *cmd);
+void load_command_list(const char *prefix,
+                      struct cmdnames *main_cmds,
+                      struct cmdnames *other_cmds);
+void add_cmdname(struct cmdnames *cmds, const char *name, int len);
 /* Here we require that excludes is a sorted list. */
-extern void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
-extern int is_in_cmdlist(struct cmdnames *cmds, const char *name);
-extern void list_commands(unsigned int colopts, struct cmdnames *main_cmds, struct cmdnames *other_cmds);
+void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
+int is_in_cmdlist(struct cmdnames *cmds, const char *name);
+void list_commands(unsigned int colopts, struct cmdnames *main_cmds, struct cmdnames *other_cmds);
 
 /*
  * call this to die(), when it is suspected that the user mistyped a
  * ref to the command, to give suggested "correct" refs.
  */
-extern void help_unknown_ref(const char *ref, const char *cmd, const char *error);
+void help_unknown_ref(const char *ref, const char *cmd, const char *error);
 
 static inline void list_config_item(struct string_list *list,
                                    const char *prefix,
diff --git a/http.c b/http.c
index 98fb06df0b9c28f7d5fc3c1407682e9333ee6923..27aa0a3192988cd0c272dab0e9f6cf52d538b6fa 100644 (file)
--- a/http.c
+++ b/http.c
@@ -176,7 +176,7 @@ size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
        memcpy(ptr, buffer->buf.buf + buffer->posn, size);
        buffer->posn += size;
 
-       return size;
+       return size / eltsize;
 }
 
 #ifndef NO_CURL_IOCTL
@@ -204,12 +204,12 @@ size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
        struct strbuf *buffer = buffer_;
 
        strbuf_add(buffer, ptr, size);
-       return size;
+       return nmemb;
 }
 
 size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf)
 {
-       return eltsize * nmemb;
+       return nmemb;
 }
 
 static void closedown_active_slot(struct active_request_slot *slot)
@@ -2319,14 +2319,14 @@ static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb,
                        BUG("curl_easy_getinfo for HTTP code failed: %s",
                                curl_easy_strerror(c));
                if (slot->http_code >= 300)
-                       return size;
+                       return nmemb;
        }
 
        do {
                ssize_t retval = xwrite(freq->localfile,
                                        (char *) ptr + posn, size - posn);
                if (retval < 0)
-                       return posn;
+                       return posn / eltsize;
                posn += retval;
        } while (posn < size);
 
@@ -2339,7 +2339,7 @@ static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb,
                the_hash_algo->update_fn(&freq->c, expn,
                                         sizeof(expn) - freq->stream.avail_out);
        } while (freq->stream.avail_in && freq->zret == Z_OK);
-       return size;
+       return nmemb;
 }
 
 struct http_object_request *new_http_object_request(const char *base_url,
diff --git a/http.h b/http.h
index ddfe52f0232150e9506577ade34dfeaab61fc3ca..b429f1cf042bbb61e97e41cd1aacb012c4db834e 100644 (file)
--- a/http.h
+++ b/http.h
@@ -75,18 +75,18 @@ struct buffer {
 };
 
 /* Curl request read/write callbacks */
-extern size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
-extern size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
-extern size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
+size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
+size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
+size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
 #ifndef NO_CURL_IOCTL
-extern curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
+curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
 #endif
 
 /* Slot lifecycle functions */
-extern struct active_request_slot *get_active_slot(void);
-extern int start_active_slot(struct active_request_slot *slot);
-extern void run_active_slot(struct active_request_slot *slot);
-extern void finish_all_active_slots(void);
+struct active_request_slot *get_active_slot(void);
+int start_active_slot(struct active_request_slot *slot);
+void run_active_slot(struct active_request_slot *slot);
+void finish_all_active_slots(void);
 
 /*
  * This will run one slot to completion in a blocking manner, similar to how
@@ -98,15 +98,15 @@ int run_one_slot(struct active_request_slot *slot,
                 struct slot_results *results);
 
 #ifdef USE_CURL_MULTI
-extern void fill_active_slots(void);
-extern void add_fill_function(void *data, int (*fill)(void *));
-extern void step_active_slots(void);
+void fill_active_slots(void);
+void add_fill_function(void *data, int (*fill)(void *));
+void step_active_slots(void);
 #endif
 
-extern void http_init(struct remote *remote, const char *url,
-                     int proactive_auth);
-extern void http_cleanup(void);
-extern struct curl_slist *http_copy_default_headers(void);
+void http_init(struct remote *remote, const char *url,
+              int proactive_auth);
+void http_cleanup(void);
+struct curl_slist *http_copy_default_headers(void);
 
 extern long int git_curl_ipresolve;
 extern int active_requests;
@@ -146,11 +146,11 @@ void normalize_curl_result(CURLcode *result, long http_code, char *errorstr,
                           size_t errorlen);
 
 /* Helpers for modifying and creating URLs */
-extern void append_remote_object_url(struct strbuf *buf, const char *url,
-                                    const char *hex,
-                                    int only_two_digit_prefix);
-extern char *get_remote_object_url(const char *url, const char *hex,
-                                  int only_two_digit_prefix);
+void append_remote_object_url(struct strbuf *buf, const char *url,
+                             const char *hex,
+                             int only_two_digit_prefix);
+char *get_remote_object_url(const char *url, const char *hex,
+                           int only_two_digit_prefix);
 
 /* Options for http_get_*() */
 struct http_get_options {
@@ -204,11 +204,11 @@ struct http_get_options {
  */
 int http_get_strbuf(const char *url, struct strbuf *result, struct http_get_options *options);
 
-extern int http_fetch_ref(const char *base, struct ref *ref);
+int http_fetch_ref(const char *base, struct ref *ref);
 
 /* Helpers for fetching packs */
-extern int http_get_info_packs(const char *base_url,
-       struct packed_git **packs_head);
+int http_get_info_packs(const char *base_url,
+                       struct packed_git **packs_head);
 
 struct http_pack_request {
        char *url;
@@ -219,10 +219,10 @@ struct http_pack_request {
        struct active_request_slot *slot;
 };
 
-extern struct http_pack_request *new_http_pack_request(
+struct http_pack_request *new_http_pack_request(
        struct packed_git *target, const char *base_url);
-extern int finish_http_pack_request(struct http_pack_request *preq);
-extern void release_http_pack_request(struct http_pack_request *preq);
+int finish_http_pack_request(struct http_pack_request *preq);
+void release_http_pack_request(struct http_pack_request *preq);
 
 /* Helpers for fetching object */
 struct http_object_request {
@@ -241,12 +241,12 @@ struct http_object_request {
        struct active_request_slot *slot;
 };
 
-extern struct http_object_request *new_http_object_request(
+struct http_object_request *new_http_object_request(
        const char *base_url, const struct object_id *oid);
-extern void process_http_object_request(struct http_object_request *freq);
-extern int finish_http_object_request(struct http_object_request *freq);
-extern void abort_http_object_request(struct http_object_request *freq);
-extern void release_http_object_request(struct http_object_request *freq);
+void process_http_object_request(struct http_object_request *freq);
+int finish_http_object_request(struct http_object_request *freq);
+void abort_http_object_request(struct http_object_request *freq);
+void release_http_object_request(struct http_object_request *freq);
 
 /* setup routine for curl_easy_setopt CURLOPT_DEBUGFUNCTION */
 void setup_curl_trace(CURL *handle);
diff --git a/khash.h b/khash.h
index a09163b3e3beef8fe90f85003aae974411f6998a..af747a683fed88d9c69c5e2571150adc89cb886e 100644 (file)
--- a/khash.h
+++ b/khash.h
@@ -69,14 +69,14 @@ static const double __ac_HASH_UPPER = 0.77;
                khval_t *vals; \
        } kh_##name##_t;
 
-#define __KHASH_PROTOTYPES(name, khkey_t, khval_t)                                             \
-       extern kh_##name##_t *kh_init_##name(void);                                                     \
-       extern void kh_destroy_##name(kh_##name##_t *h);                                        \
-       extern void kh_clear_##name(kh_##name##_t *h);                                          \
-       extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key);      \
-       extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
-       extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
-       extern void kh_del_##name(kh_##name##_t *h, khint_t x);
+#define __KHASH_PROTOTYPES(name, khkey_t, khval_t)                             \
+       kh_##name##_t *kh_init_##name(void);                                            \
+       void kh_destroy_##name(kh_##name##_t *h);                                       \
+       void kh_clear_##name(kh_##name##_t *h);                                         \
+       khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
+       int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
+       khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
+       void kh_del_##name(kh_##name##_t *h, khint_t x);
 
 #define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
        SCOPE kh_##name##_t *kh_init_##name(void) {                                                     \
diff --git a/kwset.h b/kwset.h
index 583f6268ef0beb121e8b776f38b4169784caf7a8..df99a92178231a53b4b03d7ee1f4dc1d1988a0c8 100644 (file)
--- a/kwset.h
+++ b/kwset.h
@@ -37,16 +37,16 @@ typedef struct kwset_t* kwset_t;
    if enough memory cannot be obtained.  The argument if non-NULL
    specifies a table of character translations to be applied to all
    pattern and search text. */
-extern kwset_t kwsalloc(unsigned char const *);
+kwset_t kwsalloc(unsigned char const *);
 
 /* Incrementally extend the keyword set to include the given string.
    Return NULL for success, or an error message.  Remember an index
    number for each keyword included in the set. */
-extern const char *kwsincr(kwset_t, char const *, size_t);
+const char *kwsincr(kwset_t, char const *, size_t);
 
 /* When the keyword set has been completely built, prepare it for
    use.  Return NULL for success, or an error message. */
-extern const char *kwsprep(kwset_t);
+const char *kwsprep(kwset_t);
 
 /* Search through the given buffer for a member of the keyword set.
    Return a pointer to the leftmost longest match found, or NULL if
@@ -54,8 +54,8 @@ extern const char *kwsprep(kwset_t);
    the matching substring in the integer it points to.  Similarly,
    if foundindex is non-NULL, store the index of the particular
    keyword found therein. */
-extern size_t kwsexec(kwset_t, char const *, size_t, struct kwsmatch *);
+size_t kwsexec(kwset_t, char const *, size_t, struct kwsmatch *);
 
 /* Deallocate the given keyword set and all its associated storage. */
-extern void kwsfree(kwset_t);
+void kwsfree(kwset_t);
 
index e2a5ee7c6d077df353a20d2d55d8b4fc24642bc3..8ee7a2bd4a1866be85d1cbe412be83fcbc5cc42a 100644 (file)
@@ -25,17 +25,17 @@ struct diff_ranges {
        struct range_set target;
 };
 
-extern void range_set_init(struct range_set *, size_t prealloc);
-extern void range_set_release(struct range_set *);
+void range_set_init(struct range_set *, size_t prealloc);
+void range_set_release(struct range_set *);
 /* Range includes start; excludes end */
-extern void range_set_append_unsafe(struct range_set *, long start, long end);
+void range_set_append_unsafe(struct range_set *, long start, long end);
 /* New range must begin at or after end of last added range */
-extern void range_set_append(struct range_set *, long start, long end);
+void range_set_append(struct range_set *, long start, long end);
 /*
  * In-place pass of sorting and merging the ranges in the range set,
  * to sort and make the ranges disjoint.
  */
-extern void sort_and_merge_range_set(struct range_set *);
+void sort_and_merge_range_set(struct range_set *);
 
 /* Linked list of interesting files and their associated ranges.  The
  * list must be kept sorted by path.
@@ -54,10 +54,10 @@ struct line_log_data {
        struct diff_ranges diff;
 };
 
-extern void line_log_init(struct rev_info *rev, const char *prefix, struct string_list *args);
+void line_log_init(struct rev_info *rev, const char *prefix, struct string_list *args);
 
-extern int line_log_filter(struct rev_info *rev);
+int line_log_filter(struct rev_info *rev);
 
-extern int line_log_print(struct rev_info *rev, struct commit *commit);
+int line_log_print(struct rev_info *rev, struct commit *commit);
 
 #endif /* LINE_LOG_H */
index 35403ccc0d586c4732411a5813cb97761dddc435..9843053ce8940391834a86b122d1f64d5b345edf 100644 (file)
@@ -159,7 +159,7 @@ struct lock_file {
  * timeout_ms is -1, retry indefinitely. The flags argument and error
  * handling are described above.
  */
-extern int hold_lock_file_for_update_timeout(
+int hold_lock_file_for_update_timeout(
                struct lock_file *lk, const char *path,
                int flags, long timeout_ms);
 
@@ -188,8 +188,8 @@ static inline int is_lock_file_locked(struct lock_file *lk)
  * of `hold_lock_file_for_update()` to lock `path`. `err` should be the
  * `errno` set by the failing call.
  */
-extern void unable_to_lock_message(const char *path, int err,
-                                  struct strbuf *buf);
+void unable_to_lock_message(const char *path, int err,
+                           struct strbuf *buf);
 
 /*
  * Emit an appropriate error message and `die()` following the failure
@@ -197,7 +197,7 @@ extern void unable_to_lock_message(const char *path, int err,
  * `errno` set by the failing
  * call.
  */
-extern NORETURN void unable_to_lock_die(const char *path, int err);
+NORETURN void unable_to_lock_die(const char *path, int err);
 
 /*
  * Associate a stdio stream with the lockfile (which must still be
@@ -234,7 +234,7 @@ static inline FILE *get_lock_file_fp(struct lock_file *lk)
  * Return the path of the file that is locked by the specified
  * lock_file object. The caller must free the memory.
  */
-extern char *get_locked_file_path(struct lock_file *lk);
+char *get_locked_file_path(struct lock_file *lk);
 
 /*
  * If the lockfile is still open, close it (and the file pointer if it
@@ -282,7 +282,7 @@ static inline int reopen_lock_file(struct lock_file *lk)
  * call `commit_lock_file()` for a `lock_file` object that is not
  * currently locked.
  */
-extern int commit_lock_file(struct lock_file *lk);
+int commit_lock_file(struct lock_file *lk);
 
 /*
  * Like `commit_lock_file()`, but rename the lockfile to the provided
index b62877e8dad8d2ef3088af426f3ff6f8a97187f9..7e5646f5f62b2c69e591cde485b58c5328b609bc 100644 (file)
--- a/ls-refs.h
+++ b/ls-refs.h
@@ -4,7 +4,7 @@
 struct repository;
 struct argv_array;
 struct packet_reader;
-extern int ls_refs(struct repository *r, struct argv_array *keys,
-                  struct packet_reader *request);
+int ls_refs(struct repository *r, struct argv_array *keys,
+           struct packet_reader *request);
 
 #endif /* LS_REFS_H */
index 6830e1e6259bb050cf2af9c2e203c8aa52037da1..79b1d6774ec9ea8a2ef7a6303abb9fc1c917c36f 100644 (file)
@@ -39,8 +39,8 @@ struct mailinfo {
        int input_error;
 };
 
-extern void setup_mailinfo(struct mailinfo *);
-extern int mailinfo(struct mailinfo *, const char *msg, const char *patch);
-extern void clear_mailinfo(struct mailinfo *);
+void setup_mailinfo(struct mailinfo *);
+int mailinfo(struct mailinfo *, const char *msg, const char *patch);
+void clear_mailinfo(struct mailinfo *);
 
 #endif /* MAILINFO_H */
index cc31038b807fbee073a063ec83fe298c87fd2b3d..13cf9669e5b2c43b34bbecd2ea71bf14d9a36d65 100644 (file)
@@ -4,8 +4,8 @@
 struct blob;
 struct index_state;
 
-extern void *merge_blobs(struct index_state *, const char *,
-                        struct blob *, struct blob *,
-                        struct blob *, unsigned long *);
+void *merge_blobs(struct index_state *, const char *,
+                 struct blob *, struct blob *,
+                 struct blob *, unsigned long *);
 
 #endif /* MERGE_BLOBS_H */
diff --git a/midx.c b/midx.c
index d5d2e9522fe39dc1032df4dcdea34e0eb3c741fb..e7e1fe4d65ac3be54154e44ff07cd6122011405c 100644 (file)
--- a/midx.c
+++ b/midx.c
@@ -192,18 +192,17 @@ void close_midx(struct multi_pack_index *m)
        m->fd = -1;
 
        for (i = 0; i < m->num_packs; i++) {
-               if (m->packs[i]) {
-                       close_pack(m->packs[i]);
-                       free(m->packs[i]);
-               }
+               if (m->packs[i])
+                       m->packs[i]->multi_pack_index = 0;
        }
        FREE_AND_NULL(m->packs);
        FREE_AND_NULL(m->pack_names);
 }
 
-int prepare_midx_pack(struct multi_pack_index *m, uint32_t pack_int_id)
+int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t pack_int_id)
 {
        struct strbuf pack_name = STRBUF_INIT;
+       struct packed_git *p;
 
        if (pack_int_id >= m->num_packs)
                die(_("bad pack-int-id: %u (%u total packs)"),
@@ -215,9 +214,18 @@ int prepare_midx_pack(struct multi_pack_index *m, uint32_t pack_int_id)
        strbuf_addf(&pack_name, "%s/pack/%s", m->object_dir,
                    m->pack_names[pack_int_id]);
 
-       m->packs[pack_int_id] = add_packed_git(pack_name.buf, pack_name.len, m->local);
+       p = add_packed_git(pack_name.buf, pack_name.len, m->local);
        strbuf_release(&pack_name);
-       return !m->packs[pack_int_id];
+
+       if (!p)
+               return 1;
+
+       p->multi_pack_index = 1;
+       m->packs[pack_int_id] = p;
+       install_packed_git(r, p);
+       list_add_tail(&p->mru, &r->objects->packed_git_mru);
+
+       return 0;
 }
 
 int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, uint32_t *result)
@@ -261,7 +269,10 @@ static uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos)
        return get_be32(m->chunk_object_offsets + pos * MIDX_CHUNK_OFFSET_WIDTH);
 }
 
-static int nth_midxed_pack_entry(struct multi_pack_index *m, struct pack_entry *e, uint32_t pos)
+static int nth_midxed_pack_entry(struct repository *r,
+                                struct multi_pack_index *m,
+                                struct pack_entry *e,
+                                uint32_t pos)
 {
        uint32_t pack_int_id;
        struct packed_git *p;
@@ -271,7 +282,7 @@ static int nth_midxed_pack_entry(struct multi_pack_index *m, struct pack_entry *
 
        pack_int_id = nth_midxed_pack_int_id(m, pos);
 
-       if (prepare_midx_pack(m, pack_int_id))
+       if (prepare_midx_pack(r, m, pack_int_id))
                die(_("error preparing packfile from multi-pack-index"));
        p = m->packs[pack_int_id];
 
@@ -301,14 +312,17 @@ static int nth_midxed_pack_entry(struct multi_pack_index *m, struct pack_entry *
        return 1;
 }
 
-int fill_midx_entry(const struct object_id *oid, struct pack_entry *e, struct multi_pack_index *m)
+int fill_midx_entry(struct repository * r,
+                   const struct object_id *oid,
+                   struct pack_entry *e,
+                   struct multi_pack_index *m)
 {
        uint32_t pos;
 
        if (!bsearch_midx(oid, m, &pos))
                return 0;
 
-       return nth_midxed_pack_entry(m, e, pos);
+       return nth_midxed_pack_entry(r, m, e, pos);
 }
 
 /* Match "foo.idx" against either "foo.pack" _or_ "foo.idx". */
@@ -1020,7 +1034,7 @@ static int compare_pair_pos_vs_id(const void *_a, const void *_b)
                        display_progress(progress, _n); \
        } while (0)
 
-int verify_midx_file(const char *object_dir)
+int verify_midx_file(struct repository *r, const char *object_dir)
 {
        struct pair_pos_vs_id *pairs = NULL;
        uint32_t i;
@@ -1034,7 +1048,7 @@ int verify_midx_file(const char *object_dir)
        progress = start_progress(_("Looking for referenced packfiles"),
                                  m->num_packs);
        for (i = 0; i < m->num_packs; i++) {
-               if (prepare_midx_pack(m, i))
+               if (prepare_midx_pack(r, m, i))
                        midx_report("failed to load pack in position %d", i);
 
                display_progress(progress, i + 1);
@@ -1099,7 +1113,7 @@ int verify_midx_file(const char *object_dir)
 
                nth_midxed_object_oid(&oid, m, pairs[i].pos);
 
-               if (!fill_midx_entry(&oid, &e, m)) {
+               if (!fill_midx_entry(r, &oid, &e, m)) {
                        midx_report(_("failed to load pack entry for oid[%d] = %s"),
                                    pairs[i].pos, oid_to_hex(&oid));
                        continue;
diff --git a/midx.h b/midx.h
index 26dd042d6381336bfd576ab769509f674c364d08..3eb29731f2b1e8e96a116a683fd8baad1020a46b 100644 (file)
--- a/midx.h
+++ b/midx.h
@@ -5,6 +5,7 @@
 
 struct object_id;
 struct pack_entry;
+struct repository;
 
 #define GIT_TEST_MULTI_PACK_INDEX "GIT_TEST_MULTI_PACK_INDEX"
 
@@ -37,18 +38,18 @@ struct multi_pack_index {
 };
 
 struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local);
-int prepare_midx_pack(struct multi_pack_index *m, uint32_t pack_int_id);
+int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t pack_int_id);
 int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, uint32_t *result);
 struct object_id *nth_midxed_object_oid(struct object_id *oid,
                                        struct multi_pack_index *m,
                                        uint32_t n);
-int fill_midx_entry(const struct object_id *oid, struct pack_entry *e, struct multi_pack_index *m);
+int fill_midx_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e, struct multi_pack_index *m);
 int midx_contains_pack(struct multi_pack_index *m, const char *idx_or_pack_name);
 int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local);
 
 int write_midx_file(const char *object_dir);
 void clear_midx_file(struct repository *r);
-int verify_midx_file(const char *object_dir);
+int verify_midx_file(struct repository *r, const char *object_dir);
 
 void close_midx(struct multi_pack_index *m);
 
diff --git a/notes.h b/notes.h
index 414bc6855ad1593fb281f6a829797b34f3fb2e12..76337f2384723dbce79e437aa6aaa3ba7e9901a4 100644 (file)
--- a/notes.h
+++ b/notes.h
@@ -276,12 +276,10 @@ void init_display_notes(struct display_notes_opt *opt);
 
 /*
  * Append notes for the given 'object_sha1' from all trees set up by
- * init_display_notes() to 'sb'.  The 'flags' are a bitwise
- * combination of
+ * init_display_notes() to 'sb'.
  *
- * - NOTES_SHOW_HEADER: add a 'Notes (refname):' header
- *
- * - NOTES_INDENT: indent the notes by 4 places
+ * If 'raw' is false the note will be indented by 4 places and
+ * a 'Notes (refname):' header added.
  *
  * You *must* call init_display_notes() before using this function.
  */
index b086f5ecdb82a105b9b3381de9893cb72bc5871c..272e01e452b97bd8598a76d6facc5a6f803b579a 100644 (file)
@@ -76,7 +76,8 @@ struct packed_git {
                 pack_keep_in_core:1,
                 freshened:1,
                 do_not_close:1,
-                pack_promisor:1;
+                pack_promisor:1,
+                multi_pack_index:1;
        unsigned char hash[GIT_MAX_RAWSZ];
        struct revindex_entry *revindex;
        /* something like ".git/objects/pack/xxxxx.pack" */
@@ -128,12 +129,6 @@ struct raw_object_store {
        /* A most-recently-used ordered version of the packed_git list. */
        struct list_head packed_git_mru;
 
-       /*
-        * A linked list containing all packfiles, starting with those
-        * contained in the multi_pack_index.
-        */
-       struct packed_git *all_packs;
-
        /*
         * A fast, rough count of the number of objects in the repository.
         * These two fields are not meant for direct access. Use
@@ -162,10 +157,10 @@ const char *loose_object_path(struct repository *r, struct strbuf *buf,
 void *map_loose_object(struct repository *r, const struct object_id *oid,
                       unsigned long *size);
 
-extern void *read_object_file_extended(struct repository *r,
-                                      const struct object_id *oid,
-                                      enum object_type *type,
-                                      unsigned long *size, int lookup_replace);
+void *read_object_file_extended(struct repository *r,
+                               const struct object_id *oid,
+                               enum object_type *type,
+                               unsigned long *size, int lookup_replace);
 static inline void *repo_read_object_file(struct repository *r,
                                          const struct object_id *oid,
                                          enum object_type *type,
@@ -180,20 +175,20 @@ static inline void *repo_read_object_file(struct repository *r,
 /* Read and unpack an object file into memory, write memory to an object file */
 int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);
 
-extern int hash_object_file(const void *buf, unsigned long len,
-                           const char *type, struct object_id *oid);
+int hash_object_file(const void *buf, unsigned long len,
+                    const char *type, struct object_id *oid);
 
-extern int write_object_file(const void *buf, unsigned long len,
-                            const char *type, struct object_id *oid);
+int write_object_file(const void *buf, unsigned long len,
+                     const char *type, struct object_id *oid);
 
-extern int hash_object_file_literally(const void *buf, unsigned long len,
-                                     const char *type, struct object_id *oid,
-                                     unsigned flags);
+int hash_object_file_literally(const void *buf, unsigned long len,
+                              const char *type, struct object_id *oid,
+                              unsigned flags);
 
-extern int pretend_object_file(void *, unsigned long, enum object_type,
-                              struct object_id *oid);
+int pretend_object_file(void *, unsigned long, enum object_type,
+                       struct object_id *oid);
 
-extern int force_object_loose(const struct object_id *oid, time_t mtime);
+int force_object_loose(const struct object_id *oid, time_t mtime);
 
 /*
  * Open the loose object at path, check its hash, and return the contents,
@@ -227,9 +222,9 @@ int repo_has_object_file_with_flags(struct repository *r,
  * with the specified name.  This function does not respect replace
  * references.
  */
-extern int has_loose_object_nonlocal(const struct object_id *);
+int has_loose_object_nonlocal(const struct object_id *);
 
-extern void assert_oid_type(const struct object_id *oid, enum object_type expect);
+void assert_oid_type(const struct object_id *oid, enum object_type expect);
 
 struct object_info {
        /* Request */
index 796792cb32a7ae86b253df05671e1ed4736e4d15..4526979ccf264d10a0fddafcb49697b45fadf71c 100644 (file)
--- a/object.h
+++ b/object.h
@@ -90,19 +90,19 @@ struct object {
        struct object_id oid;
 };
 
-extern const char *type_name(unsigned int type);
-extern int type_from_string_gently(const char *str, ssize_t, int gentle);
+const char *type_name(unsigned int type);
+int type_from_string_gently(const char *str, ssize_t, int gentle);
 #define type_from_string(str) type_from_string_gently(str, -1, 0)
 
 /*
  * Return the current number of buckets in the object hashmap.
  */
-extern unsigned int get_max_object_index(void);
+unsigned int get_max_object_index(void);
 
 /*
  * Return the object from the specified bucket in the object hashmap.
  */
-extern struct object *get_indexed_object(unsigned int);
+struct object *get_indexed_object(unsigned int);
 
 /*
  * This can be used to see if we have heard of the object before, but
@@ -118,7 +118,7 @@ extern struct object *get_indexed_object(unsigned int);
  */
 struct object *lookup_object(struct repository *r, const unsigned char *sha1);
 
-extern void *create_object(struct repository *r, const unsigned char *sha1, void *obj);
+void *create_object(struct repository *r, const unsigned char *sha1, void *obj);
 
 void *object_as_type(struct repository *r, struct object *obj, enum object_type type, int quiet);
 
@@ -189,6 +189,6 @@ void clear_object_flags(unsigned flags);
 /*
  * Clear the specified object flags from all in-core commit objects.
  */
-extern void clear_commit_marks_all(unsigned int flags);
+void clear_commit_marks_all(unsigned int flags);
 
 #endif /* OBJECT_H */
index 72430b611ebf710b4c3ba0160af91104258db138..7a939461ff5baf8aa6d5f599af9e2a5a52a21864 100644 (file)
--- a/oidmap.h
+++ b/oidmap.h
@@ -33,7 +33,7 @@ struct oidmap {
  * parameter may be used to preallocate a sufficiently large table and thus
  * prevent expensive resizing. If 0, the table is dynamically resized.
  */
-extern void oidmap_init(struct oidmap *map, size_t initial_size);
+void oidmap_init(struct oidmap *map, size_t initial_size);
 
 /*
  * Frees an oidmap structure and allocated memory.
@@ -41,13 +41,13 @@ extern void oidmap_init(struct oidmap *map, size_t initial_size);
  * If `free_entries` is true, each oidmap_entry in the map is freed as well
  * using stdlibs free().
  */
-extern void oidmap_free(struct oidmap *map, int free_entries);
+void oidmap_free(struct oidmap *map, int free_entries);
 
 /*
  * Returns the oidmap entry for the specified oid, or NULL if not found.
  */
-extern void *oidmap_get(const struct oidmap *map,
-                       const struct object_id *key);
+void *oidmap_get(const struct oidmap *map,
+                const struct object_id *key);
 
 /*
  * Adds or replaces an oidmap entry.
@@ -57,14 +57,14 @@ extern void *oidmap_get(const struct oidmap *map,
  *
  * Returns the replaced entry, or NULL if not found (i.e. the entry was added).
  */
-extern void *oidmap_put(struct oidmap *map, void *entry);
+void *oidmap_put(struct oidmap *map, void *entry);
 
 /*
  * Removes an oidmap entry matching the specified oid.
  *
  * Returns the removed entry, or NULL if not found.
  */
-extern void *oidmap_remove(struct oidmap *map, const struct object_id *key);
+void *oidmap_remove(struct oidmap *map, const struct object_id *key);
 
 
 struct oidmap_iter {
diff --git a/pack.h b/pack.h
index da99fdd1d2baf7574b606f4c2bc6e1dcfeacf0fa..9fc0945ac9162e542d32c0352ddf6b63e5438f40 100644 (file)
--- a/pack.h
+++ b/pack.h
@@ -55,7 +55,7 @@ struct pack_idx_option {
        uint32_t *anomaly;
 };
 
-extern void reset_pack_idx_option(struct pack_idx_option *);
+void reset_pack_idx_option(struct pack_idx_option *);
 
 /*
  * Packed object index header
@@ -79,28 +79,28 @@ struct progress;
 /* Note, the data argument could be NULL if object type is blob */
 typedef int (*verify_fn)(const struct object_id *, enum object_type, unsigned long, void*, int*);
 
-extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *, const unsigned char *sha1);
-extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
-extern int verify_pack_index(struct packed_git *);
-extern int verify_pack(struct repository *, struct packed_git *, verify_fn fn, struct progress *, uint32_t);
-extern off_t write_pack_header(struct hashfile *f, uint32_t);
-extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);
-extern char *index_pack_lockfile(int fd);
+const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *, const unsigned char *sha1);
+int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
+int verify_pack_index(struct packed_git *);
+int verify_pack(struct repository *, struct packed_git *, verify_fn fn, struct progress *, uint32_t);
+off_t write_pack_header(struct hashfile *f, uint32_t);
+void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);
+char *index_pack_lockfile(int fd);
 
 /*
  * The "hdr" output buffer should be at least this big, which will handle sizes
  * up to 2^67.
  */
 #define MAX_PACK_OBJECT_HEADER 10
-extern int encode_in_pack_object_header(unsigned char *hdr, int hdr_len,
-                                       enum object_type, uintmax_t);
+int encode_in_pack_object_header(unsigned char *hdr, int hdr_len,
+                                enum object_type, uintmax_t);
 
 #define PH_ERROR_EOF           (-1)
 #define PH_ERROR_PACK_SIGNATURE        (-2)
 #define PH_ERROR_PROTOCOL      (-3)
-extern int read_pack_header(int fd, struct pack_header *);
+int read_pack_header(int fd, struct pack_header *);
 
-extern struct hashfile *create_tmp_packfile(char **pack_tmp_name);
-extern void finish_tmp_packfile(struct strbuf *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, uint32_t nr_written, struct pack_idx_option *pack_idx_opts, unsigned char sha1[]);
+struct hashfile *create_tmp_packfile(char **pack_tmp_name);
+void finish_tmp_packfile(struct strbuf *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, uint32_t nr_written, struct pack_idx_option *pack_idx_opts, unsigned char sha1[]);
 
 #endif
index 9f52af928131e8bf9f72a1afccdcb0831e6daf9f..49c8544ff4591e71e1845cd1b275d5fdb898b400 100644 (file)
@@ -994,8 +994,6 @@ static void prepare_packed_git(struct repository *r)
        }
        rearrange_packed_git(r);
 
-       r->objects->all_packs = NULL;
-
        prepare_packed_git_mru(r);
        r->objects->packed_git_initialized = 1;
 }
@@ -1026,26 +1024,16 @@ struct multi_pack_index *get_multi_pack_index(struct repository *r)
 
 struct packed_git *get_all_packs(struct repository *r)
 {
-       prepare_packed_git(r);
-
-       if (!r->objects->all_packs) {
-               struct packed_git *p = r->objects->packed_git;
-               struct multi_pack_index *m;
-
-               for (m = r->objects->multi_pack_index; m; m = m->next) {
-                       uint32_t i;
-                       for (i = 0; i < m->num_packs; i++) {
-                               if (!prepare_midx_pack(m, i)) {
-                                       m->packs[i]->next = p;
-                                       p = m->packs[i];
-                               }
-                       }
-               }
+       struct multi_pack_index *m;
 
-               r->objects->all_packs = p;
+       prepare_packed_git(r);
+       for (m = r->objects->multi_pack_index; m; m = m->next) {
+               uint32_t i;
+               for (i = 0; i < m->num_packs; i++)
+                       prepare_midx_pack(r, m, i);
        }
 
-       return r->objects->all_packs;
+       return r->objects->packed_git;
 }
 
 struct list_head *get_packed_git_mru(struct repository *r)
@@ -1998,13 +1986,13 @@ int find_pack_entry(struct repository *r, const struct object_id *oid, struct pa
                return 0;
 
        for (m = r->objects->multi_pack_index; m; m = m->next) {
-               if (fill_midx_entry(oid, e, m))
+               if (fill_midx_entry(r, oid, e, m))
                        return 1;
        }
 
        list_for_each(pos, &r->objects->packed_git_mru) {
                struct packed_git *p = list_entry(pos, struct packed_git, mru);
-               if (fill_pack_entry(oid, e, p)) {
+               if (!p->multi_pack_index && fill_pack_entry(oid, e, p)) {
                        list_move(&p->mru, &r->objects->packed_git_mru);
                        return 1;
                }
index 6e2e8d6273a2b3c35248a956f77a19925ded3e7d..4b95d04a37c028322c6fbf7d3f1b59e0d541fdb3 100644 (file)
@@ -96,6 +96,23 @@ int parse_opt_commits(const struct option *opt, const char *arg, int unset)
        return 0;
 }
 
+int parse_opt_commit(const struct option *opt, const char *arg, int unset)
+{
+       struct object_id oid;
+       struct commit *commit;
+       struct commit **target = opt->value;
+
+       if (!arg)
+               return -1;
+       if (get_oid(arg, &oid))
+               return error("malformed object name %s", arg);
+       commit = lookup_commit_reference(the_repository, &oid);
+       if (!commit)
+               return error("no such commit %s", arg);
+       *target = commit;
+       return 0;
+}
+
 int parse_opt_object_name(const struct option *opt, const char *arg, int unset)
 {
        struct object_id oid;
@@ -112,6 +129,23 @@ int parse_opt_object_name(const struct option *opt, const char *arg, int unset)
        return 0;
 }
 
+int parse_opt_object_id(const struct option *opt, const char *arg, int unset)
+{
+       struct object_id oid;
+       struct object_id *target = opt->value;
+
+       if (unset) {
+               *target = null_oid;
+               return 0;
+       }
+       if (!arg)
+               return -1;
+       if (get_oid(arg, &oid))
+               return error(_("malformed object name '%s'"), arg);
+       *target = oid;
+       return 0;
+}
+
 int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
 {
        int *target = opt->value;
index cb24f1aa8ae980a366f6f700db15b68064e1f926..987e27cb91162ab03320ff9674f3ad52ffa829b4 100644 (file)
@@ -261,6 +261,35 @@ static enum parse_opt_result parse_short_opt(struct parse_opt_ctx_t *p,
        return PARSE_OPT_UNKNOWN;
 }
 
+static int has_string(const char *it, const char **array)
+{
+       while (*array)
+               if (!strcmp(it, *(array++)))
+                       return 1;
+       return 0;
+}
+
+static int is_alias(struct parse_opt_ctx_t *ctx,
+                   const struct option *one_opt,
+                   const struct option *another_opt)
+{
+       const char **group;
+
+       if (!ctx->alias_groups)
+               return 0;
+
+       if (!one_opt->long_name || !another_opt->long_name)
+               return 0;
+
+       for (group = ctx->alias_groups; *group; group += 3) {
+               /* it and other are from the same family? */
+               if (has_string(one_opt->long_name, group) &&
+                   has_string(another_opt->long_name, group))
+                       return 1;
+       }
+       return 0;
+}
+
 static enum parse_opt_result parse_long_opt(
        struct parse_opt_ctx_t *p, const char *arg,
        const struct option *options)
@@ -298,7 +327,8 @@ static enum parse_opt_result parse_long_opt(
                        if (!(p->flags & PARSE_OPT_KEEP_UNKNOWN) &&
                            !strncmp(long_name, arg, arg_end - arg)) {
 is_abbreviated:
-                               if (abbrev_option) {
+                               if (abbrev_option &&
+                                   !is_alias(p, abbrev_option, options)) {
                                        /*
                                         * If this is abbreviated, it is
                                         * ambiguous. So when there is no
@@ -447,6 +477,10 @@ static void parse_options_check(const struct option *opts)
                        if (opts->callback)
                                BUG("OPTION_LOWLEVEL_CALLBACK needs no high level callback");
                        break;
+               case OPTION_ALIAS:
+                       BUG("OPT_ALIAS() should not remain at this point. "
+                           "Are you using parse_options_step() directly?\n"
+                           "That case is not supported yet.");
                default:
                        ; /* ok. (usually accepts an argument) */
                }
@@ -458,11 +492,10 @@ static void parse_options_check(const struct option *opts)
                exit(128);
 }
 
-void parse_options_start(struct parse_opt_ctx_t *ctx,
-                        int argc, const char **argv, const char *prefix,
-                        const struct option *options, int flags)
+static void parse_options_start_1(struct parse_opt_ctx_t *ctx,
+                                 int argc, const char **argv, const char *prefix,
+                                 const struct option *options, int flags)
 {
-       memset(ctx, 0, sizeof(*ctx));
        ctx->argc = argc;
        ctx->argv = argv;
        if (!(flags & PARSE_OPT_ONE_SHOT)) {
@@ -484,6 +517,14 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
        parse_options_check(options);
 }
 
+void parse_options_start(struct parse_opt_ctx_t *ctx,
+                        int argc, const char **argv, const char *prefix,
+                        const struct option *options, int flags)
+{
+       memset(ctx, 0, sizeof(*ctx));
+       parse_options_start_1(ctx, argc, argv, prefix, options, flags);
+}
+
 static void show_negated_gitcomp(const struct option *opts, int nr_noopts)
 {
        int printed_dashdash = 0;
@@ -575,6 +616,83 @@ static int show_gitcomp(const struct option *opts)
        return PARSE_OPT_COMPLETE;
 }
 
+/*
+ * Scan and may produce a new option[] array, which should be used
+ * instead of the original 'options'.
+ *
+ * Right now this is only used to preprocess and substitue
+ * OPTION_ALIAS.
+ */
+static struct option *preprocess_options(struct parse_opt_ctx_t *ctx,
+                                        const struct option *options)
+{
+       struct option *newopt;
+       int i, nr, alias;
+       int nr_aliases = 0;
+
+       for (nr = 0; options[nr].type != OPTION_END; nr++) {
+               if (options[nr].type == OPTION_ALIAS)
+                       nr_aliases++;
+       }
+
+       if (!nr_aliases)
+               return NULL;
+
+       ALLOC_ARRAY(newopt, nr + 1);
+       COPY_ARRAY(newopt, options, nr + 1);
+
+       /* each alias has two string pointers and NULL */
+       CALLOC_ARRAY(ctx->alias_groups, 3 * (nr_aliases + 1));
+
+       for (alias = 0, i = 0; i < nr; i++) {
+               int short_name;
+               const char *long_name;
+               const char *source;
+               int j;
+
+               if (newopt[i].type != OPTION_ALIAS)
+                       continue;
+
+               short_name = newopt[i].short_name;
+               long_name = newopt[i].long_name;
+               source = newopt[i].value;
+
+               if (!long_name)
+                       BUG("An alias must have long option name");
+
+               for (j = 0; j < nr; j++) {
+                       const char *name = options[j].long_name;
+
+                       if (!name || strcmp(name, source))
+                               continue;
+
+                       if (options[j].type == OPTION_ALIAS)
+                               BUG("No please. Nested aliases are not supported.");
+
+                       /*
+                        * NEEDSWORK: this is a bit inconsistent because
+                        * usage_with_options() on the original options[] will print
+                        * help string as "alias of %s" but "git cmd -h" will
+                        * print the original help string.
+                        */
+                       memcpy(newopt + i, options + j, sizeof(*newopt));
+                       newopt[i].short_name = short_name;
+                       newopt[i].long_name = long_name;
+                       break;
+               }
+
+               if (j == nr)
+                       BUG("could not find source option '%s' of alias '%s'",
+                           source, newopt[i].long_name);
+               ctx->alias_groups[alias * 3 + 0] = newopt[i].long_name;
+               ctx->alias_groups[alias * 3 + 1] = options[j].long_name;
+               ctx->alias_groups[alias * 3 + 2] = NULL;
+               alias++;
+       }
+
+       return newopt;
+}
+
 static int usage_with_options_internal(struct parse_opt_ctx_t *,
                                       const char * const *,
                                       const struct option *, int, int);
@@ -714,11 +832,16 @@ int parse_options(int argc, const char **argv, const char *prefix,
                  int flags)
 {
        struct parse_opt_ctx_t ctx;
+       struct option *real_options;
 
        disallow_abbreviated_options =
                git_env_bool("GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS", 0);
 
-       parse_options_start(&ctx, argc, argv, prefix, options, flags);
+       memset(&ctx, 0, sizeof(ctx));
+       real_options = preprocess_options(&ctx, options);
+       if (real_options)
+               options = real_options;
+       parse_options_start_1(&ctx, argc, argv, prefix, options, flags);
        switch (parse_options_step(&ctx, options, usagestr)) {
        case PARSE_OPT_HELP:
        case PARSE_OPT_ERROR:
@@ -741,6 +864,8 @@ int parse_options(int argc, const char **argv, const char *prefix,
        }
 
        precompose_argv(argc, argv);
+       free(real_options);
+       free(ctx.alias_groups);
        return parse_options_end(&ctx);
 }
 
@@ -835,6 +960,12 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
                        fputc('\n', outfile);
                        pad = USAGE_OPTS_WIDTH;
                }
+               if (opts->type == OPTION_ALIAS) {
+                       fprintf(outfile, "%*s", pad + USAGE_GAP, "");
+                       fprintf_ln(outfile, _("alias of --%s"),
+                                  (const char *)opts->value);
+                       continue;
+               }
                fprintf(outfile, "%*s%s\n", pad + USAGE_GAP, "", _(opts->help));
        }
        fputc('\n', outfile);
index 1dd3523c15a0020d4886dcf1c516dad43b529d0c..98ea42ffd9ecd977b655143651359bf1859eba2a 100644 (file)
@@ -7,6 +7,7 @@ enum parse_opt_type {
        OPTION_ARGUMENT,
        OPTION_GROUP,
        OPTION_NUMBER,
+       OPTION_ALIAS,
        /* options with no arguments */
        OPTION_BIT,
        OPTION_NEGBIT,
@@ -183,6 +184,9 @@ struct option {
          N_("no-op (backward compatibility)"),         \
          PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, parse_opt_noop_cb }
 
+#define OPT_ALIAS(s, l, source_long_name) \
+       { OPTION_ALIAS, (s), (l), (source_long_name) }
+
 /*
  * parse_options() will filter out the processed options and leave the
  * non-option arguments in argv[]. argv0 is assumed program name and
@@ -258,6 +262,8 @@ struct parse_opt_ctx_t {
        const char *opt;
        int flags;
        const char *prefix;
+       const char **alias_groups; /* must be in groups of 3 elements! */
+       struct option *updated_options;
 };
 
 void parse_options_start(struct parse_opt_ctx_t *ctx,
@@ -277,8 +283,12 @@ int parse_opt_abbrev_cb(const struct option *, const char *, int);
 int parse_opt_expiry_date_cb(const struct option *, const char *, int);
 int parse_opt_color_flag_cb(const struct option *, const char *, int);
 int parse_opt_verbosity_cb(const struct option *, const char *, int);
+/* value is struct oid_array* */
 int parse_opt_object_name(const struct option *, const char *, int);
+/* value is struct object_id* */
+int parse_opt_object_id(const struct option *, const char *, int);
 int parse_opt_commits(const struct option *, const char *, int);
+int parse_opt_commit(const struct option *, const char *, int);
 int parse_opt_tertiary(const struct option *, const char *, int);
 int parse_opt_string_list(const struct option *, const char *, int);
 int parse_opt_noop_cb(const struct option *, const char *, int);
diff --git a/path.h b/path.h
index 651e6157fc480264e3495bd508a88d0835de1379..2ba6ca58c83487b5e02a71ce7c2f0d556c59aebe 100644 (file)
--- a/path.h
+++ b/path.h
@@ -13,19 +13,19 @@ struct strbuf;
 /*
  * Return a statically allocated path.
  */
-extern const char *mkpath(const char *fmt, ...)
+const char *mkpath(const char *fmt, ...)
        __attribute__((format (printf, 1, 2)));
 
 /*
  * Return a path.
  */
-extern char *mkpathdup(const char *fmt, ...)
+char *mkpathdup(const char *fmt, ...)
        __attribute__((format (printf, 1, 2)));
 
 /*
  * Construct a path and place the result in the provided buffer `buf`.
  */
-extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
+char *mksnpath(char *buf, size_t n, const char *fmt, ...)
        __attribute__((format (printf, 3, 4)));
 
 /*
@@ -37,16 +37,16 @@ extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
  * Constructs a path into the common git directory of repository `repo` and
  * append it in the provided buffer `sb`.
  */
-extern void strbuf_git_common_path(struct strbuf *sb,
-                                  const struct repository *repo,
-                                  const char *fmt, ...)
+void strbuf_git_common_path(struct strbuf *sb,
+                           const struct repository *repo,
+                           const char *fmt, ...)
        __attribute__((format (printf, 3, 4)));
 
 /*
  * Return a statically allocated path into the main repository's
  * (the_repository) common git directory.
  */
-extern const char *git_common_path(const char *fmt, ...)
+const char *git_common_path(const char *fmt, ...)
        __attribute__((format (printf, 1, 2)));
 
 
@@ -66,30 +66,30 @@ extern const char *git_common_path(const char *fmt, ...)
 /*
  * Return a path into the git directory of repository `repo`.
  */
-extern char *repo_git_path(const struct repository *repo,
-                          const char *fmt, ...)
+char *repo_git_path(const struct repository *repo,
+                   const char *fmt, ...)
        __attribute__((format (printf, 2, 3)));
 
 /*
  * Construct a path into the git directory of repository `repo` and append it
  * to the provided buffer `sb`.
  */
-extern void strbuf_repo_git_path(struct strbuf *sb,
-                                const struct repository *repo,
-                                const char *fmt, ...)
+void strbuf_repo_git_path(struct strbuf *sb,
+                         const struct repository *repo,
+                         const char *fmt, ...)
        __attribute__((format (printf, 3, 4)));
 
 /*
  * Return a statically allocated path into the main repository's
  * (the_repository) git directory.
  */
-extern const char *git_path(const char *fmt, ...)
+const char *git_path(const char *fmt, ...)
        __attribute__((format (printf, 1, 2)));
 
 /*
  * Return a path into the main repository's (the_repository) git directory.
  */
-extern char *git_pathdup(const char *fmt, ...)
+char *git_pathdup(const char *fmt, ...)
        __attribute__((format (printf, 1, 2)));
 
 /*
@@ -97,14 +97,14 @@ extern char *git_pathdup(const char *fmt, ...)
  * and place it in the provided buffer `buf`, the contents of the buffer will
  * be overridden.
  */
-extern char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
+char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
        __attribute__((format (printf, 2, 3)));
 
 /*
  * Construct a path into the main repository's (the_repository) git directory
  * and append it to the provided buffer `sb`.
  */
-extern void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
+void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
        __attribute__((format (printf, 2, 3)));
 
 /*
@@ -112,7 +112,7 @@ extern void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
  *
  * If the repository doesn't have a worktree NULL is returned.
  */
-extern char *repo_worktree_path(const struct repository *repo,
+char *repo_worktree_path(const struct repository *repo,
                                const char *fmt, ...)
        __attribute__((format (printf, 2, 3)));
 
@@ -122,7 +122,7 @@ extern char *repo_worktree_path(const struct repository *repo,
  *
  * If the repository doesn't have a worktree nothing will be appended to `sb`.
  */
-extern void strbuf_repo_worktree_path(struct strbuf *sb,
+void strbuf_repo_worktree_path(struct strbuf *sb,
                                      const struct repository *repo,
                                      const char *fmt, ...)
        __attribute__((format (printf, 3, 4)));
@@ -131,7 +131,7 @@ extern void strbuf_repo_worktree_path(struct strbuf *sb,
  * Return a path into a submodule's git directory located at `path`.  `path`
  * must only reference a submodule of the main repository (the_repository).
  */
-extern char *git_pathdup_submodule(const char *path, const char *fmt, ...)
+char *git_pathdup_submodule(const char *path, const char *fmt, ...)
        __attribute__((format (printf, 2, 3)));
 
 /*
@@ -139,11 +139,11 @@ extern char *git_pathdup_submodule(const char *path, const char *fmt, ...)
  * append it to the provided buffer `sb`.  `path` must only reference a
  * submodule of the main repository (the_repository).
  */
-extern int strbuf_git_path_submodule(struct strbuf *sb, const char *path,
+int strbuf_git_path_submodule(struct strbuf *sb, const char *path,
                                     const char *fmt, ...)
        __attribute__((format (printf, 3, 4)));
 
-extern void report_linked_checkout_garbage(void);
+void report_linked_checkout_garbage(void);
 
 /*
  * You can define a static memoized git path like:
index c36cb788ed47f388e9c51fca46cb6ec4e73830ef..5c62015db4df7007d6c0f5a1cc6041ce04e14b43 100644 (file)
@@ -172,9 +172,9 @@ struct packet_reader {
  * Initialize a 'struct packet_reader' object which is an
  * abstraction around the 'packet_read_with_status()' function.
  */
-extern void packet_reader_init(struct packet_reader *reader, int fd,
-                              char *src_buffer, size_t src_len,
-                              int options);
+void packet_reader_init(struct packet_reader *reader, int fd,
+                       char *src_buffer, size_t src_len,
+                       int options);
 
 /*
  * Perform a packet read and return the status of the read.
@@ -186,7 +186,7 @@ extern void packet_reader_init(struct packet_reader *reader, int fd,
  *                    'line' is set to point at the read line
  * PACKET_READ_FLUSH: 'pktlen' is set to '0' and 'line' is set to NULL
  */
-extern enum packet_read_status packet_reader_read(struct packet_reader *reader);
+enum packet_read_status packet_reader_read(struct packet_reader *reader);
 
 /*
  * Peek the next packet line without consuming it and return the status.
@@ -196,7 +196,7 @@ extern enum packet_read_status packet_reader_read(struct packet_reader *reader);
  * Peeking multiple times without calling 'packet_reader_read()' will return
  * the same result.
  */
-extern enum packet_read_status packet_reader_peek(struct packet_reader *reader);
+enum packet_read_status packet_reader_peek(struct packet_reader *reader);
 
 #define DEFAULT_PACKET_MAX 1000
 #define LARGE_PACKET_MAX 65520
index ec6a1926d4465e61364a7a8450e8f4c86ed841f0..1b705cee1fe95150c8cce73a5cced934aea6cffd 100644 (file)
@@ -10,8 +10,8 @@
 #include <string.h>
 #include "sha1.h"
 
-extern void ppc_sha1_core(uint32_t *hash, const unsigned char *p,
-                         unsigned int nblocks);
+void ppc_sha1_core(uint32_t *hash, const unsigned char *p,
+                  unsigned int nblocks);
 
 int ppc_SHA1_Init(ppc_SHA_CTX *c)
 {
index 682e51867a3452bc1106bc63f44d6d6ba5f523b9..4f9a37e6bee5b537c10458c9ec18792cfd5de348 100644 (file)
@@ -37,24 +37,24 @@ struct prio_queue {
 /*
  * Add the "thing" to the queue.
  */
-extern void prio_queue_put(struct prio_queue *, void *thing);
+void prio_queue_put(struct prio_queue *, void *thing);
 
 /*
  * Extract the "thing" that compares the smallest out of the queue,
  * or NULL.  If compare function is NULL, the queue acts as a LIFO
  * stack.
  */
-extern void *prio_queue_get(struct prio_queue *);
+void *prio_queue_get(struct prio_queue *);
 
 /*
  * Gain access to the "thing" that would be returned by
  * prio_queue_get, but do not remove it from the queue.
  */
-extern void *prio_queue_peek(struct prio_queue *);
+void *prio_queue_peek(struct prio_queue *);
 
-extern void clear_prio_queue(struct prio_queue *);
+void clear_prio_queue(struct prio_queue *);
 
 /* Reverse the LIFO elements */
-extern void prio_queue_reverse(struct prio_queue *);
+void prio_queue_reverse(struct prio_queue *);
 
 #endif /* PRIO_QUEUE_H */
index 2ad35e433c1e6f5f0d08c9d7500dc35782429f51..cef1a4a01c7902b0b1181a43580639fcead442ff 100644 (file)
@@ -14,7 +14,7 @@ enum protocol_version {
  * 'protocol.version' config.  If unconfigured, a value of 'protocol_v0' is
  * returned.
  */
-extern enum protocol_version get_protocol_version_config(void);
+enum protocol_version get_protocol_version_config(void);
 
 /*
  * Used by a server to determine which protocol version should be used based on
@@ -23,12 +23,12 @@ extern enum protocol_version get_protocol_version_config(void);
  * request a particular protocol version, a default of 'protocol_v0' will be
  * used.
  */
-extern enum protocol_version determine_protocol_version_server(void);
+enum protocol_version determine_protocol_version_server(void);
 
 /*
  * Used by a client to determine which protocol version the server is speaking
  * based on the server's initial response.
  */
-extern enum protocol_version determine_protocol_version_client(const char *server_response);
+enum protocol_version determine_protocol_version_client(const char *server_response);
 
 #endif /* PROTOCOL_H */
diff --git a/quote.h b/quote.h
index ea992dcc91ef599b5d053b00ae3a036ce5e87c1a..fb08dc085cca25c276cebd79a4cac5b81bd6ad9a 100644 (file)
--- a/quote.h
+++ b/quote.h
@@ -29,9 +29,9 @@ struct strbuf;
  * sq_quotef() quotes the entire formatted string as a single result.
  */
 
-extern void sq_quote_buf(struct strbuf *, const char *src);
-extern void sq_quote_argv(struct strbuf *, const char **argv);
-extern void sq_quotef(struct strbuf *, const char *fmt, ...);
+void sq_quote_buf(struct strbuf *, const char *src);
+void sq_quote_argv(struct strbuf *, const char **argv);
+void sq_quotef(struct strbuf *, const char *fmt, ...);
 
 /*
  * These match their non-pretty variants, except that they avoid
@@ -45,14 +45,14 @@ void sq_quote_argv_pretty(struct strbuf *, const char **argv);
  * NULL if the input does not look like what sq_quote would have
  * produced.
  */
-extern char *sq_dequote(char *);
+char *sq_dequote(char *);
 
 /*
  * Same as the above, but can be used to unwrap many arguments in the
  * same string separated by space. Like sq_quote, it works in place,
  * modifying arg and appending pointers into it to argv.
  */
-extern int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc);
+int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc);
 
 /*
  * Same as above, but store the unquoted strings in an argv_array. We will
@@ -60,24 +60,24 @@ extern int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc
  * will duplicate and take ownership of the strings.
  */
 struct argv_array;
-extern int sq_dequote_to_argv_array(char *arg, struct argv_array *);
+int sq_dequote_to_argv_array(char *arg, struct argv_array *);
 
-extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
-extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
-extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
+int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
+size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
+void quote_two_c_style(struct strbuf *, const char *, const char *, int);
 
-extern void write_name_quoted(const char *name, FILE *, int terminator);
-extern void write_name_quoted_relative(const char *name, const char *prefix,
-               FILE *fp, int terminator);
+void write_name_quoted(const char *name, FILE *, int terminator);
+void write_name_quoted_relative(const char *name, const char *prefix,
+                               FILE *fp, int terminator);
 
 /* quote path as relative to the given prefix */
-extern char *quote_path_relative(const char *in, const char *prefix,
+char *quote_path_relative(const char *in, const char *prefix,
                          struct strbuf *out);
 
 /* quoting as a string literal for other languages */
-extern void perl_quote_buf(struct strbuf *sb, const char *src);
-extern void python_quote_buf(struct strbuf *sb, const char *src);
-extern void tcl_quote_buf(struct strbuf *sb, const char *src);
-extern void basic_regex_quote_buf(struct strbuf *sb, const char *src);
+void perl_quote_buf(struct strbuf *sb, const char *src);
+void python_quote_buf(struct strbuf *sb, const char *src);
+void tcl_quote_buf(struct strbuf *sb, const char *src);
+void basic_regex_quote_buf(struct strbuf *sb, const char *src);
 
 #endif
index 18b0f9f2f0df0b6cceb67bc0eee81244e3c8a114..5df932ad8f54418927d30117ee0209ba91459bde 100644 (file)
@@ -4,9 +4,9 @@
 struct progress;
 struct rev_info;
 
-extern int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
-                                                 timestamp_t timestamp);
-extern void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
-                                  timestamp_t mark_recent, struct progress *);
+int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
+                                          timestamp_t timestamp);
+void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
+                           timestamp_t mark_recent, struct progress *);
 
 #endif
index 61b043bac3f2e26088177d13adc5ee5fe5e5c2e7..22e7b9944e35d257b144fe06dce2073c91d4819f 100644 (file)
@@ -2326,6 +2326,7 @@ int discard_index(struct index_state *istate)
        free_name_hash(istate);
        cache_tree_free(&(istate->cache_tree));
        istate->initialized = 0;
+       istate->fsmonitor_has_run_once = 0;
        FREE_AND_NULL(istate->cache);
        istate->cache_alloc = 0;
        discard_split_index(istate);
@@ -3131,7 +3132,7 @@ static int write_shared_index(struct index_state *istate,
        trace2_region_enter_printf("index", "shared/do_write_index",
                                   the_repository, "%s", (*temp)->filename.buf);
        ret = do_write_index(si->base, *temp, 1);
-       trace2_region_enter_printf("index", "shared/do_write_index",
+       trace2_region_leave_printf("index", "shared/do_write_index",
                                   the_repository, "%s", (*temp)->filename.buf);
 
        if (ret)
index cb3e73755d445b866ad51246dc8b1ea3ab6f1639..f26408f6cc1caffd93949ebc95d74426c2a9db25 100644 (file)
@@ -6,21 +6,21 @@
 struct commit;
 struct reflog_walk_info;
 
-extern void init_reflog_walk(struct reflog_walk_info **info);
-extern int add_reflog_for_walk(struct reflog_walk_info *info,
-               struct commit *commit, const char *name);
-extern void show_reflog_message(struct reflog_walk_info *info, int,
-                               const struct date_mode *, int force_date);
-extern void get_reflog_message(struct strbuf *sb,
-               struct reflog_walk_info *reflog_info);
-extern const char *get_reflog_ident(struct reflog_walk_info *reflog_info);
-extern timestamp_t get_reflog_timestamp(struct reflog_walk_info *reflog_info);
-extern void get_reflog_selector(struct strbuf *sb,
-               struct reflog_walk_info *reflog_info,
-               const struct date_mode *dmode, int force_date,
-               int shorten);
+void init_reflog_walk(struct reflog_walk_info **info);
+int add_reflog_for_walk(struct reflog_walk_info *info,
+                       struct commit *commit, const char *name);
+void show_reflog_message(struct reflog_walk_info *info, int,
+                        const struct date_mode *, int force_date);
+void get_reflog_message(struct strbuf *sb,
+                       struct reflog_walk_info *reflog_info);
+const char *get_reflog_ident(struct reflog_walk_info *reflog_info);
+timestamp_t get_reflog_timestamp(struct reflog_walk_info *reflog_info);
+void get_reflog_selector(struct strbuf *sb,
+                        struct reflog_walk_info *reflog_info,
+                        const struct date_mode *dmode, int force_date,
+                        int shorten);
 
-extern int reflog_walk_empty(struct reflog_walk_info *walk);
+int reflog_walk_empty(struct reflog_walk_info *walk);
 
 struct commit *next_reflog_entry(struct reflog_walk_info *reflog_info);
 
diff --git a/refs.h b/refs.h
index 8f9cbf8a931611b203b6fa45eefdf9c5fa971312..2727405b61c4e26538c3e76b528df37078337376 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -111,7 +111,7 @@ int should_autocreate_reflog(const char *refname);
 
 int is_branch(const char *refname);
 
-extern int refs_init_db(struct strbuf *err);
+int refs_init_db(struct strbuf *err);
 
 /*
  * If refname is a non-symbolic reference that refers to a tag object,
index 6a1795947e6f3ff3265a406b2bc43c87842a0833..83e885672ba968309c17341b2067f6863acfaaf9 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -119,13 +119,13 @@ struct ref {
 #define REF_HEADS      (1u << 1)
 #define REF_TAGS       (1u << 2)
 
-extern struct ref *find_ref_by_name(const struct ref *list, const char *name);
+struct ref *find_ref_by_name(const struct ref *list, const char *name);
 
 struct ref *alloc_ref(const char *name);
 struct ref *copy_ref(const struct ref *ref);
 struct ref *copy_ref_list(const struct ref *ref);
 void sort_ref_list(struct ref **, int (*cmp)(const void *, const void *));
-extern int count_refspec_match(const char *, struct ref *refs, struct ref **matched_ref);
+int count_refspec_match(const char *, struct ref *refs, struct ref **matched_ref);
 int ref_compare_name(const void *, const void *);
 
 int check_ref_type(const struct ref *ref, int flags);
@@ -141,16 +141,16 @@ struct oid_array;
 struct packet_reader;
 struct argv_array;
 struct string_list;
-extern struct ref **get_remote_heads(struct packet_reader *reader,
-                                    struct ref **list, unsigned int flags,
-                                    struct oid_array *extra_have,
-                                    struct oid_array *shallow_points);
+struct ref **get_remote_heads(struct packet_reader *reader,
+                             struct ref **list, unsigned int flags,
+                             struct oid_array *extra_have,
+                             struct oid_array *shallow_points);
 
 /* Used for protocol v2 in order to retrieve refs from a remote */
-extern struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
-                                   struct ref **list, int for_push,
-                                   const struct argv_array *ref_prefixes,
-                                   const struct string_list *server_options);
+struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
+                            struct ref **list, int for_push,
+                            const struct argv_array *ref_prefixes,
+                            const struct string_list *server_options);
 
 int resolve_remote_symref(struct ref *ref, struct ref *list);
 
@@ -290,9 +290,9 @@ struct push_cas_option {
        int alloc;
 };
 
-extern int parseopt_push_cas_option(const struct option *, const char *arg, int unset);
+int parseopt_push_cas_option(const struct option *, const char *arg, int unset);
 
-extern int is_empty_cas(const struct push_cas_option *);
+int is_empty_cas(const struct push_cas_option *);
 void apply_push_cas(struct push_cas_option *, struct remote *, struct ref *);
 
 #endif
index 16528df942f79e3d7ce65d99e0103395d0c69f51..04ed7a85a2402d64e715c38850a41bea43d0f3b3 100644 (file)
@@ -16,8 +16,8 @@ void prepare_replace_object(struct repository *r);
  * This internal function is only declared here for the benefit of
  * lookup_replace_object().  Please do not call it directly.
  */
-extern const struct object_id *do_lookup_replace_object(struct repository *r,
-                                                       const struct object_id *oid);
+const struct object_id *do_lookup_replace_object(struct repository *r,
+                                                const struct object_id *oid);
 
 /*
  * If object sha1 should be replaced, return the replacement object's
index fbe348efac929f9202c4f3e81d962e84157b9082..2b3f0f901e63aeab70dfca86d3067d169dc315e2 100644 (file)
@@ -8,12 +8,12 @@ struct resolve_undo_info {
        struct object_id oid[3];
 };
 
-extern void record_resolve_undo(struct index_state *, struct cache_entry *);
-extern void resolve_undo_write(struct strbuf *, struct string_list *);
-extern struct string_list *resolve_undo_read(const char *, unsigned long);
-extern void resolve_undo_clear_index(struct index_state *);
-extern int unmerge_index_entry_at(struct index_state *, int);
-extern void unmerge_index(struct index_state *, const struct pathspec *);
-extern void unmerge_marked_index(struct index_state *);
+void record_resolve_undo(struct index_state *, struct cache_entry *);
+void resolve_undo_write(struct strbuf *, struct string_list *);
+struct string_list *resolve_undo_read(const char *, unsigned long);
+void resolve_undo_clear_index(struct index_state *);
+int unmerge_index_entry_at(struct index_state *, int);
+void unmerge_index(struct index_state *, const struct pathspec *);
+void unmerge_marked_index(struct index_state *);
 
 #endif
index a6950691c042e6234b46c0b8c94f5312da58f734..f769e03f018f3ca20d7c17f1c5d021555a91f626 100644 (file)
@@ -55,7 +55,7 @@ struct child_process {
 #define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }
 void child_process_init(struct child_process *);
 void child_process_clear(struct child_process *);
-extern int is_executable(const char *name);
+int is_executable(const char *name);
 
 int start_command(struct child_process *);
 int finish_command(struct child_process *);
@@ -67,10 +67,10 @@ int run_command(struct child_process *);
  * or disabled. Note that this points to static storage that will be
  * overwritten by further calls to find_hook and run_hook_*.
  */
-extern const char *find_hook(const char *name);
+const char *find_hook(const char *name);
 LAST_ARG_MUST_BE_NULL
-extern int run_hook_le(const char *const *env, const char *name, ...);
-extern int run_hook_ve(const char *const *env, const char *name, va_list args);
+int run_hook_le(const char *const *env, const char *name, ...);
+int run_hook_ve(const char *const *env, const char *name, va_list args);
 
 #define RUN_COMMAND_NO_STDIN 1
 #define RUN_GIT_CMD         2  /*If this is to be git sub-command */
index 4407a3f97858acdf47add8e8848cba12daf1de6d..f88a97fb10a322c21062ec8c102482677cfd0feb 100644 (file)
@@ -2168,6 +2168,41 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
        return !item->commit;
 }
 
+int sequencer_get_last_command(struct repository *r, enum replay_action *action)
+{
+       struct todo_item item;
+       char *eol;
+       const char *todo_file;
+       struct strbuf buf = STRBUF_INIT;
+       int ret = -1;
+
+       todo_file = git_path_todo_file();
+       if (strbuf_read_file(&buf, todo_file, 0) < 0) {
+               if (errno == ENOENT)
+                       return -1;
+               else
+                       return error_errno("unable to open '%s'", todo_file);
+       }
+       eol = strchrnul(buf.buf, '\n');
+       if (buf.buf != eol && eol[-1] == '\r')
+               eol--; /* strip Carriage Return */
+       if (parse_insn_line(r, &item, buf.buf, buf.buf, eol))
+               goto fail;
+       if (item.command == TODO_PICK)
+               *action = REPLAY_PICK;
+       else if (item.command == TODO_REVERT)
+               *action = REPLAY_REVERT;
+       else
+               goto fail;
+
+       ret = 0;
+
+ fail:
+       strbuf_release(&buf);
+
+       return ret;
+}
+
 int todo_list_parse_insn_buffer(struct repository *r, char *buf,
                                struct todo_list *todo_list)
 {
@@ -2251,6 +2286,57 @@ static ssize_t strbuf_read_file_or_whine(struct strbuf *sb, const char *path)
        return len;
 }
 
+static int have_finished_the_last_pick(void)
+{
+       struct strbuf buf = STRBUF_INIT;
+       const char *eol;
+       const char *todo_path = git_path_todo_file();
+       int ret = 0;
+
+       if (strbuf_read_file(&buf, todo_path, 0) < 0) {
+               if (errno == ENOENT) {
+                       return 0;
+               } else {
+                       error_errno("unable to open '%s'", todo_path);
+                       return 0;
+               }
+       }
+       /* If there is only one line then we are done */
+       eol = strchr(buf.buf, '\n');
+       if (!eol || !eol[1])
+               ret = 1;
+
+       strbuf_release(&buf);
+
+       return ret;
+}
+
+void sequencer_post_commit_cleanup(struct repository *r)
+{
+       struct replay_opts opts = REPLAY_OPTS_INIT;
+       int need_cleanup = 0;
+
+       if (file_exists(git_path_cherry_pick_head(r))) {
+               unlink(git_path_cherry_pick_head(r));
+               opts.action = REPLAY_PICK;
+               need_cleanup = 1;
+       }
+
+       if (file_exists(git_path_revert_head(r))) {
+               unlink(git_path_revert_head(r));
+               opts.action = REPLAY_REVERT;
+               need_cleanup = 1;
+       }
+
+       if (!need_cleanup)
+               return;
+
+       if (!have_finished_the_last_pick())
+               return;
+
+       sequencer_remove_state(&opts);
+}
+
 static int read_populate_todo(struct repository *r,
                              struct todo_list *todo_list,
                              struct replay_opts *opts)
@@ -2494,14 +2580,15 @@ static void write_strategy_opts(struct replay_opts *opts)
 }
 
 int write_basic_state(struct replay_opts *opts, const char *head_name,
-                     const char *onto, const char *orig_head)
+                     struct commit *onto, const char *orig_head)
 {
        const char *quiet = getenv("GIT_QUIET");
 
        if (head_name)
                write_file(rebase_path_head_name(), "%s\n", head_name);
        if (onto)
-               write_file(rebase_path_onto(), "%s\n", onto);
+               write_file(rebase_path_onto(), "%s\n",
+                          oid_to_hex(&onto->object.oid));
        if (orig_head)
                write_file(rebase_path_orig_head(), "%s\n", orig_head);
 
@@ -3517,10 +3604,11 @@ static const char *reflog_message(struct replay_opts *opts,
        return buf.buf;
 }
 
-static int run_git_checkout(struct replay_opts *opts, const char *commit,
-                           const char *action)
+static int run_git_checkout(struct repository *r, struct replay_opts *opts,
+                           const char *commit, const char *action)
 {
        struct child_process cmd = CHILD_PROCESS_INIT;
+       int ret;
 
        cmd.git_cmd = 1;
 
@@ -3529,26 +3617,32 @@ static int run_git_checkout(struct replay_opts *opts, const char *commit,
        argv_array_pushf(&cmd.env_array, GIT_REFLOG_ACTION "=%s", action);
 
        if (opts->verbose)
-               return run_command(&cmd);
+               ret = run_command(&cmd);
        else
-               return run_command_silent_on_success(&cmd);
+               ret = run_command_silent_on_success(&cmd);
+
+       if (!ret)
+               discard_index(r->index);
+
+       return ret;
 }
 
-int prepare_branch_to_be_rebased(struct replay_opts *opts, const char *commit)
+int prepare_branch_to_be_rebased(struct repository *r, struct replay_opts *opts,
+                                const char *commit)
 {
        const char *action;
 
        if (commit && *commit) {
                action = reflog_message(opts, "start", "checkout %s", commit);
-               if (run_git_checkout(opts, commit, action))
+               if (run_git_checkout(r, opts, commit, action))
                        return error(_("could not checkout %s"), commit);
        }
 
        return 0;
 }
 
-static int checkout_onto(struct replay_opts *opts,
-                        const char *onto_name, const char *onto,
+static int checkout_onto(struct repository *r, struct replay_opts *opts,
+                        const char *onto_name, const struct object_id *onto,
                         const char *orig_head)
 {
        struct object_id oid;
@@ -3557,7 +3651,7 @@ static int checkout_onto(struct replay_opts *opts,
        if (get_oid(orig_head, &oid))
                return error(_("%s: not a valid OID"), orig_head);
 
-       if (run_git_checkout(opts, onto, action)) {
+       if (run_git_checkout(r, opts, oid_to_hex(onto), action)) {
                apply_autostash(opts);
                sequencer_remove_state(opts);
                return error(_("could not detach HEAD"));
@@ -4833,16 +4927,16 @@ static int skip_unnecessary_picks(struct repository *r,
 
 int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
                    const char *shortrevisions, const char *onto_name,
-                   const char *onto, const char *orig_head, struct string_list *commands,
-                   unsigned autosquash, struct todo_list *todo_list)
+                   struct commit *onto, const char *orig_head,
+                   struct string_list *commands, unsigned autosquash,
+                   struct todo_list *todo_list)
 {
        const char *shortonto, *todo_file = rebase_path_todo();
        struct todo_list new_todo = TODO_LIST_INIT;
        struct strbuf *buf = &todo_list->buf;
-       struct object_id oid;
+       struct object_id oid = onto->object.oid;
        int res;
 
-       get_oid(onto, &oid);
        shortonto = find_unique_abbrev(&oid, DEFAULT_ABBREV);
 
        if (buf->len == 0) {
@@ -4885,7 +4979,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
        if (todo_list_parse_insn_buffer(r, new_todo.buf.buf, &new_todo) ||
            todo_list_check(todo_list, &new_todo)) {
                fprintf(stderr, _(edit_todo_list_advice));
-               checkout_onto(opts, onto_name, onto, orig_head);
+               checkout_onto(r, opts, onto_name, &onto->object.oid, orig_head);
                todo_list_release(&new_todo);
 
                return -1;
@@ -4904,7 +4998,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
 
        todo_list_release(&new_todo);
 
-       if (checkout_onto(opts, onto_name, oid_to_hex(&oid), orig_head))
+       if (checkout_onto(r, opts, onto_name, &oid, orig_head))
                return -1;
 
        if (require_clean_work_tree(r, "rebase", "", 1, 1))
index 75e292c03bdd002da58ec5089b1fbf321971b4bf..0c494b83d43e2c0d71822a23dd274176fe743490 100644 (file)
@@ -151,7 +151,7 @@ void todo_list_add_exec_commands(struct todo_list *todo_list,
 int check_todo_list_from_file(struct repository *r);
 int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
                    const char *shortrevisions, const char *onto_name,
-                   const char *onto, const char *orig_head, struct string_list *commands,
+                   struct commit *onto, const char *orig_head, struct string_list *commands,
                    unsigned autosquash, struct todo_list *todo_list);
 int todo_list_rearrange_squash(struct todo_list *todo_list);
 
@@ -183,7 +183,8 @@ void commit_post_rewrite(struct repository *r,
                         const struct commit *current_head,
                         const struct object_id *new_head);
 
-int prepare_branch_to_be_rebased(struct replay_opts *opts, const char *commit);
+int prepare_branch_to_be_rebased(struct repository *r, struct replay_opts *opts,
+                                const char *commit);
 
 #define SUMMARY_INITIAL_COMMIT   (1 << 0)
 #define SUMMARY_SHOW_AUTHOR_DATE (1 << 1)
@@ -198,4 +199,7 @@ int read_author_script(const char *path, char **name, char **email, char **date,
 
 void parse_strategy_opts(struct replay_opts *opts, char *raw_opts);
 int write_basic_state(struct replay_opts *opts, const char *head_name,
-                     const char *onto, const char *orig_head);
+                     struct commit *onto, const char *orig_head);
+void sequencer_post_commit_cleanup(struct repository *r);
+int sequencer_get_last_command(struct repository* r,
+                              enum replay_action *action);
diff --git a/serve.h b/serve.h
index fe65ba9f469018c05dc1c930381cf49eb30357c1..42ddca7f8b4fdd6bb78ab6da710a086645dd44f2 100644 (file)
--- a/serve.h
+++ b/serve.h
@@ -2,14 +2,14 @@
 #define SERVE_H
 
 struct argv_array;
-extern int has_capability(const struct argv_array *keys, const char *capability,
-                         const char **value);
+int has_capability(const struct argv_array *keys, const char *capability,
+                  const char **value);
 
 struct serve_options {
        unsigned advertise_capabilities;
        unsigned stateless_rpc;
 };
 #define SERVE_OPTIONS_INIT { 0 }
-extern void serve(struct serve_options *options);
+void serve(struct serve_options *options);
 
 #endif /* SERVE_H */
index 7678b23b36c291c7b1b6656e0c42fc14ea12da15..5afcd011c6be3c7b9add226b098860b88c77c2fd 100644 (file)
@@ -3,10 +3,10 @@
 
 typedef const unsigned char *sha1_access_fn(size_t index, void *table);
 
-extern int sha1_pos(const unsigned char *sha1,
-                   void *table,
-                   size_t nr,
-                   sha1_access_fn fn);
+int sha1_pos(const unsigned char *sha1,
+            void *table,
+            size_t nr,
+            sha1_access_fn fn);
 
 /*
  * Searches for sha1 in table, using the given fanout table to determine the
index 775a73d8adf6748cd67796a6b13ea1c4843d9f6a..b4f5cadae745e54d03729f135a2208a3067ad0fa 100644 (file)
@@ -157,6 +157,9 @@ static void unique_in_pack(struct packed_git *p,
        uint32_t num, i, first = 0;
        const struct object_id *current = NULL;
 
+       if (p->multi_pack_index)
+               return;
+
        if (open_pack_index(p) || !p->num_objects)
                return;
 
@@ -625,6 +628,9 @@ static void find_abbrev_len_for_pack(struct packed_git *p,
        struct object_id oid;
        const struct object_id *mad_oid;
 
+       if (p->multi_pack_index)
+               return;
+
        if (open_pack_index(p) || !p->num_objects)
                return;
 
index 32f46267710b4e88cd0fc90e1a5a6f6388361c61..f465a3cd311ea7e899ec7bf922a1c24fc831f0b4 100644 (file)
@@ -8,10 +8,10 @@
 /* opaque */
 struct git_istream;
 
-extern struct git_istream *open_istream(const struct object_id *, enum object_type *, unsigned long *, struct stream_filter *);
-extern int close_istream(struct git_istream *);
-extern ssize_t read_istream(struct git_istream *, void *, size_t);
+struct git_istream *open_istream(const struct object_id *, enum object_type *, unsigned long *, struct stream_filter *);
+int close_istream(struct git_istream *);
+ssize_t read_istream(struct git_istream *, void *, size_t);
 
-extern int stream_blob_to_fd(int fd, const struct object_id *, struct stream_filter *, int can_seek);
+int stream_blob_to_fd(int fd, const struct object_id *, struct stream_filter *, int can_seek);
 
 #endif /* STREAMING_H */
index 18c718c12ce84609ddf7d2baf471042bf9fafc7a..f964399949ce58dc1edd561fb0614776dfa2d01f 100644 (file)
@@ -174,8 +174,8 @@ struct string_list_item *string_list_insert(struct string_list *list, const char
  * Remove the given string from the sorted list.  If the string
  * doesn't exist, the list is not altered.
  */
-extern void string_list_remove(struct string_list *list, const char *string,
-                              int free_util);
+void string_list_remove(struct string_list *list, const char *string,
+                       int free_util);
 
 /**
  * Check if the given string is part of a sorted list. If it is part of the list,
index 71b18ad5af24b92421719c3e1e4d5b7154da5926..5c182fad98539eecd1b23edadebf369eb21f353b 100644 (file)
@@ -42,10 +42,10 @@ struct subprocess_capability {
 /* subprocess functions */
 
 /* Function to test two subprocess hashmap entries for equality. */
-extern int cmd2process_cmp(const void *unused_cmp_data,
-                          const void *e1,
-                          const void *e2,
-                          const void *unused_keydata);
+int cmd2process_cmp(const void *unused_cmp_data,
+                   const void *e1,
+                   const void *e2,
+                   const void *unused_keydata);
 
 /*
  * User-supplied function to initialize the sub-process.  This is
index 4dc9b0771c3c2c745d737ad228423e06d55e84c0..1b4e2da658dca189346a39bd0d7831a65cc128aa 100644 (file)
@@ -30,17 +30,17 @@ struct submodule {
 struct submodule_cache;
 struct repository;
 
-extern void submodule_cache_free(struct submodule_cache *cache);
+void submodule_cache_free(struct submodule_cache *cache);
 
-extern int parse_submodule_fetchjobs(const char *var, const char *value);
-extern int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
+int parse_submodule_fetchjobs(const char *var, const char *value);
+int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
 struct option;
-extern int option_fetch_parse_recurse_submodules(const struct option *opt,
-                                                const char *arg, int unset);
-extern int parse_update_recurse_submodules_arg(const char *opt, const char *arg);
-extern int parse_push_recurse_submodules_arg(const char *opt, const char *arg);
-extern void repo_read_gitmodules(struct repository *repo);
-extern void gitmodules_config_oid(const struct object_id *commit_oid);
+int option_fetch_parse_recurse_submodules(const struct option *opt,
+                                         const char *arg, int unset);
+int parse_update_recurse_submodules_arg(const char *opt, const char *arg);
+int parse_push_recurse_submodules_arg(const char *opt, const char *arg);
+void repo_read_gitmodules(struct repository *repo);
+void gitmodules_config_oid(const struct object_id *commit_oid);
 const struct submodule *submodule_from_name(struct repository *r,
                                            const struct object_id *commit_or_tree,
                                            const char *name);
@@ -66,7 +66,7 @@ int check_submodule_name(const char *name);
  * New helpers to retrieve arbitrary configuration from the '.gitmodules' file
  * should NOT be added.
  */
-extern void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules);
-extern void update_clone_config_from_gitmodules(int *max_jobs);
+void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules);
+void update_clone_config_from_gitmodules(int *max_jobs);
 
 #endif /* SUBMODULE_CONFIG_H */
index 2232b2f79ecd7524b5763716fbca5a87bed06f5d..af82db06ac59c77c181351c76fff81ebe92f38c6 100644 (file)
@@ -149,6 +149,9 @@ int cmd__parse_options(int argc, const char **argv)
                OPT_CALLBACK(0, "expect", &expect, "string",
                             "expected output in the variable dump",
                             collect_expect),
+               OPT_GROUP("Alias"),
+               OPT_STRING('A', "alias-source", &string, "string", "get a string"),
+               OPT_ALIAS('Z', "alias-target", "alias-source"),
                OPT_END(),
        };
        int i;
index d674c88ba092d60366a14eaeccc9f4bc6f32660c..7e79b555de8059fae8f47ae1d2382d14b830a4d1 100644 (file)
@@ -1,14 +1,36 @@
 #include "test-tool.h"
 #include "cache.h"
+#include "config.h"
 
 int cmd__read_cache(int argc, const char **argv)
 {
-       int i, cnt = 1;
+       int i, cnt = 1, namelen;
+       const char *name = NULL;
+
+       if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) {
+               namelen = strlen(name);
+               argc--;
+               argv++;
+       }
+
        if (argc == 2)
                cnt = strtol(argv[1], NULL, 0);
        setup_git_directory();
+       git_config(git_default_config, NULL);
        for (i = 0; i < cnt; i++) {
                read_cache();
+               if (name) {
+                       int pos;
+
+                       refresh_index(&the_index, REFRESH_QUIET,
+                                     NULL, NULL, NULL);
+                       pos = index_name_pos(&the_index, name, namelen);
+                       if (pos < 0)
+                               die("%s not in index", name);
+                       printf("%s is%s up to date\n", name,
+                              ce_uptodate(the_index.cache[pos]) ? "" : " not");
+                       write_file(name, "%d\n", i);
+               }
                discard_cache();
        }
        return 0;
index 06a81b54c75d5948b31c03152609fccb1311c12f..5c1c86c193ab79bd89212d0eefd5a114ec542f7d 100644 (file)
@@ -76,6 +76,7 @@ PassEnv GIT_VALGRIND
 PassEnv GIT_VALGRIND_OPTIONS
 PassEnv GNUPGHOME
 PassEnv ASAN_OPTIONS
+PassEnv LSAN_OPTIONS
 PassEnv GIT_TRACE
 PassEnv GIT_CONFIG_NOSYSTEM
 PassEnv GIT_TEST_SIDEBAND_ALL
index be12090c3853b8d64bb903aa92b74001d0fdd19f..c7b70e2d28ba3f8b24a3c4dfe4bb436b1f4acfa5 100644 (file)
@@ -45,7 +45,7 @@ call the aggregation script to summarize the results:
 
     $ ./p0001-rev-list.sh
     [...]
-    $ GIT_BUILD_DIR=/path/to/other/git ./p0001-rev-list.sh
+    $ ./run /path/to/other/git -- ./p0001-rev-list.sh
     [...]
     $ ./aggregate.perl . /path/to/other/git ./p0001-rev-list.sh
 
index 494907a892bba90b677448a152fd55c010b2ebda..66554d216122d26699e425b35166de460fa3821f 100755 (executable)
@@ -3,9 +3,9 @@
 use lib '../../perl/build/lib';
 use strict;
 use warnings;
-use JSON;
 use Getopt::Long;
 use Git;
+use Cwd qw(realpath);
 
 sub get_times {
        my $name = shift;
@@ -99,18 +99,21 @@ sub format_size {
 while (scalar @ARGV) {
        my $arg = $ARGV[0];
        my $dir;
+       my $prefix = '';
        last if -f $arg or $arg eq "--";
        if (! -d $arg) {
                my $rev = Git::command_oneline(qw(rev-parse --verify), $arg);
                $dir = "build/".$rev;
+       } elsif ($arg eq '.') {
+               $dir = '.';
        } else {
-               $arg =~ s{/*$}{};
-               $dir = $arg;
-               $dirabbrevs{$dir} = $dir;
+               $dir = realpath($arg);
+               $dirnames{$dir} = $dir;
+               $prefix .= 'bindir';
        }
        push @dirs, $dir;
-       $dirnames{$dir} = $arg;
-       my $prefix = $dir;
+       $dirnames{$dir} ||= $arg;
+       $prefix .= $dir;
        $prefix =~ tr/^a-zA-Z0-9/_/c;
        $prefixes{$dir} = $prefix . '.';
        shift @ARGV;
@@ -312,9 +315,6 @@ sub print_codespeed_results {
                $environment = $reponame;
        } elsif (exists $ENV{GIT_PERF_REPO_NAME} and $ENV{GIT_PERF_REPO_NAME} ne "") {
                $environment = $ENV{GIT_PERF_REPO_NAME};
-       } elsif (exists $ENV{GIT_TEST_INSTALLED} and $ENV{GIT_TEST_INSTALLED} ne "") {
-               $environment = $ENV{GIT_TEST_INSTALLED};
-               $environment =~ s|/bin-wrappers$||;
        } else {
                $environment = `uname -r`;
                chomp $environment;
@@ -342,7 +342,8 @@ sub print_codespeed_results {
                }
        }
 
-       print to_json(\@data, {utf8 => 1, pretty => 1, canonical => 1}), "\n";
+       require JSON;
+       print JSON::to_json(\@data, {utf8 => 1, pretty => 1, canonical => 1}), "\n";
 }
 
 binmode STDOUT, ":utf8" or die "PANIC on binmode: $!";
index 99bdb16c8583a98b0c33cddadabb85f47b7d5c41..a9b3e112d98223134d791727ffcde01e9123b117 100755 (executable)
@@ -13,35 +13,40 @@ test_expect_success 'repack' '
        export PACK
 '
 
-test_expect_success 'create target repositories' '
-       for repo in t1 t2 t3 t4 t5 t6
-       do
-               git init --bare $repo
-       done
-'
-
 test_perf 'index-pack 0 threads' '
-       GIT_DIR=t1 git index-pack --threads=1 --stdin < $PACK
+       rm -rf repo.git &&
+       git init --bare repo.git &&
+       GIT_DIR=repo.git git index-pack --threads=1 --stdin < $PACK
 '
 
 test_perf 'index-pack 1 thread ' '
-       GIT_DIR=t2 GIT_FORCE_THREADS=1 git index-pack --threads=1 --stdin < $PACK
+       rm -rf repo.git &&
+       git init --bare repo.git &&
+       GIT_DIR=repo.git GIT_FORCE_THREADS=1 git index-pack --threads=1 --stdin < $PACK
 '
 
 test_perf 'index-pack 2 threads' '
-       GIT_DIR=t3 git index-pack --threads=2 --stdin < $PACK
+       rm -rf repo.git &&
+       git init --bare repo.git &&
+       GIT_DIR=repo.git git index-pack --threads=2 --stdin < $PACK
 '
 
 test_perf 'index-pack 4 threads' '
-       GIT_DIR=t4 git index-pack --threads=4 --stdin < $PACK
+       rm -rf repo.git &&
+       git init --bare repo.git &&
+       GIT_DIR=repo.git git index-pack --threads=4 --stdin < $PACK
 '
 
 test_perf 'index-pack 8 threads' '
-       GIT_DIR=t5 git index-pack --threads=8 --stdin < $PACK
+       rm -rf repo.git &&
+       git init --bare repo.git &&
+       GIT_DIR=repo.git git index-pack --threads=8 --stdin < $PACK
 '
 
 test_perf 'index-pack default number of threads' '
-       GIT_DIR=t6 git index-pack --stdin < $PACK
+       rm -rf repo.git &&
+       git init --bare repo.git &&
+       GIT_DIR=repo.git git index-pack --stdin < $PACK
 '
 
 test_done
index bb91dbb173dd01bfbfc11f867f0fcfc355db6822..6a3a42531b056285ac3a42cabe97c41146fa4291 100755 (executable)
@@ -12,8 +12,7 @@ test_perf_large_repo
 # We intentionally use the deprecated pack.writebitmaps
 # config so that we can test against older versions of git.
 test_expect_success 'setup bitmap config' '
-       git config pack.writebitmaps true &&
-       git config pack.writebitmaphashcache true
+       git config pack.writebitmaps true
 '
 
 test_perf 'repack to disk' '
index b04575951f51ea1a41229aa7a17643aa0380dbf5..47c3fd7581cc99d562bb5796f3374e207573a304 100755 (executable)
@@ -7,7 +7,6 @@ test_perf_default_repo
 
 test_expect_success 'create bitmapped server repo' '
        git config pack.writebitmaps true &&
-       git config pack.writebitmaphashcache true &&
        git repack -ad
 '
 
diff --git a/t/perf/p5600-partial-clone.sh b/t/perf/p5600-partial-clone.sh
new file mode 100755 (executable)
index 0000000..3e04bd2
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+test_description='performance of partial clones'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_expect_success 'enable server-side config' '
+       git config uploadpack.allowFilter true &&
+       git config uploadpack.allowAnySHA1InWant true
+'
+
+test_perf 'clone without blobs' '
+       rm -rf bare.git &&
+       git clone --no-local --bare --filter=blob:none . bare.git
+'
+
+test_perf 'checkout of result' '
+       rm -rf worktree &&
+       mkdir -p worktree/.git &&
+       tar -C bare.git -cf - . | tar -C worktree/.git -xf - &&
+       git -C worktree config core.bare false &&
+       git -C worktree checkout -f
+'
+
+test_done
index 169f92eae3d419b2d9d4ccdfbde4a394cc9e15dd..b58a43ea4364a8e5a2c5b9af39b41ec9f0b94f5b 100644 (file)
 # because it will change our working directory.
 TEST_DIRECTORY=$(pwd)/..
 TEST_OUTPUT_DIRECTORY=$(pwd)
-ABSOLUTE_GIT_TEST_INSTALLED=$(
-       test -n "$GIT_TEST_INSTALLED" && cd "$GIT_TEST_INSTALLED" && pwd)
 
 TEST_NO_CREATE_REPO=t
 TEST_NO_MALLOC_CHECK=t
 
 . ../test-lib.sh
 
-if test -z "$GIT_TEST_INSTALLED"; then
-       perf_results_prefix=
-else
-       perf_results_prefix=$(printf "%s" "${GIT_TEST_INSTALLED%/bin-wrappers}" | tr -c "[a-zA-Z0-9]" "[_*]")"."
-       GIT_TEST_INSTALLED=$ABSOLUTE_GIT_TEST_INSTALLED
+if test -n "$GIT_TEST_INSTALLED" -a -z "$PERF_SET_GIT_TEST_INSTALLED"
+then
+       error "Do not use GIT_TEST_INSTALLED with the perf tests.
+
+Instead use:
+
+    ./run <path-to-git> -- <tests>
+
+See t/perf/README for details."
 fi
 
 # Variables from test-lib that are normally internal to the tests; we
@@ -179,7 +181,7 @@ test_wrapper_ () {
                base=$(basename "$0" .sh)
                echo "$test_count" >>"$perf_results_dir"/$base.subtests
                echo "$1" >"$perf_results_dir"/$base.$test_count.descr
-               base="$perf_results_dir"/"$perf_results_prefix$(basename "$0" .sh)"."$test_count"
+               base="$perf_results_dir"/"$PERF_RESULTS_PREFIX$(basename "$0" .sh)"."$test_count"
                "$test_wrapper_func_" "$@"
        fi
 
index 9aaa733c770fb97157e273b6c6d1efd38f9a630a..c7b86104e12a6637b1084d6e02743f6c36df9265 100755 (executable)
@@ -70,6 +70,24 @@ build_git_rev () {
        ) || die "failed to build revision '$mydir'"
 }
 
+set_git_test_installed () {
+       mydir=$1
+
+       mydir_abs=$(cd $mydir && pwd)
+       mydir_abs_wrappers="$mydir_abs_wrappers/bin-wrappers"
+       if test -d "$mydir_abs_wrappers"
+       then
+               GIT_TEST_INSTALLED=$mydir_abs_wrappers
+       else
+               # Older versions of git lacked bin-wrappers;
+               # fallback to the files in the root.
+               GIT_TEST_INSTALLED=$mydir_abs
+       fi
+       export GIT_TEST_INSTALLED
+       PERF_SET_GIT_TEST_INSTALLED=true
+       export PERF_SET_GIT_TEST_INSTALLED
+}
+
 run_dirs_helper () {
        mydir=${1%/}
        shift
@@ -79,7 +97,16 @@ run_dirs_helper () {
        if test $# -gt 0 -a "$1" = --; then
                shift
        fi
-       if [ ! -d "$mydir" ]; then
+
+       PERF_RESULTS_PREFIX=
+       if test "$mydir" = "."
+       then
+               unset GIT_TEST_INSTALLED
+       elif test -d "$mydir"
+       then
+               PERF_RESULTS_PREFIX=bindir$(cd $mydir && printf "%s" "$(pwd)" | tr -c "[a-zA-Z0-9]" "_").
+               set_git_test_installed "$mydir"
+       else
                rev=$(git rev-parse --verify "$mydir" 2>/dev/null) ||
                die "'$mydir' is neither a directory nor a valid revision"
                if [ ! -d build/$rev ]; then
@@ -87,16 +114,12 @@ run_dirs_helper () {
                fi
                build_git_rev $rev "$mydir"
                mydir=build/$rev
+
+               PERF_RESULTS_PREFIX=build_$rev.
+               set_git_test_installed "$mydir"
        fi
-       if test "$mydir" = .; then
-               unset GIT_TEST_INSTALLED
-       else
-               GIT_TEST_INSTALLED="$mydir/bin-wrappers"
-               # Older versions of git lacked bin-wrappers; fallback to the
-               # files in the root.
-               test -d "$GIT_TEST_INSTALLED" || GIT_TEST_INSTALLED=$mydir
-               export GIT_TEST_INSTALLED
-       fi
+       export PERF_RESULTS_PREFIX
+
        run_one_dir "$@"
 }
 
index 800b3ea5f5b64650efa95bfa05e8f90945966f85..cebc77fab0b254fc2e6f63e7eb68956b2b3dec9c 100755 (executable)
@@ -48,6 +48,12 @@ Standard options
     -q, --quiet           be quiet
     --expect <string>     expected output in the variable dump
 
+Alias
+    -A, --alias-source <string>
+                          get a string
+    -Z, --alias-target <string>
+                          get a string
+
 EOF
 
 test_expect_success 'test help' '
@@ -224,6 +230,17 @@ test_expect_success 'non ambiguous option (after two options it abbreviates)' '
        test-tool parse-options --expect="string: 123" --st 123
 '
 
+test_expect_success 'Alias options do not contribute to abbreviation' '
+       test-tool parse-options --alias-source 123 >output &&
+       grep "^string: 123" output &&
+       test-tool parse-options --alias-target 123 >output &&
+       grep "^string: 123" output &&
+       test_must_fail test-tool parse-options --alias &&
+       GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
+       test-tool parse-options --alias 123 >output &&
+       grep "^string: 123" output
+'
+
 cat >typo.err <<\EOF
 error: did you mean `--boolean` (with two dashes ?)
 EOF
index 819430658be65dca58cc4f6f7aec0c2f4ecefb70..71194a3623c61bd7ddf1ccfd0e2da8a3ea065dfe 100755 (executable)
@@ -3,6 +3,11 @@
 test_description='test trace2 facility (normal target)'
 . ./test-lib.sh
 
+# Turn off any inherited trace2 settings for this test.
+sane_unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
+sane_unset GIT_TR2_BRIEF
+sane_unset GIT_TR2_CONFIG_PARAMS
+
 # Add t/helper directory to PATH so that we can use a relative
 # path to run nested instances of test-tool.exe (see 004child).
 # This helps with HEREDOC comparisons later.
@@ -15,11 +20,6 @@ PATH="$TTDIR:$PATH" && export PATH
 # Warning: So you may see extra lines in artifact files when
 # Warning: interactively debugging.
 
-# Turn off any inherited trace2 settings for this test.
-unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
-unset GIT_TR2_BRIEF
-unset GIT_TR2_CONFIG_PARAMS
-
 V=$(git version | sed -e 's/^git version //') && export V
 
 # There are multiple trace2 targets: normal, perf, and event.
@@ -147,4 +147,43 @@ test_expect_success 'normal stream, error event' '
        test_cmp expect actual
 '
 
+sane_unset GIT_TR2_BRIEF
+
+# Now test without environment variables and get all Trace2 settings
+# from the global config.
+
+test_expect_success 'using global config, normal stream, return code 0' '
+       test_when_finished "rm trace.normal actual expect" &&
+       test_config_global trace2.normalBrief 1 &&
+       test_config_global trace2.normalTarget "$(pwd)/trace.normal" &&
+       test-tool trace2 001return 0 &&
+       perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual &&
+       cat >expect <<-EOF &&
+               version $V
+               start _EXE_ trace2 001return 0
+               cmd_name trace2 (trace2)
+               exit elapsed:_TIME_ code:0
+               atexit elapsed:_TIME_ code:0
+       EOF
+       test_cmp expect actual
+'
+
+test_expect_success 'using global config with include' '
+       test_when_finished "rm trace.normal actual expect real.gitconfig" &&
+       test_config_global trace2.normalBrief 1 &&
+       test_config_global trace2.normalTarget "$(pwd)/trace.normal" &&
+       mv "$(pwd)/.gitconfig" "$(pwd)/real.gitconfig" &&
+       test_config_global include.path "$(pwd)/real.gitconfig" &&
+       test-tool trace2 001return 0 &&
+       perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual &&
+       cat >expect <<-EOF &&
+               version $V
+               start _EXE_ trace2 001return 0
+               cmd_name trace2 (trace2)
+               exit elapsed:_TIME_ code:0
+               atexit elapsed:_TIME_ code:0
+       EOF
+       test_cmp expect actual
+'
+
 test_done
index 953e2f78471f647312c4b53920a4d71f24f9c4d5..b501e867af5404e8b9938c2c7ac9dfba5b8d2e30 100755 (executable)
@@ -3,6 +3,11 @@
 test_description='test trace2 facility (perf target)'
 . ./test-lib.sh
 
+# Turn off any inherited trace2 settings for this test.
+sane_unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
+sane_unset GIT_TR2_PERF_BRIEF
+sane_unset GIT_TR2_CONFIG_PARAMS
+
 # Add t/helper directory to PATH so that we can use a relative
 # path to run nested instances of test-tool.exe (see 004child).
 # This helps with HEREDOC comparisons later.
@@ -15,11 +20,6 @@ PATH="$TTDIR:$PATH" && export PATH
 # Warning: So you may see extra lines in artifact files when
 # Warning: interactively debugging.
 
-# Turn off any inherited trace2 settings for this test.
-unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
-unset GIT_TR2_PERF_BRIEF
-unset GIT_TR2_CONFIG_PARAMS
-
 V=$(git version | sed -e 's/^git version //') && export V
 
 # There are multiple trace2 targets: normal, perf, and event.
@@ -50,7 +50,7 @@ test_expect_success 'perf stream, return code 0' '
        perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
        cat >expect <<-EOF &&
                d0|main|version|||||$V
-               d0|main|start|||||_EXE_ trace2 001return 0
+               d0|main|start||_T_ABS_|||_EXE_ trace2 001return 0
                d0|main|cmd_name|||||trace2 (trace2)
                d0|main|exit||_T_ABS_|||code:0
                d0|main|atexit||_T_ABS_|||code:0
@@ -64,7 +64,7 @@ test_expect_success 'perf stream, return code 1' '
        perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
        cat >expect <<-EOF &&
                d0|main|version|||||$V
-               d0|main|start|||||_EXE_ trace2 001return 1
+               d0|main|start||_T_ABS_|||_EXE_ trace2 001return 1
                d0|main|cmd_name|||||trace2 (trace2)
                d0|main|exit||_T_ABS_|||code:1
                d0|main|atexit||_T_ABS_|||code:1
@@ -82,7 +82,7 @@ test_expect_success 'perf stream, error event' '
        perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
        cat >expect <<-EOF &&
                d0|main|version|||||$V
-               d0|main|start|||||_EXE_ trace2 003error '\''hello world'\'' '\''this is a test'\''
+               d0|main|start||_T_ABS_|||_EXE_ trace2 003error '\''hello world'\'' '\''this is a test'\''
                d0|main|cmd_name|||||trace2 (trace2)
                d0|main|error|||||hello world
                d0|main|error|||||this is a test
@@ -128,15 +128,15 @@ test_expect_success 'perf stream, child processes' '
        perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
        cat >expect <<-EOF &&
                d0|main|version|||||$V
-               d0|main|start|||||_EXE_ trace2 004child test-tool trace2 004child test-tool trace2 001return 0
+               d0|main|start||_T_ABS_|||_EXE_ trace2 004child test-tool trace2 004child test-tool trace2 001return 0
                d0|main|cmd_name|||||trace2 (trace2)
                d0|main|child_start||_T_ABS_|||[ch0] class:? argv: test-tool trace2 004child test-tool trace2 001return 0
                d1|main|version|||||$V
-               d1|main|start|||||_EXE_ trace2 004child test-tool trace2 001return 0
+               d1|main|start||_T_ABS_|||_EXE_ trace2 004child test-tool trace2 001return 0
                d1|main|cmd_name|||||trace2 (trace2/trace2)
                d1|main|child_start||_T_ABS_|||[ch0] class:? argv: test-tool trace2 001return 0
                d2|main|version|||||$V
-               d2|main|start|||||_EXE_ trace2 001return 0
+               d2|main|start||_T_ABS_|||_EXE_ trace2 001return 0
                d2|main|cmd_name|||||trace2 (trace2/trace2/trace2)
                d2|main|exit||_T_ABS_|||code:0
                d2|main|atexit||_T_ABS_|||code:0
@@ -150,4 +150,25 @@ test_expect_success 'perf stream, child processes' '
        test_cmp expect actual
 '
 
+sane_unset GIT_TR2_PERF_BRIEF
+
+# Now test without environment variables and get all Trace2 settings
+# from the global config.
+
+test_expect_success 'using global config, perf stream, return code 0' '
+       test_when_finished "rm trace.perf actual expect" &&
+       test_config_global trace2.perfBrief 1 &&
+       test_config_global trace2.perfTarget "$(pwd)/trace.perf" &&
+       test-tool trace2 001return 0 &&
+       perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
+       cat >expect <<-EOF &&
+               d0|main|version|||||$V
+               d0|main|start||_T_ABS_|||_EXE_ trace2 001return 0
+               d0|main|cmd_name|||||trace2 (trace2)
+               d0|main|exit||_T_ABS_|||code:0
+               d0|main|atexit||_T_ABS_|||code:0
+       EOF
+       test_cmp expect actual
+'
+
 test_done
index 028b6c56715e05677d26c39cb7ade92a5510fde2..59adae8123c964b98a3b80bf26867f3562bf81b8 100755 (executable)
@@ -3,6 +3,11 @@
 test_description='test trace2 facility'
 . ./test-lib.sh
 
+# Turn off any inherited trace2 settings for this test.
+sane_unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
+sane_unset GIT_TR2_BARE
+sane_unset GIT_TR2_CONFIG_PARAMS
+
 perl -MJSON::PP -e 0 >/dev/null 2>&1 && test_set_prereq JSON_PP
 
 # Add t/helper directory to PATH so that we can use a relative
@@ -17,11 +22,6 @@ PATH="$TTDIR:$PATH" && export PATH
 # Warning: So you may see extra lines in artifact files when
 # Warning: interactively debugging.
 
-# Turn off any inherited trace2 settings for this test.
-unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
-unset GIT_TR2_BARE
-unset GIT_TR2_CONFIG_PARAMS
-
 V=$(git version | sed -e 's/^git version //') && export V
 
 # There are multiple trace2 targets: normal, perf, and event.
@@ -233,4 +233,36 @@ test_expect_success JSON_PP 'basic trace2_data' '
        test_cmp expect actual
 '
 
+# Now test without environment variables and get all Trace2 settings
+# from the global config.
+
+test_expect_success JSON_PP 'using global config, event stream, error event' '
+       test_when_finished "rm trace.event actual expect" &&
+       test_config_global trace2.eventTarget "$(pwd)/trace.event" &&
+       test-tool trace2 003error "hello world" "this is a test" &&
+       perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual &&
+       sed -e "s/^|//" >expect <<-EOF &&
+       |VAR1 = {
+       |  "_SID0_":{
+       |    "argv":[
+       |      "_EXE_",
+       |      "trace2",
+       |      "003error",
+       |      "hello world",
+       |      "this is a test"
+       |    ],
+       |    "errors":[
+       |      "%s",
+       |      "%s"
+       |    ],
+       |    "exit_code":0,
+       |    "hierarchy":"trace2",
+       |    "name":"trace2",
+       |    "version":"$V"
+       |  }
+       |};
+       EOF
+       test_cmp expect actual
+'
+
 test_done
index c5014ad9a63f2451f84db5076f902a0132d318c1..822381dd9df67f7a392e7697c21d9aade2eb56e1 100755 (executable)
@@ -60,38 +60,47 @@ test_expect_success 'setup' '
 '
 
 test_expect_success 'checkout -b to a new branch, set to HEAD' '
+       test_when_finished "
+               git checkout branch1 &&
+               test_might_fail git branch -D branch2" &&
        do_checkout branch2
 '
 
-test_expect_success 'checkout -b to a new branch, set to an explicit ref' '
-       git checkout branch1 &&
-       git branch -D branch2 &&
+test_expect_success 'checkout -b to a merge base' '
+       test_when_finished "
+               git checkout branch1 &&
+               test_might_fail git branch -D branch2" &&
+       git checkout -b branch2 branch1...
+'
 
+test_expect_success 'checkout -b to a new branch, set to an explicit ref' '
+       test_when_finished "
+               git checkout branch1 &&
+               test_might_fail git branch -D branch2" &&
        do_checkout branch2 $HEAD1
 '
 
 test_expect_success 'checkout -b to a new branch with unmergeable changes fails' '
-       git checkout branch1 &&
-
-       # clean up from previous test
-       git branch -D branch2 &&
-
        setup_dirty_unmergeable &&
        test_must_fail do_checkout branch2 $HEAD1 &&
        test_dirty_unmergeable
 '
 
 test_expect_success 'checkout -f -b to a new branch with unmergeable changes discards changes' '
+       test_when_finished "
+               git checkout branch1 &&
+               test_might_fail git branch -D branch2" &&
+
        # still dirty and on branch1
        do_checkout branch2 $HEAD1 "-f -b" &&
        test_must_fail test_dirty_unmergeable
 '
 
 test_expect_success 'checkout -b to a new branch preserves mergeable changes' '
-       git checkout branch1 &&
-
-       # clean up from previous test
-       git branch -D branch2 &&
+       test_when_finished "
+               git reset --hard &&
+               git checkout branch1 &&
+               test_might_fail git branch -D branch2" &&
 
        setup_dirty_mergeable &&
        do_checkout branch2 $HEAD1 &&
@@ -99,27 +108,18 @@ test_expect_success 'checkout -b to a new branch preserves mergeable changes' '
 '
 
 test_expect_success 'checkout -f -b to a new branch with mergeable changes discards changes' '
-       # clean up from previous test
-       git reset --hard &&
-
-       git checkout branch1 &&
-
-       # clean up from previous test
-       git branch -D branch2 &&
-
+       test_when_finished git reset --hard HEAD &&
        setup_dirty_mergeable &&
        do_checkout branch2 $HEAD1 "-f -b" &&
        test_must_fail test_dirty_mergeable
 '
 
 test_expect_success 'checkout -b to an existing branch fails' '
-       git reset --hard HEAD &&
-
+       test_when_finished git reset --hard HEAD &&
        test_must_fail do_checkout branch2 $HEAD2
 '
 
 test_expect_success 'checkout -b to @{-1} fails with the right branch name' '
-       git reset --hard HEAD &&
        git checkout branch1 &&
        git checkout branch2 &&
        echo  >expect "fatal: A branch named '\''branch1'\'' already exists." &&
@@ -133,6 +133,12 @@ test_expect_success 'checkout -B to an existing branch resets branch to HEAD' '
        do_checkout branch2 "" -B
 '
 
+test_expect_success 'checkout -B to a merge base' '
+       git checkout branch1 &&
+
+       git checkout -B branch2 branch1...
+'
+
 test_expect_success 'checkout -B to an existing branch from detached HEAD resets branch to HEAD' '
        git checkout $(git rev-parse --verify HEAD) &&
 
@@ -160,6 +166,7 @@ test_expect_success 'checkout -f -B to an existing branch with unmergeable chang
 '
 
 test_expect_success 'checkout -B to an existing branch preserves mergeable changes' '
+       test_when_finished git reset --hard &&
        git checkout branch1 &&
 
        setup_dirty_mergeable &&
@@ -168,9 +175,6 @@ test_expect_success 'checkout -B to an existing branch preserves mergeable chang
 '
 
 test_expect_success 'checkout -f -B to an existing branch with mergeable changes discards changes' '
-       # clean up from previous test
-       git reset --hard &&
-
        git checkout branch1 &&
 
        setup_dirty_mergeable &&
index e9ad50b66dece121464f0638d5a4a1dd0280d121..e9d7084d19c9d650f43f97d1c389c7fbc4cc51d2 100755 (executable)
@@ -42,6 +42,10 @@ test_expect_success 'git branch a/b/c should create a branch' '
        git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c
 '
 
+test_expect_success 'git branch mb master... should create a branch' '
+       git branch mb master... && test_path_is_file .git/refs/heads/mb
+'
+
 test_expect_success 'git branch HEAD should fail' '
        test_must_fail git branch HEAD
 '
@@ -316,8 +320,8 @@ test_expect_success 'git branch --list -v with --abbrev' '
 test_expect_success 'git branch --column' '
        COLUMNS=81 git branch --column=column >actual &&
        cat >expected <<\EOF &&
-  a/b/c     bam       foo       l       * master    n         o/p       r
-  abc       bar       j/k       m/m       master2   o/o       q
+  a/b/c     bam       foo       l       * master    mb        o/o       q
+  abc       bar       j/k       m/m       master2   n         o/p       r
 EOF
        test_cmp expected actual
 '
@@ -339,6 +343,7 @@ test_expect_success 'git branch --column with an extremely long branch name' '
   m/m
 * master
   master2
+  mb
   n
   o/o
   o/p
@@ -356,8 +361,8 @@ test_expect_success 'git branch with column.*' '
        git config --unset column.branch &&
        git config --unset column.ui &&
        cat >expected <<\EOF &&
-  a/b/c   bam   foo   l   * master    n     o/p   r
-  abc     bar   j/k   m/m   master2   o/o   q
+  a/b/c   bam   foo   l   * master    mb   o/o   q
+  abc     bar   j/k   m/m   master2   n    o/p   r
 EOF
        test_cmp expected actual
 '
@@ -381,6 +386,7 @@ test_expect_success 'git branch -v with column.ui ignored' '
   m/m
 * master
   master2
+  mb
   n
   o/o
   o/p
index 1a8818fbe02c72164fbaa676c1bc734390f7dbc0..9b9b4ca8d4f2a2188c206a0e1e2de763d00a1ab6 100755 (executable)
@@ -161,6 +161,25 @@ test_expect_success 'successful commit clears CHERRY_PICK_HEAD' '
 
        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
 '
+test_expect_success 'successful final commit clears cherry-pick state' '
+       pristine_detach initial &&
+
+       test_must_fail git cherry-pick base picked-signed &&
+       echo resolved >foo &&
+       test_path_is_file .git/sequencer/todo &&
+       git commit -a &&
+       test_must_fail test_path_exists .git/sequencer
+'
+
+test_expect_success 'reset after final pick clears cherry-pick state' '
+       pristine_detach initial &&
+
+       test_must_fail git cherry-pick base picked-signed &&
+       echo resolved >foo &&
+       test_path_is_file .git/sequencer/todo &&
+       git reset &&
+       test_must_fail test_path_exists .git/sequencer
+'
 
 test_expect_success 'failed cherry-pick produces dirty index' '
        pristine_detach initial &&
@@ -361,6 +380,26 @@ test_expect_success 'failed commit does not clear REVERT_HEAD' '
        test_cmp_rev picked REVERT_HEAD
 '
 
+test_expect_success 'successful final commit clears revert state' '
+       pristine_detach picked-signed &&
+
+       test_must_fail git revert picked-signed base &&
+       echo resolved >foo &&
+       test_path_is_file .git/sequencer/todo &&
+       git commit -a &&
+       test_must_fail test_path_exists .git/sequencer
+'
+
+test_expect_success 'reset after final pick clears revert state' '
+       pristine_detach picked-signed &&
+
+       test_must_fail git revert picked-signed base &&
+       echo resolved >foo &&
+       test_path_is_file .git/sequencer/todo &&
+       git reset &&
+       test_must_fail test_path_exists .git/sequencer
+'
+
 test_expect_success 'revert conflict, diff3 -m style' '
        pristine_detach initial &&
        git config merge.conflictstyle diff3 &&
index 553fe3e88e0d90bde62ec4f257bd0648f917f0b5..6e1b73ec3afcfff62ebe628cc673b236bc74e63d 100755 (executable)
@@ -51,14 +51,16 @@ test_expect_success 'am with dos files without --keep-cr' '
 
 test_expect_success 'am with dos files with --keep-cr' '
        git checkout -b dosfiles-keep-cr initial &&
-       git format-patch -k --stdout initial..master | git am --keep-cr -k -3 &&
+       git format-patch -k --stdout initial..master >output &&
+       git am --keep-cr -k -3 output &&
        git diff --exit-code master
 '
 
 test_expect_success 'am with dos files config am.keepcr' '
        git config am.keepcr 1 &&
        git checkout -b dosfiles-conf-keepcr initial &&
-       git format-patch -k --stdout initial..master | git am -k -3 &&
+       git format-patch -k --stdout initial..master >output &&
+       git am -k -3 output &&
        git diff --exit-code master
 '
 
index 82d7f7f6a5bbdc5609e0b76c97a3ae14f6a53a92..a26c8ba9a2b1b815e1917f703cb3520a7608d624 100755 (executable)
@@ -34,8 +34,7 @@ test_expect_success 'setup repo with moderate-sized history' '
        bitmaptip=$(git rev-parse master) &&
        blob=$(echo tagged-blob | git hash-object -w --stdin) &&
        git tag tagged-blob $blob &&
-       git config repack.writebitmaps true &&
-       git config pack.writebitmaphashcache true
+       git config repack.writebitmaps true
 '
 
 test_expect_success 'full repack creates bitmaps' '
@@ -269,7 +268,7 @@ test_expect_success JGIT 'we can read jgit bitmaps' '
        git clone --bare . compat-jgit.git &&
        (
                cd compat-jgit.git &&
-               rm -f .git/objects/pack/*.bitmap &&
+               rm -f objects/pack/*.bitmap &&
                jgit gc &&
                git rev-list --test-bitmap HEAD
        )
index 217adf3a632b49e9322de1db78c3e1a588c3b7bd..b3c8a92450bc0e9ba869563ef1a7a4c1362cebd6 100755 (executable)
@@ -62,4 +62,16 @@ test_expect_success MINGW 'remote nick cannot contain backslashes' '
        test_i18ngrep ! "unable to access" err
 '
 
+test_expect_success 'unc alternates' '
+       tree="$(git rev-parse HEAD:)" &&
+       mkdir test-unc-alternate &&
+       (
+               cd test-unc-alternate &&
+               git init &&
+               test_must_fail git show $tree &&
+               echo "$UNCPATH/.git/objects" >.git/objects/info/alternates &&
+               git show $tree
+       )
+'
+
 test_done
index 7411bf7fecd89984c7256668863c9f96bb75efbf..515c6735e9cb076c9f4b5a252c48216765b5076a 100755 (executable)
@@ -181,7 +181,15 @@ test_expect_success 'background auto gc respects lock for all operations' '
        # now fake a concurrent gc that holds the lock; we can use our
        # shell pid so that it looks valid.
        hostname=$(hostname || echo unknown) &&
-       printf "$$ %s" "$hostname" >.git/gc.pid &&
+       shell_pid=$$ &&
+       if test_have_prereq MINGW && test -f /proc/$shell_pid/winpid
+       then
+               # In Git for Windows, Bash (actually, the MSYS2 runtime) has a
+               # different idea of PIDs than git.exe (actually Windows). Use
+               # the Windows PID in this case.
+               shell_pid=$(cat /proc/$shell_pid/winpid)
+       fi &&
+       printf "%d %s" "$shell_pid" "$hostname" >.git/gc.pid &&
 
        # our gc should exit zero without doing anything
        run_and_wait_for_auto_gc &&
index e285686662df781c87d59c910aa9d596eb974c34..6aeeb279a0a03614151a37f1bed8f22f4af0c4f5 100755 (executable)
@@ -1702,7 +1702,7 @@ test_expect_success '--points-at finds annotated tags of tags' '
 
 test_expect_success 'recursive tagging should give advice' '
        sed -e "s/|$//" <<-EOF >expect &&
-       hint: You have created a nested tag. The object referred to by your new is
+       hint: You have created a nested tag. The object referred to by your new tag is
        hint: already a tag. If you meant to tag the object that it points to, use:
        hint: |
        hint:   git tag -f nested annotated-v4.0^{}
index 458608cc1e7ca51e1a7e40017794b5f2c55d3db3..c1eb72555d0c9878aafe04b8b3f69392a0b32dcd 100755 (executable)
@@ -780,6 +780,24 @@ EOF
        test_i18ncmp expected actual
 '
 
+test_expect_success 'status when cherry-picking after committing conflict resolution' '
+       git reset --hard cherry_branch &&
+       test_when_finished "git cherry-pick --abort" &&
+       test_must_fail git cherry-pick cherry_branch_second one_cherry &&
+       echo end >main.txt &&
+       git commit -a &&
+       cat >expected <<EOF &&
+On branch cherry_branch
+Cherry-pick currently in progress.
+  (run "git cherry-pick --continue" to continue)
+  (use "git cherry-pick --abort" to cancel the cherry-pick operation)
+
+nothing to commit (use -u to show untracked files)
+EOF
+       git status --untracked-files=no >actual &&
+       test_i18ncmp expected actual
+'
+
 test_expect_success 'status showing detached at and from a tag' '
        test_commit atag tagging &&
        git checkout atag &&
@@ -857,6 +875,24 @@ EOF
        test_i18ncmp expected actual
 '
 
+test_expect_success 'status while reverting after committing conflict resolution' '
+       test_when_finished "git revert --abort" &&
+       git reset --hard new &&
+       test_must_fail git revert old new &&
+       echo reverted >to-revert.txt &&
+       git commit -a &&
+       cat >expected <<EOF &&
+On branch master
+Revert currently in progress.
+  (run "git revert --continue" to continue)
+  (use "git revert --abort" to cancel the revert operation)
+
+nothing to commit (use -u to show untracked files)
+EOF
+       git status --untracked-files=no >actual &&
+       test_i18ncmp expected actual
+'
+
 test_expect_success 'prepare for different number of commits rebased' '
        git reset --hard master &&
        git checkout -b several_commits &&
index 3e0a61db2348577ed5c6cef4f844c2a26548de1d..81a375fa0ff9845cb755dd77df9921d2b71c764b 100755 (executable)
@@ -346,4 +346,12 @@ test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR'
        test_cmp before after
 '
 
+test_expect_success 'discard_index() also discards fsmonitor info' '
+       test_config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-all" &&
+       test_might_fail git update-index --refresh &&
+       test-tool read-cache --print-and-refresh=tracked 2 >actual &&
+       printf "tracked is%s up to date\n" "" " not" >expect &&
+       test_cmp expect actual
+'
+
 test_done
index a9fb971615b7f40bd17f16dcc1ce99ab2c0930ca..5b61c10a9c5402bfca8473f663076f9062a2e2a4 100755 (executable)
@@ -130,14 +130,55 @@ test_expect_success 'custom mergetool' '
        test_when_finished "git reset --hard" &&
        git checkout -b test$test_count branch1 &&
        git submodule update -N &&
-       test_must_fail git merge master >/dev/null 2>&1 &&
-       ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
+       test_must_fail git merge master &&
+       ( yes "" | git mergetool both ) &&
        ( yes "" | git mergetool file1 file1 ) &&
-       ( yes "" | git mergetool file2 "spaced name" >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
-       ( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool file2 "spaced name" ) &&
+       ( yes "" | git mergetool subdir/file3 ) &&
+       ( yes "d" | git mergetool file11 ) &&
+       ( yes "d" | git mergetool file12 ) &&
+       ( yes "l" | git mergetool submod ) &&
+       test "$(cat file1)" = "master updated" &&
+       test "$(cat file2)" = "master new" &&
+       test "$(cat subdir/file3)" = "master new sub" &&
+       test "$(cat submod/bar)" = "branch1 submodule" &&
+       git commit -m "branch1 resolved with mergetool"
+'
+
+test_expect_success 'gui mergetool' '
+       test_config merge.guitool myguitool &&
+       test_config mergetool.myguitool.cmd "(printf \"gui \" && cat \"\$REMOTE\") >\"\$MERGED\"" &&
+       test_config mergetool.myguitool.trustExitCode true &&
+       test_when_finished "git reset --hard" &&
+       git checkout -b test$test_count branch1 &&
+       git submodule update -N &&
+       test_must_fail git merge master &&
+       ( yes "" | git mergetool --gui both ) &&
+       ( yes "" | git mergetool -g file1 file1 ) &&
+       ( yes "" | git mergetool --gui file2 "spaced name" ) &&
+       ( yes "" | git mergetool --gui subdir/file3 ) &&
+       ( yes "d" | git mergetool --gui file11 ) &&
+       ( yes "d" | git mergetool --gui file12 ) &&
+       ( yes "l" | git mergetool --gui submod ) &&
+       test "$(cat file1)" = "gui master updated" &&
+       test "$(cat file2)" = "gui master new" &&
+       test "$(cat subdir/file3)" = "gui master new sub" &&
+       test "$(cat submod/bar)" = "branch1 submodule" &&
+       git commit -m "branch1 resolved with mergetool"
+'
+
+test_expect_success 'gui mergetool without merge.guitool set falls back to merge.tool' '
+       test_when_finished "git reset --hard" &&
+       git checkout -b test$test_count branch1 &&
+       git submodule update -N &&
+       test_must_fail git merge master &&
+       ( yes "" | git mergetool --gui both ) &&
+       ( yes "" | git mergetool -g file1 file1 ) &&
+       ( yes "" | git mergetool --gui file2 "spaced name" ) &&
+       ( yes "" | git mergetool --gui subdir/file3 ) &&
+       ( yes "d" | git mergetool --gui file11 ) &&
+       ( yes "d" | git mergetool --gui file12 ) &&
+       ( yes "l" | git mergetool --gui submod ) &&
        test "$(cat file1)" = "master updated" &&
        test "$(cat file2)" = "master new" &&
        test "$(cat subdir/file3)" = "master new sub" &&
@@ -153,15 +194,15 @@ test_expect_success 'mergetool crlf' '
        # test_when_finished is LIFO.)
        test_config core.autocrlf true &&
        git checkout -b test$test_count branch1 &&
-       test_must_fail git merge master >/dev/null 2>&1 &&
-       ( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool "spaced name" >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
-       ( yes "r" | git mergetool submod >/dev/null 2>&1 ) &&
+       test_must_fail git merge master &&
+       ( yes "" | git mergetool file1 ) &&
+       ( yes "" | git mergetool file2 ) &&
+       ( yes "" | git mergetool "spaced name" ) &&
+       ( yes "" | git mergetool both ) &&
+       ( yes "" | git mergetool subdir/file3 ) &&
+       ( yes "d" | git mergetool file11 ) &&
+       ( yes "d" | git mergetool file12 ) &&
+       ( yes "r" | git mergetool submod ) &&
        test "$(printf x | cat file1 -)" = "$(printf "master updated\r\nx")" &&
        test "$(printf x | cat file2 -)" = "$(printf "master new\r\nx")" &&
        test "$(printf x | cat subdir/file3 -)" = "$(printf "master new sub\r\nx")" &&
@@ -176,8 +217,8 @@ test_expect_success 'mergetool in subdir' '
        git submodule update -N &&
        (
                cd subdir &&
-               test_must_fail git merge master >/dev/null 2>&1 &&
-               ( yes "" | git mergetool file3 >/dev/null 2>&1 ) &&
+               test_must_fail git merge master &&
+               ( yes "" | git mergetool file3 ) &&
                test "$(cat file3)" = "master new sub"
        )
 '
@@ -188,14 +229,14 @@ test_expect_success 'mergetool on file in parent dir' '
        git submodule update -N &&
        (
                cd subdir &&
-               test_must_fail git merge master >/dev/null 2>&1 &&
-               ( yes "" | git mergetool file3 >/dev/null 2>&1 ) &&
-               ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) &&
-               ( yes "" | git mergetool ../file2 ../spaced\ name >/dev/null 2>&1 ) &&
-               ( yes "" | git mergetool ../both >/dev/null 2>&1 ) &&
-               ( yes "d" | git mergetool ../file11 >/dev/null 2>&1 ) &&
-               ( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) &&
-               ( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) &&
+               test_must_fail git merge master &&
+               ( yes "" | git mergetool file3 ) &&
+               ( yes "" | git mergetool ../file1 ) &&
+               ( yes "" | git mergetool ../file2 ../spaced\ name ) &&
+               ( yes "" | git mergetool ../both ) &&
+               ( yes "d" | git mergetool ../file11 ) &&
+               ( yes "d" | git mergetool ../file12 ) &&
+               ( yes "l" | git mergetool ../submod ) &&
                test "$(cat ../file1)" = "master updated" &&
                test "$(cat ../file2)" = "master new" &&
                test "$(cat ../submod/bar)" = "branch1 submodule" &&
@@ -209,9 +250,9 @@ test_expect_success 'mergetool skips autoresolved' '
        git submodule update -N &&
        test_must_fail git merge master &&
        test -n "$(git ls-files -u)" &&
-       ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
-       ( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
+       ( yes "d" | git mergetool file11 ) &&
+       ( yes "d" | git mergetool file12 ) &&
+       ( yes "l" | git mergetool submod ) &&
        output="$(git mergetool --no-prompt)" &&
        test "$output" = "No files need merging"
 '
@@ -259,9 +300,9 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' '
        rm -rf .git/rr-cache &&
        git checkout -b test$test_count branch1 &&
        git submodule update -N &&
-       test_must_fail git merge master >/dev/null 2>&1 &&
-       ( yes "l" | git mergetool --no-prompt submod >/dev/null 2>&1 ) &&
-       ( yes "d" "d" | git mergetool --no-prompt >/dev/null 2>&1 ) &&
+       test_must_fail git merge master &&
+       ( yes "l" | git mergetool --no-prompt submod ) &&
+       ( yes "d" "d" | git mergetool --no-prompt ) &&
        git submodule update -N &&
        output="$(yes "n" | git mergetool --no-prompt)" &&
        test "$output" = "No files need merging"
@@ -369,9 +410,9 @@ test_expect_success 'deleted vs modified submodule' '
        git checkout -b test$test_count.a test$test_count &&
        test_must_fail git merge master &&
        test -n "$(git ls-files -u)" &&
-       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
+       ( yes "" | git mergetool both ) &&
+       ( yes "d" | git mergetool file11 file12 ) &&
        ( yes "r" | git mergetool submod ) &&
        rmdir submod && mv submod-movedaside submod &&
        test "$(cat submod/bar)" = "branch1 submodule" &&
@@ -386,9 +427,9 @@ test_expect_success 'deleted vs modified submodule' '
        git submodule update -N &&
        test_must_fail git merge master &&
        test -n "$(git ls-files -u)" &&
-       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
+       ( yes "" | git mergetool both ) &&
+       ( yes "d" | git mergetool file11 file12 ) &&
        ( yes "l" | git mergetool submod ) &&
        test ! -e submod &&
        output="$(git mergetool --no-prompt)" &&
@@ -400,9 +441,9 @@ test_expect_success 'deleted vs modified submodule' '
        git submodule update -N &&
        test_must_fail git merge test$test_count &&
        test -n "$(git ls-files -u)" &&
-       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
+       ( yes "" | git mergetool both ) &&
+       ( yes "d" | git mergetool file11 file12 ) &&
        ( yes "r" | git mergetool submod ) &&
        test ! -e submod &&
        test -d submod.orig &&
@@ -416,9 +457,9 @@ test_expect_success 'deleted vs modified submodule' '
        git submodule update -N &&
        test_must_fail git merge test$test_count &&
        test -n "$(git ls-files -u)" &&
-       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
+       ( yes "" | git mergetool both ) &&
+       ( yes "d" | git mergetool file11 file12 ) &&
        ( yes "l" | git mergetool submod ) &&
        test "$(cat submod/bar)" = "master submodule" &&
        git submodule update -N &&
@@ -440,9 +481,9 @@ test_expect_success 'file vs modified submodule' '
        git checkout -b test$test_count.a branch1 &&
        test_must_fail git merge master &&
        test -n "$(git ls-files -u)" &&
-       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
+       ( yes "" | git mergetool both ) &&
+       ( yes "d" | git mergetool file11 file12 ) &&
        ( yes "r" | git mergetool submod ) &&
        rmdir submod && mv submod-movedaside submod &&
        test "$(cat submod/bar)" = "branch1 submodule" &&
@@ -456,9 +497,9 @@ test_expect_success 'file vs modified submodule' '
        git checkout -b test$test_count.b test$test_count &&
        test_must_fail git merge master &&
        test -n "$(git ls-files -u)" &&
-       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
+       ( yes "" | git mergetool both ) &&
+       ( yes "d" | git mergetool file11 file12 ) &&
        ( yes "l" | git mergetool submod ) &&
        git submodule update -N &&
        test "$(cat submod)" = "not a submodule" &&
@@ -472,9 +513,9 @@ test_expect_success 'file vs modified submodule' '
        git submodule update -N &&
        test_must_fail git merge test$test_count &&
        test -n "$(git ls-files -u)" &&
-       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
+       ( yes "" | git mergetool both ) &&
+       ( yes "d" | git mergetool file11 file12 ) &&
        ( yes "r" | git mergetool submod ) &&
        test -d submod.orig &&
        git submodule update -N &&
@@ -488,9 +529,9 @@ test_expect_success 'file vs modified submodule' '
        git submodule update -N &&
        test_must_fail git merge test$test_count &&
        test -n "$(git ls-files -u)" &&
-       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool both>/dev/null 2>&1 ) &&
-       ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
+       ( yes "" | git mergetool both ) &&
+       ( yes "d" | git mergetool file11 file12 ) &&
        ( yes "l" | git mergetool submod ) &&
        test "$(cat submod/bar)" = "master submodule" &&
        git submodule update -N &&
@@ -543,7 +584,7 @@ test_expect_success 'submodule in subdirectory' '
        git add subdir/subdir_module &&
        git commit -m "change submodule in subdirectory on test$test_count.b" &&
 
-       test_must_fail git merge test$test_count.a >/dev/null 2>&1 &&
+       test_must_fail git merge test$test_count.a &&
        (
                cd subdir &&
                ( yes "l" | git mergetool subdir_module )
@@ -554,7 +595,7 @@ test_expect_success 'submodule in subdirectory' '
        git reset --hard &&
        git submodule update -N &&
 
-       test_must_fail git merge test$test_count.a >/dev/null 2>&1 &&
+       test_must_fail git merge test$test_count.a &&
        ( yes "r" | git mergetool subdir/subdir_module ) &&
        test "$(cat subdir/subdir_module/file15)" = "test$test_count.b" &&
        git submodule update -N &&
@@ -641,7 +682,7 @@ test_expect_success 'filenames seen by tools start with ./' '
        test_config mergetool.myecho.trustExitCode true &&
        test_must_fail git merge master &&
        git mergetool --no-prompt --tool myecho -- both >actual &&
-       grep ^\./both_LOCAL_ actual >/dev/null
+       grep ^\./both_LOCAL_ actual
 '
 
 test_lazy_prereq MKTEMP '
@@ -658,8 +699,8 @@ test_expect_success MKTEMP 'temporary filenames are used with mergetool.writeToT
        test_config mergetool.myecho.trustExitCode true &&
        test_must_fail git merge master &&
        git mergetool --no-prompt --tool myecho -- both >actual &&
-       ! grep ^\./both_LOCAL_ actual >/dev/null &&
-       grep /both_LOCAL_ actual >/dev/null
+       ! grep ^\./both_LOCAL_ actual &&
+       grep /both_LOCAL_ actual
 '
 
 test_expect_success 'diff.orderFile configuration is honored' '
index 6162e2a8e66f6f0e42e0a8ba6ee3b728e8e84918..86d05160a3589cefd7ad21dbf64c655658f26342 100755 (executable)
@@ -221,5 +221,22 @@ test_expect_success 'repack --keep-pack' '
        )
 '
 
-test_done
+test_expect_success 'bitmaps are created by default in bare repos' '
+       git clone --bare .git bare.git &&
+       git -C bare.git repack -ad &&
+       bitmap=$(ls bare.git/objects/pack/*.bitmap) &&
+       test_path_is_file "$bitmap"
+'
+
+test_expect_success 'incremental repack does not complain' '
+       git -C bare.git repack -q 2>repack.err &&
+       test_must_be_empty repack.err
+'
 
+test_expect_success 'bitmaps can be disabled on bare repos' '
+       git -c repack.writeBitmaps=false -C bare.git repack -ad &&
+       bitmap=$(ls bare.git/objects/pack/*.bitmap 2>/dev/null || :) &&
+       test -z "$bitmap"
+'
+
+test_done
index 480dd0633fd3e979aecca82784d38642232d44b4..6bac9ed180e7342b34401b2d6af9e83b4472f08d 100755 (executable)
@@ -279,11 +279,27 @@ test_expect_success 'difftool + mergetool config variables' '
        echo branch >expect &&
        git difftool --no-prompt branch >actual &&
        test_cmp expect actual &&
+       git difftool --gui --no-prompt branch >actual &&
+       test_cmp expect actual &&
 
        # set merge.tool to something bogus, diff.tool to test-tool
        test_config merge.tool bogus-tool &&
        test_config diff.tool test-tool &&
        git difftool --no-prompt branch >actual &&
+       test_cmp expect actual &&
+       git difftool --gui --no-prompt branch >actual &&
+       test_cmp expect actual &&
+
+       # set merge.tool, diff.tool to something bogus, merge.guitool to test-tool
+       test_config diff.tool bogus-tool &&
+       test_config merge.guitool test-tool &&
+       git difftool --gui --no-prompt branch >actual &&
+       test_cmp expect actual &&
+
+       # set merge.tool, diff.tool, merge.guitool to something bogus, diff.guitool to test-tool
+       test_config merge.guitool bogus-tool &&
+       test_config diff.guitool test-tool &&
+       git difftool --gui --no-prompt branch >actual &&
        test_cmp expect actual
 '
 
@@ -715,4 +731,12 @@ test_expect_success 'outside worktree' '
        test_cmp expect actual
 '
 
+test_expect_success 'difftool --gui, --tool and --extcmd are mutually exclusive' '
+       difftool_test_setup &&
+       test_must_fail git difftool --gui --tool=test-tool &&
+       test_must_fail git difftool --gui --extcmd=cat &&
+       test_must_fail git difftool --tool=test-tool --extcmd=cat &&
+       test_must_fail git difftool --gui --tool=test-tool --extcmd=cat
+'
+
 test_done
diff --git a/tag.h b/tag.h
index e669c3e497a95bdeb08c4b45dec37a7d80b52ac4..03265fbfe2942f9ca7409cb2b771b14edd9fb998 100644 (file)
--- a/tag.h
+++ b/tag.h
@@ -11,13 +11,13 @@ struct tag {
        char *tag;
        timestamp_t date;
 };
-extern struct tag *lookup_tag(struct repository *r, const struct object_id *oid);
-extern int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, unsigned long size);
-extern int parse_tag(struct tag *item);
-extern void release_tag_memory(struct tag *t);
-extern struct object *deref_tag(struct repository *r, struct object *, const char *, int);
-extern struct object *deref_tag_noverify(struct object *);
-extern int gpg_verify_tag(const struct object_id *oid,
-               const char *name_to_report, unsigned flags);
+struct tag *lookup_tag(struct repository *r, const struct object_id *oid);
+int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, unsigned long size);
+int parse_tag(struct tag *item);
+void release_tag_memory(struct tag *t);
+struct object *deref_tag(struct repository *r, struct object *, const char *, int);
+struct object *deref_tag_noverify(struct object *);
+int gpg_verify_tag(const struct object_id *oid,
+                  const char *name_to_report, unsigned flags);
 
 #endif /* TAG_H */
index 61d8dc4d1bb2fc446ac7b452661064e615b4b5c9..cddda0a33c3e1ef39c6d294221fc9f7ae5205217 100644 (file)
@@ -89,7 +89,7 @@ struct tempfile {
  * a tempfile (whose "fd" member can be used for writing to it), or
  * NULL on error. It is an error if a file already exists at that path.
  */
-extern struct tempfile *create_tempfile(const char *path);
+struct tempfile *create_tempfile(const char *path);
 
 /*
  * Register an existing file as a tempfile, meaning that it will be
@@ -97,7 +97,7 @@ extern struct tempfile *create_tempfile(const char *path);
  * but it can be worked with like any other closed tempfile (for
  * example, it can be opened using reopen_tempfile()).
  */
-extern struct tempfile *register_tempfile(const char *path);
+struct tempfile *register_tempfile(const char *path);
 
 
 /*
@@ -136,8 +136,8 @@ extern struct tempfile *register_tempfile(const char *path);
  */
 
 /* See "mks_tempfile functions" above. */
-extern struct tempfile *mks_tempfile_sm(const char *filename_template,
-                                       int suffixlen, int mode);
+struct tempfile *mks_tempfile_sm(const char *filename_template,
+                                int suffixlen, int mode);
 
 /* See "mks_tempfile functions" above. */
 static inline struct tempfile *mks_tempfile_s(const char *filename_template,
@@ -159,8 +159,8 @@ static inline struct tempfile *mks_tempfile(const char *filename_template)
 }
 
 /* See "mks_tempfile functions" above. */
-extern struct tempfile *mks_tempfile_tsm(const char *filename_template,
-                                        int suffixlen, int mode);
+struct tempfile *mks_tempfile_tsm(const char *filename_template,
+                                 int suffixlen, int mode);
 
 /* See "mks_tempfile functions" above. */
 static inline struct tempfile *mks_tempfile_ts(const char *filename_template,
@@ -182,7 +182,7 @@ static inline struct tempfile *mks_tempfile_t(const char *filename_template)
 }
 
 /* See "mks_tempfile functions" above. */
-extern struct tempfile *xmks_tempfile_m(const char *filename_template, int mode);
+struct tempfile *xmks_tempfile_m(const char *filename_template, int mode);
 
 /* See "mks_tempfile functions" above. */
 static inline struct tempfile *xmks_tempfile(const char *filename_template)
@@ -196,7 +196,7 @@ static inline struct tempfile *xmks_tempfile(const char *filename_template)
  * stream is closed automatically when `close_tempfile_gently()` is called or
  * when the file is deleted or renamed.
  */
-extern FILE *fdopen_tempfile(struct tempfile *tempfile, const char *mode);
+FILE *fdopen_tempfile(struct tempfile *tempfile, const char *mode);
 
 static inline int is_tempfile_active(struct tempfile *tempfile)
 {
@@ -207,10 +207,10 @@ static inline int is_tempfile_active(struct tempfile *tempfile)
  * Return the path of the lockfile. The return value is a pointer to a
  * field within the lock_file object and should not be freed.
  */
-extern const char *get_tempfile_path(struct tempfile *tempfile);
+const char *get_tempfile_path(struct tempfile *tempfile);
 
-extern int get_tempfile_fd(struct tempfile *tempfile);
-extern FILE *get_tempfile_fp(struct tempfile *tempfile);
+int get_tempfile_fd(struct tempfile *tempfile);
+FILE *get_tempfile_fp(struct tempfile *tempfile);
 
 /*
  * If the temporary file is still open, close it (and the file pointer
@@ -220,7 +220,7 @@ extern FILE *get_tempfile_fp(struct tempfile *tempfile);
  * should eventually be called regardless of whether `close_tempfile_gently()`
  * succeeds.
  */
-extern int close_tempfile_gently(struct tempfile *tempfile);
+int close_tempfile_gently(struct tempfile *tempfile);
 
 /*
  * Re-open a temporary file that has been closed using
@@ -241,7 +241,7 @@ extern int close_tempfile_gently(struct tempfile *tempfile);
  *
  * * `rename_tempfile()` to move the file to its permanent location.
  */
-extern int reopen_tempfile(struct tempfile *tempfile);
+int reopen_tempfile(struct tempfile *tempfile);
 
 /*
  * Close the file descriptor and/or file pointer and remove the
@@ -249,7 +249,7 @@ extern int reopen_tempfile(struct tempfile *tempfile);
  * `delete_tempfile()` for a `tempfile` object that has already been
  * deleted or renamed.
  */
-extern void delete_tempfile(struct tempfile **tempfile_p);
+void delete_tempfile(struct tempfile **tempfile_p);
 
 /*
  * Close the file descriptor and/or file pointer if they are still
@@ -260,6 +260,6 @@ extern void delete_tempfile(struct tempfile **tempfile_p);
  * `rename(2)`. It is a bug to call `rename_tempfile()` for a
  * `tempfile` object that is not currently active.
  */
-extern int rename_tempfile(struct tempfile **tempfile_p, const char *path);
+int rename_tempfile(struct tempfile **tempfile_p, const char *path);
 
 #endif /* TEMPFILE_H */
diff --git a/trace.h b/trace.h
index 171b256d261c771927541cf4d431b926b3ba102b..9fa3e7a59407541d288da6ce2720279e2e23ab4e 100644 (file)
--- a/trace.h
+++ b/trace.h
@@ -17,34 +17,34 @@ extern struct trace_key trace_default_key;
 extern struct trace_key trace_perf_key;
 extern struct trace_key trace_setup_key;
 
-extern void trace_repo_setup(const char *prefix);
-extern int trace_want(struct trace_key *key);
-extern void trace_disable(struct trace_key *key);
-extern uint64_t getnanotime(void);
-extern void trace_command_performance(const char **argv);
-extern void trace_verbatim(struct trace_key *key, const void *buf, unsigned len);
+void trace_repo_setup(const char *prefix);
+int trace_want(struct trace_key *key);
+void trace_disable(struct trace_key *key);
+uint64_t getnanotime(void);
+void trace_command_performance(const char **argv);
+void trace_verbatim(struct trace_key *key, const void *buf, unsigned len);
 uint64_t trace_performance_enter(void);
 
 #ifndef HAVE_VARIADIC_MACROS
 
 __attribute__((format (printf, 1, 2)))
-extern void trace_printf(const char *format, ...);
+void trace_printf(const char *format, ...);
 
 __attribute__((format (printf, 2, 3)))
-extern void trace_printf_key(struct trace_key *key, const char *format, ...);
+void trace_printf_key(struct trace_key *key, const char *format, ...);
 
 __attribute__((format (printf, 2, 3)))
-extern void trace_argv_printf(const char **argv, const char *format, ...);
+void trace_argv_printf(const char **argv, const char *format, ...);
 
-extern void trace_strbuf(struct trace_key *key, const struct strbuf *data);
+void trace_strbuf(struct trace_key *key, const struct strbuf *data);
 
 /* Prints elapsed time (in nanoseconds) if GIT_TRACE_PERFORMANCE is enabled. */
 __attribute__((format (printf, 2, 3)))
-extern void trace_performance(uint64_t nanos, const char *format, ...);
+void trace_performance(uint64_t nanos, const char *format, ...);
 
 /* Prints elapsed time since 'start' if GIT_TRACE_PERFORMANCE is enabled. */
 __attribute__((format (printf, 2, 3)))
-extern void trace_performance_since(uint64_t start, const char *format, ...);
+void trace_performance_since(uint64_t start, const char *format, ...);
 
 __attribute__((format (printf, 1, 2)))
 void trace_performance_leave(const char *format, ...);
@@ -132,19 +132,19 @@ void trace_performance_leave(const char *format, ...);
 
 /* backend functions, use non-*fl macros instead */
 __attribute__((format (printf, 4, 5)))
-extern void trace_printf_key_fl(const char *file, int line, struct trace_key *key,
-                               const char *format, ...);
+void trace_printf_key_fl(const char *file, int line, struct trace_key *key,
+                        const char *format, ...);
 __attribute__((format (printf, 4, 5)))
-extern void trace_argv_printf_fl(const char *file, int line, const char **argv,
-                                const char *format, ...);
-extern void trace_strbuf_fl(const char *file, int line, struct trace_key *key,
-                           const struct strbuf *data);
+void trace_argv_printf_fl(const char *file, int line, const char **argv,
+                         const char *format, ...);
+void trace_strbuf_fl(const char *file, int line, struct trace_key *key,
+                    const struct strbuf *data);
 __attribute__((format (printf, 4, 5)))
-extern void trace_performance_fl(const char *file, int line,
-                                uint64_t nanos, const char *fmt, ...);
+void trace_performance_fl(const char *file, int line,
+                         uint64_t nanos, const char *fmt, ...);
 __attribute__((format (printf, 4, 5)))
-extern void trace_performance_leave_fl(const char *file, int line,
-                                      uint64_t nanos, const char *fmt, ...);
+void trace_performance_leave_fl(const char *file, int line,
+                               uint64_t nanos, const char *fmt, ...);
 static inline int trace_pass_fl(struct trace_key *key)
 {
        return key->fd || !key->initialized;
index 8bbad568871dc2a8526d47ae4cb9f36f49fcb7a3..c7b4f14d29a9d0ef38fba7595d15911757b9cbdb 100644 (file)
--- a/trace2.c
+++ b/trace2.c
@@ -10,6 +10,7 @@
 #include "trace2/tr2_cmd_name.h"
 #include "trace2/tr2_dst.h"
 #include "trace2/tr2_sid.h"
+#include "trace2/tr2_sysenv.h"
 #include "trace2/tr2_tgt.h"
 #include "trace2/tr2_tls.h"
 
@@ -120,6 +121,7 @@ static void tr2main_atexit_handler(void)
        tr2_sid_release();
        tr2_cmd_name_release();
        tr2_cfg_free_patterns();
+       tr2_sysenv_release();
 
        trace2_enabled = 0;
 }
@@ -142,6 +144,11 @@ static void tr2main_signal_handler(int signo)
        raise(signo);
 }
 
+void trace2_initialize_clock(void)
+{
+       tr2tls_start_process_clock();
+}
+
 void trace2_initialize_fl(const char *file, int line)
 {
        struct tr2_tgt *tgt_j;
@@ -150,6 +157,8 @@ void trace2_initialize_fl(const char *file, int line)
        if (trace2_enabled)
                return;
 
+       tr2_sysenv_load();
+
        if (!tr2_tgt_want_builtins())
                return;
        trace2_enabled = 1;
@@ -177,13 +186,19 @@ void trace2_cmd_start_fl(const char *file, int line, const char **argv)
 {
        struct tr2_tgt *tgt_j;
        int j;
+       uint64_t us_now;
+       uint64_t us_elapsed_absolute;
 
        if (!trace2_enabled)
                return;
 
+       us_now = getnanotime() / 1000;
+       us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
+
        for_each_wanted_builtin (j, tgt_j)
                if (tgt_j->pfn_start_fl)
-                       tgt_j->pfn_start_fl(file, line, argv);
+                       tgt_j->pfn_start_fl(file, line, us_elapsed_absolute,
+                                           argv);
 }
 
 int trace2_cmd_exit_fl(const char *file, int line, int code)
@@ -198,6 +213,8 @@ int trace2_cmd_exit_fl(const char *file, int line, int code)
        if (!trace2_enabled)
                return code;
 
+       trace2_collect_process_info(TRACE2_PROCESS_INFO_EXIT);
+
        tr2main_exit_code = code;
 
        us_now = getnanotime() / 1000;
@@ -428,7 +445,7 @@ void trace2_thread_start_fl(const char *file, int line, const char *thread_name)
        us_now = getnanotime() / 1000;
        us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
 
-       tr2tls_create_self(thread_name);
+       tr2tls_create_self(thread_name, us_now);
 
        for_each_wanted_builtin (j, tgt_j)
                if (tgt_j->pfn_thread_start_fl)
@@ -717,7 +734,7 @@ void trace2_data_json_fl(const char *file, int line, const char *category,
        us_elapsed_region = tr2tls_region_elasped_self(us_now);
 
        for_each_wanted_builtin (j, tgt_j)
-               if (tgt_j->pfn_data_fl)
+               if (tgt_j->pfn_data_json_fl)
                        tgt_j->pfn_data_json_fl(file, line, us_elapsed_absolute,
                                                us_elapsed_region, category,
                                                repo, key, value);
index b330a54a89a08c2e1f764db6708a8f55a7479f3b..f189ef5984f0e2e699a1a2a7a0e8fd93e5e0281c 100644 (file)
--- a/trace2.h
+++ b/trace2.h
@@ -19,9 +19,27 @@ struct json_writer;
  * [] trace2_printf*    -- legacy trace[1] messages.
  */
 
+/*
+ * Initialize the TRACE2 clock and do nothing else, in particular
+ * no mallocs, no system inspection, and no environment inspection.
+ *
+ * This should be called at the very top of main() to capture the
+ * process start time.  This is intended to reduce chicken-n-egg
+ * bootstrap pressure.
+ *
+ * It is safe to call this more than once.  This allows capturing
+ * absolute startup costs on Windows which uses a little trickery
+ * to do setup work before common-main.c:main() is called.
+ *
+ * The main trace2_initialize_fl() may be called a little later
+ * after more infrastructure is established.
+ */
+void trace2_initialize_clock(void);
+
 /*
  * Initialize TRACE2 tracing facility if any of the builtin TRACE2
- * targets are enabled in the environment.  Emits a 'version' event.
+ * targets are enabled in the system config or the environment.
+ * Emits a 'version' event.
  *
  * Cleanup/Termination is handled automatically by a registered
  * atexit() routine.
@@ -108,10 +126,11 @@ void trace2_cmd_alias_fl(const char *file, int line, const char *alias,
  * Emit one or more 'def_param' events for "interesting" configuration
  * settings.
  *
- * The environment variable "GIT_TR2_CONFIG_PARAMS" can be set to a
- * list of patterns considered important.  For example:
- *
- *    GIT_TR2_CONFIG_PARAMS="core.*,remote.*.url"
+ * Use the TR2_SYSENV_CFG_PARAM setting to register a comma-separated
+ * list of patterns configured important.  For example:
+ *     git config --system trace2.configParams 'core.*,remote.*.url'
+ * or:
+ *     GIT_TR2_CONFIG_PARAMS=core.*,remote.*.url"
  *
  * Note: this routine does a read-only iteration on the config data
  * (using read_early_config()), so it must not be called until enough
@@ -372,13 +391,19 @@ void trace2_printf(const char *fmt, ...);
  * Optional platform-specific code to dump information about the
  * current and any parent process(es).  This is intended to allow
  * post-processors to know who spawned this git instance and anything
- * else the platform may be able to tell us about the current process.
+ * else that the platform may be able to tell us about the current process.
  */
+
+enum trace2_process_info_reason {
+       TRACE2_PROCESS_INFO_STARTUP,
+       TRACE2_PROCESS_INFO_EXIT,
+};
+
 #if defined(GIT_WINDOWS_NATIVE)
-void trace2_collect_process_info(void);
+void trace2_collect_process_info(enum trace2_process_info_reason reason);
 #else
-#define trace2_collect_process_info() \
-       do {                          \
+#define trace2_collect_process_info(reason) \
+       do {                                \
        } while (0)
 #endif
 
index b329921ac5a583567485f03d69dbfa70ab8d680a..caa7f06948ab97c09ee9adf82a9588fcc07d6e52 100644 (file)
@@ -1,8 +1,7 @@
 #include "cache.h"
 #include "config.h"
-#include "tr2_cfg.h"
-
-#define TR2_ENVVAR_CFG_PARAM "GIT_TR2_CONFIG_PARAMS"
+#include "trace2/tr2_cfg.h"
+#include "trace2/tr2_sysenv.h"
 
 static struct strbuf **tr2_cfg_patterns;
 static int tr2_cfg_count_patterns;
@@ -21,7 +20,7 @@ static int tr2_cfg_load_patterns(void)
                return tr2_cfg_count_patterns;
        tr2_cfg_loaded = 1;
 
-       envvar = getenv(TR2_ENVVAR_CFG_PARAM);
+       envvar = tr2_sysenv_get(TR2_SYSENV_CFG_PARAM);
        if (!envvar || !*envvar)
                return tr2_cfg_count_patterns;
 
index c3d82ca6a4bd852ed175c0800f31ce08bfb32ea3..5dda0ca1cdb5d09a8cdfb27dd45d4436f3e8aa6f 100644 (file)
@@ -1,17 +1,7 @@
 #include "cache.h"
 #include "trace2/tr2_dst.h"
 #include "trace2/tr2_sid.h"
-
-/*
- * If a Trace2 target cannot be opened for writing, we should issue a
- * warning to stderr, but this is very annoying if the target is a pipe
- * or socket and beyond the user's control -- especially since every
- * git command (and sub-command) will print the message.  So we silently
- * eat these warnings and just discard the trace data.
- *
- * Enable the following environment variable to see these warnings.
- */
-#define TR2_ENVVAR_DST_DEBUG "GIT_TR2_DST_DEBUG"
+#include "trace2/tr2_sysenv.h"
 
 /*
  * How many attempts we will make at creating an automatically-named trace file.
@@ -23,7 +13,7 @@ static int tr2_dst_want_warning(void)
        static int tr2env_dst_debug = -1;
 
        if (tr2env_dst_debug == -1) {
-               const char *env_value = getenv(TR2_ENVVAR_DST_DEBUG);
+               const char *env_value = tr2_sysenv_get(TR2_SYSENV_DST_DEBUG);
                if (!env_value || !*env_value)
                        tr2env_dst_debug = 0;
                else
@@ -75,7 +65,8 @@ static int tr2_dst_try_auto_path(struct tr2_dst *dst, const char *tgt_prefix)
                if (tr2_dst_want_warning())
                        warning("trace2: could not open '%.*s' for '%s' tracing: %s",
                                (int) base_path_len, path.buf,
-                               dst->env_var_name, strerror(errno));
+                               tr2_sysenv_display_name(dst->sysenv_var),
+                               strerror(errno));
 
                tr2_dst_trace_disable(dst);
                strbuf_release(&path);
@@ -97,7 +88,9 @@ static int tr2_dst_try_path(struct tr2_dst *dst, const char *tgt_value)
        if (fd == -1) {
                if (tr2_dst_want_warning())
                        warning("trace2: could not open '%s' for '%s' tracing: %s",
-                               tgt_value, dst->env_var_name, strerror(errno));
+                               tgt_value,
+                               tr2_sysenv_display_name(dst->sysenv_var),
+                               strerror(errno));
 
                tr2_dst_trace_disable(dst);
                return 0;
@@ -171,7 +164,8 @@ static int tr2_dst_try_unix_domain_socket(struct tr2_dst *dst,
        if (!path || !*path) {
                if (tr2_dst_want_warning())
                        warning("trace2: invalid AF_UNIX value '%s' for '%s' tracing",
-                               tgt_value, dst->env_var_name);
+                               tgt_value,
+                               tr2_sysenv_display_name(dst->sysenv_var));
 
                tr2_dst_trace_disable(dst);
                return 0;
@@ -181,7 +175,7 @@ static int tr2_dst_try_unix_domain_socket(struct tr2_dst *dst,
            strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
                if (tr2_dst_want_warning())
                        warning("trace2: invalid AF_UNIX path '%s' for '%s' tracing",
-                               path, dst->env_var_name);
+                               path, tr2_sysenv_display_name(dst->sysenv_var));
 
                tr2_dst_trace_disable(dst);
                return 0;
@@ -203,7 +197,8 @@ static int tr2_dst_try_unix_domain_socket(struct tr2_dst *dst,
 error:
        if (tr2_dst_want_warning())
                warning("trace2: could not connect to socket '%s' for '%s' tracing: %s",
-                       path, dst->env_var_name, strerror(e));
+                       path, tr2_sysenv_display_name(dst->sysenv_var),
+                       strerror(e));
 
        tr2_dst_trace_disable(dst);
        return 0;
@@ -223,7 +218,7 @@ static void tr2_dst_malformed_warning(struct tr2_dst *dst,
        struct strbuf buf = STRBUF_INIT;
 
        strbuf_addf(&buf, "trace2: unknown value for '%s': '%s'",
-                   dst->env_var_name, tgt_value);
+                   tr2_sysenv_display_name(dst->sysenv_var), tgt_value);
        warning("%s", buf.buf);
 
        strbuf_release(&buf);
@@ -239,7 +234,7 @@ int tr2_dst_get_trace_fd(struct tr2_dst *dst)
 
        dst->initialized = 1;
 
-       tgt_value = getenv(dst->env_var_name);
+       tgt_value = tr2_sysenv_get(dst->sysenv_var);
 
        if (!tgt_value || !strcmp(tgt_value, "") || !strcmp(tgt_value, "0") ||
            !strcasecmp(tgt_value, "false")) {
@@ -305,7 +300,8 @@ void tr2_dst_write_line(struct tr2_dst *dst, struct strbuf *buf_line)
                return;
 
        if (tr2_dst_want_warning())
-               warning("unable to write trace to '%s': %s", dst->env_var_name,
+               warning("unable to write trace to '%s': %s",
+                       tr2_sysenv_display_name(dst->sysenv_var),
                        strerror(errno));
        tr2_dst_trace_disable(dst);
 }
index 9a64f05b0299df2444f7a1d93ccac77a713e40c2..3adf3bac139b1aa910b4aea0dc71e3b03ce722ed 100644 (file)
@@ -2,9 +2,10 @@
 #define TR2_DST_H
 
 struct strbuf;
+#include "trace2/tr2_sysenv.h"
 
 struct tr2_dst {
-       const char *const env_var_name;
+       enum tr2_sysenv_variable sysenv_var;
        int fd;
        unsigned int initialized : 1;
        unsigned int need_close : 1;
index 984524a43ce44536e1dc825995ee4e0aa80734fb..50470954783672d7642d3359c5c581ace5f7b86c 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "trace2/tr2_tbuf.h"
 #include "trace2/tr2_sid.h"
 
 #define TR2_ENVVAR_PARENT_SID "GIT_TR2_PARENT_SID"
@@ -6,6 +7,53 @@
 static struct strbuf tr2sid_buf = STRBUF_INIT;
 static int tr2sid_nr_git_parents;
 
+/*
+ * Compute the final component of the SID representing the current process.
+ * This should uniquely identify the process and be a valid filename (to
+ * allow writing trace2 data to per-process files).  It should also be fixed
+ * length for possible use as a database key.
+ *
+ * "<yyyymmdd>T<hhmmss>.<fraction>Z-<host>-<process>"
+ *
+ * where <host> is a 9 character string:
+ *    "H<first_8_chars_of_sha1_of_hostname>"
+ *    "Localhost" when no hostname.
+ *
+ * where <process> is a 9 character string containing the least signifcant
+ * 32 bits in the process-id.
+ *    "P<pid>"
+ * (This is an abribrary choice.  On most systems pid_t is a 32 bit value,
+ * so limit doesn't matter.  On larger systems, a truncated value is fine
+ * for our purposes here.)
+ */
+static void tr2_sid_append_my_sid_component(void)
+{
+       const struct git_hash_algo *algo = &hash_algos[GIT_HASH_SHA1];
+       struct tr2_tbuf tb_now;
+       git_hash_ctx ctx;
+       pid_t pid = getpid();
+       unsigned char hash[GIT_MAX_RAWSZ + 1];
+       char hex[GIT_MAX_HEXSZ + 1];
+       char hostname[HOST_NAME_MAX + 1];
+
+       tr2_tbuf_utc_datetime(&tb_now);
+       strbuf_addstr(&tr2sid_buf, tb_now.buf);
+
+       strbuf_addch(&tr2sid_buf, '-');
+       if (xgethostname(hostname, sizeof(hostname)))
+               strbuf_add(&tr2sid_buf, "Localhost", 9);
+       else {
+               algo->init_fn(&ctx);
+               algo->update_fn(&ctx, hostname, strlen(hostname));
+               algo->final_fn(hash, &ctx);
+               hash_to_hex_algop_r(hex, hash, algo);
+               strbuf_addch(&tr2sid_buf, 'H');
+               strbuf_add(&tr2sid_buf, hex, 8);
+       }
+
+       strbuf_addf(&tr2sid_buf, "-P%08"PRIx32, (uint32_t)pid);
+}
+
 /*
  * Compute a "unique" session id (SID) for the current process.  This allows
  * all events from this process to have a single label (much like a PID).
@@ -20,7 +68,6 @@ static int tr2sid_nr_git_parents;
  */
 static void tr2_sid_compute(void)
 {
-       uint64_t us_now;
        const char *parent_sid;
 
        if (tr2sid_buf.len)
@@ -38,9 +85,7 @@ static void tr2_sid_compute(void)
                tr2sid_nr_git_parents++;
        }
 
-       us_now = getnanotime() / 1000;
-       strbuf_addf(&tr2sid_buf, "%" PRIuMAX "-%" PRIdMAX, (uintmax_t)us_now,
-                   (intmax_t)getpid());
+       tr2_sid_append_my_sid_component();
 
        setenv(TR2_ENVVAR_PARENT_SID, tr2sid_buf.buf, 1);
 }
diff --git a/trace2/tr2_sysenv.c b/trace2/tr2_sysenv.c
new file mode 100644 (file)
index 0000000..9025b86
--- /dev/null
@@ -0,0 +1,127 @@
+#include "cache.h"
+#include "config.h"
+#include "dir.h"
+#include "tr2_sysenv.h"
+
+/*
+ * Each entry represents a trace2 setting.
+ * See Documentation/technical/api-trace2.txt
+ */
+struct tr2_sysenv_entry {
+       const char *env_var_name;
+       const char *git_config_name;
+
+       char *value;
+       unsigned int getenv_called : 1;
+};
+
+/*
+ * This table must match "enum tr2_sysenv_variable" in tr2_sysenv.h.
+ *
+ * The strings in this table are constant and must match the published
+ * config and environment variable names as described in the documentation.
+ *
+ * We do not define entries for the GIT_TR2_PARENT_* environment
+ * variables because they are transient and used to pass information
+ * from parent to child git processes, rather than settings.
+ */
+/* clang-format off */
+static struct tr2_sysenv_entry tr2_sysenv_settings[] = {
+       [TR2_SYSENV_CFG_PARAM]     = { "GIT_TR2_CONFIG_PARAMS",
+                                      "trace2.configparams" },
+
+       [TR2_SYSENV_DST_DEBUG]     = { "GIT_TR2_DST_DEBUG",
+                                      "trace2.destinationdebug" },
+
+       [TR2_SYSENV_NORMAL]        = { "GIT_TR2",
+                                      "trace2.normaltarget" },
+       [TR2_SYSENV_NORMAL_BRIEF]  = { "GIT_TR2_BRIEF",
+                                      "trace2.normalbrief" },
+
+       [TR2_SYSENV_EVENT]         = { "GIT_TR2_EVENT",
+                                      "trace2.eventtarget" },
+       [TR2_SYSENV_EVENT_BRIEF]   = { "GIT_TR2_EVENT_BRIEF",
+                                      "trace2.eventbrief" },
+       [TR2_SYSENV_EVENT_NESTING] = { "GIT_TR2_EVENT_NESTING",
+                                      "trace2.eventnesting" },
+
+       [TR2_SYSENV_PERF]          = { "GIT_TR2_PERF",
+                                      "trace2.perftarget" },
+       [TR2_SYSENV_PERF_BRIEF]    = { "GIT_TR2_PERF_BRIEF",
+                                      "trace2.perfbrief" },
+};
+/* clang-format on */
+
+static int tr2_sysenv_cb(const char *key, const char *value, void *d)
+{
+       int k;
+
+       if (!starts_with(key, "trace2."))
+               return 0;
+
+       for (k = 0; k < ARRAY_SIZE(tr2_sysenv_settings); k++) {
+               if (!strcmp(key, tr2_sysenv_settings[k].git_config_name)) {
+                       free(tr2_sysenv_settings[k].value);
+                       tr2_sysenv_settings[k].value = xstrdup(value);
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Load Trace2 settings from the system config (usually "/etc/gitconfig"
+ * unless we were built with a runtime-prefix).  These are intended to
+ * define the default values for Trace2 as requested by the administrator.
+ *
+ * Then override with the Trace2 settings from the global config.
+ */
+void tr2_sysenv_load(void)
+{
+       if (ARRAY_SIZE(tr2_sysenv_settings) != TR2_SYSENV_MUST_BE_LAST)
+               BUG("tr2_sysenv_settings size is wrong");
+
+       read_very_early_config(tr2_sysenv_cb, NULL);
+}
+
+/*
+ * Return the value for the requested Trace2 setting from these sources:
+ * the system config, the global config, and the environment.
+ */
+const char *tr2_sysenv_get(enum tr2_sysenv_variable var)
+{
+       if (var >= TR2_SYSENV_MUST_BE_LAST)
+               BUG("tr2_sysenv_get invalid var '%d'", var);
+
+       if (!tr2_sysenv_settings[var].getenv_called) {
+               const char *v = getenv(tr2_sysenv_settings[var].env_var_name);
+               if (v && *v) {
+                       free(tr2_sysenv_settings[var].value);
+                       tr2_sysenv_settings[var].value = xstrdup(v);
+               }
+               tr2_sysenv_settings[var].getenv_called = 1;
+       }
+
+       return tr2_sysenv_settings[var].value;
+}
+
+/*
+ * Return a friendly name for this setting that is suitable for printing
+ * in an error messages.
+ */
+const char *tr2_sysenv_display_name(enum tr2_sysenv_variable var)
+{
+       if (var >= TR2_SYSENV_MUST_BE_LAST)
+               BUG("tr2_sysenv_get invalid var '%d'", var);
+
+       return tr2_sysenv_settings[var].env_var_name;
+}
+
+void tr2_sysenv_release(void)
+{
+       int k;
+
+       for (k = 0; k < ARRAY_SIZE(tr2_sysenv_settings); k++)
+               free(tr2_sysenv_settings[k].value);
+}
diff --git a/trace2/tr2_sysenv.h b/trace2/tr2_sysenv.h
new file mode 100644 (file)
index 0000000..369b20b
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef TR2_SYSENV_H
+#define TR2_SYSENV_H
+
+/*
+ * The Trace2 settings that can be loaded from /etc/gitconfig
+ * and/or user environment variables.
+ *
+ * Note that this set does not contain any of the transient
+ * environment variables used to pass information from parent
+ * to child git processes, such "GIT_TR2_PARENT_SID".
+ */
+enum tr2_sysenv_variable {
+       TR2_SYSENV_CFG_PARAM = 0,
+
+       TR2_SYSENV_DST_DEBUG,
+
+       TR2_SYSENV_NORMAL,
+       TR2_SYSENV_NORMAL_BRIEF,
+
+       TR2_SYSENV_EVENT,
+       TR2_SYSENV_EVENT_BRIEF,
+       TR2_SYSENV_EVENT_NESTING,
+
+       TR2_SYSENV_PERF,
+       TR2_SYSENV_PERF_BRIEF,
+
+       TR2_SYSENV_MUST_BE_LAST
+};
+
+void tr2_sysenv_load(void);
+
+const char *tr2_sysenv_get(enum tr2_sysenv_variable);
+const char *tr2_sysenv_display_name(enum tr2_sysenv_variable var);
+void tr2_sysenv_release(void);
+
+#endif /* TR2_SYSENV_H */
index 0844910423679374bcf418bf1abd79c8edddcbe7..2498482d9ad82a29b2e734b0d726599d594a20c6 100644 (file)
@@ -15,7 +15,7 @@ void tr2_tbuf_local_time(struct tr2_tbuf *tb)
                  tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
 }
 
-void tr2_tbuf_utc_time(struct tr2_tbuf *tb)
+void tr2_tbuf_utc_datetime_extended(struct tr2_tbuf *tb)
 {
        struct timeval tv;
        struct tm tm;
@@ -26,7 +26,22 @@ void tr2_tbuf_utc_time(struct tr2_tbuf *tb)
        gmtime_r(&secs, &tm);
 
        xsnprintf(tb->buf, sizeof(tb->buf),
-                 "%4d-%02d-%02d %02d:%02d:%02d.%06ld", tm.tm_year + 1900,
+                 "%4d-%02d-%02dT%02d:%02d:%02d.%06ldZ", tm.tm_year + 1900,
                  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
                  (long)tv.tv_usec);
 }
+
+void tr2_tbuf_utc_datetime(struct tr2_tbuf *tb)
+{
+       struct timeval tv;
+       struct tm tm;
+       time_t secs;
+
+       gettimeofday(&tv, NULL);
+       secs = tv.tv_sec;
+       gmtime_r(&secs, &tm);
+
+       xsnprintf(tb->buf, sizeof(tb->buf), "%4d%02d%02dT%02d%02d%02d.%06ldZ",
+                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
+                 tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
+}
index 9cdefa395749f02286c4f821d51bf78c6c06d181..fa853d8f4211b5c34ec592308cf028e3dbd0b406 100644 (file)
@@ -16,8 +16,9 @@ struct tr2_tbuf {
 void tr2_tbuf_local_time(struct tr2_tbuf *tb);
 
 /*
- * Fill buffer with formatted UTC time string.
+ * Fill buffer with formatted UTC datatime string.
  */
-void tr2_tbuf_utc_time(struct tr2_tbuf *tb);
+void tr2_tbuf_utc_datetime_extended(struct tr2_tbuf *tb);
+void tr2_tbuf_utc_datetime(struct tr2_tbuf *tb);
 
 #endif /* TR2_TBUF_H */
index 297bb8ffbe498358b41e697c892c259871a6a937..7b904692123e28074458fce0c0afe06922caa607 100644 (file)
@@ -15,6 +15,7 @@ typedef void(tr2_tgt_term_t)(void);
 typedef void(tr2_tgt_evt_version_fl_t)(const char *file, int line);
 
 typedef void(tr2_tgt_evt_start_fl_t)(const char *file, int line,
+                                    uint64_t us_elapsed_absolute,
                                     const char **argv);
 typedef void(tr2_tgt_evt_exit_fl_t)(const char *file, int line,
                                    uint64_t us_elapsed_absolute, int code);
index 1cf4f62441c9307d610ebb0274ddb272ec2b8f01..c2852d1bd2bd856d518b5ce499d38e7b13bb452c 100644 (file)
@@ -6,10 +6,11 @@
 #include "trace2/tr2_dst.h"
 #include "trace2/tr2_tbuf.h"
 #include "trace2/tr2_sid.h"
+#include "trace2/tr2_sysenv.h"
 #include "trace2/tr2_tgt.h"
 #include "trace2/tr2_tls.h"
 
-static struct tr2_dst tr2dst_event = { "GIT_TR2_EVENT", 0, 0, 0 };
+static struct tr2_dst tr2dst_event = { TR2_SYSENV_EVENT, 0, 0, 0 };
 
 /*
  * The version number of the JSON data generated by the EVENT target
@@ -28,37 +29,36 @@ static struct tr2_dst tr2dst_event = { "GIT_TR2_EVENT", 0, 0, 0 };
  * are primarily intended for the performance target during debugging.
  *
  * Some of the outer-most messages, however, may be of interest to the
- * event target.  Set this environment variable to a larger integer for
- * more detail in the event target.
+ * event target.  Use the TR2_SYSENV_EVENT_NESTING setting to increase
+ * region details in the event target.
  */
-#define TR2_ENVVAR_EVENT_NESTING "GIT_TR2_EVENT_NESTING"
-static int tr2env_event_nesting_wanted = 2;
+static int tr2env_event_max_nesting_levels = 2;
 
 /*
- * Set this environment variable to true to omit the <time>, <file>, and
+ * Use the TR2_SYSENV_EVENT_BRIEF to omit the <time>, <file>, and
  * <line> fields from most events.
  */
-#define TR2_ENVVAR_EVENT_BRIEF "GIT_TR2_EVENT_BRIEF"
-static int tr2env_event_brief;
+static int tr2env_event_be_brief;
 
 static int fn_init(void)
 {
        int want = tr2_dst_trace_want(&tr2dst_event);
-       int want_nesting;
+       int max_nesting;
        int want_brief;
-       char *nesting;
-       char *brief;
+       const char *nesting;
+       const char *brief;
 
        if (!want)
                return want;
 
-       nesting = getenv(TR2_ENVVAR_EVENT_NESTING);
-       if (nesting && ((want_nesting = atoi(nesting)) > 0))
-               tr2env_event_nesting_wanted = want_nesting;
+       nesting = tr2_sysenv_get(TR2_SYSENV_EVENT_NESTING);
+       if (nesting && *nesting && ((max_nesting = atoi(nesting)) > 0))
+               tr2env_event_max_nesting_levels = max_nesting;
 
-       brief = getenv(TR2_ENVVAR_EVENT_BRIEF);
-       if (brief && ((want_brief = atoi(brief)) > 0))
-               tr2env_event_brief = want_brief;
+       brief = tr2_sysenv_get(TR2_SYSENV_EVENT_BRIEF);
+       if (brief && *brief &&
+           ((want_brief = git_parse_maybe_bool(brief)) != -1))
+               tr2env_event_be_brief = want_brief;
 
        return want;
 }
@@ -92,13 +92,13 @@ static void event_fmt_prepare(const char *event_name, const char *file,
        /*
         * In brief mode, only emit <time> on these 2 event types.
         */
-       if (!tr2env_event_brief || !strcmp(event_name, "version") ||
+       if (!tr2env_event_be_brief || !strcmp(event_name, "version") ||
            !strcmp(event_name, "atexit")) {
-               tr2_tbuf_utc_time(&tb_now);
+               tr2_tbuf_utc_datetime_extended(&tb_now);
                jw_object_string(jw, "time", tb_now.buf);
        }
 
-       if (!tr2env_event_brief && file && *file) {
+       if (!tr2env_event_be_brief && file && *file) {
                jw_object_string(jw, "file", file);
                jw_object_intmax(jw, "line", line);
        }
@@ -122,13 +122,16 @@ static void fn_version_fl(const char *file, int line)
        jw_release(&jw);
 }
 
-static void fn_start_fl(const char *file, int line, const char **argv)
+static void fn_start_fl(const char *file, int line,
+                       uint64_t us_elapsed_absolute, const char **argv)
 {
        const char *event_name = "start";
        struct json_writer jw = JSON_WRITER_INIT;
+       double t_abs = (double)us_elapsed_absolute / 1000000.0;
 
        jw_object_begin(&jw, 0);
        event_fmt_prepare(event_name, file, line, NULL, &jw);
+       jw_object_double(&jw, "t_abs", 6, t_abs);
        jw_object_inline_begin_array(&jw, "argv");
        jw_array_argv(&jw, argv);
        jw_end(&jw);
@@ -456,7 +459,7 @@ static void fn_region_enter_printf_va_fl(const char *file, int line,
 {
        const char *event_name = "region_enter";
        struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
-       if (ctx->nr_open_regions <= tr2env_event_nesting_wanted) {
+       if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
                struct json_writer jw = JSON_WRITER_INIT;
 
                jw_object_begin(&jw, 0);
@@ -481,7 +484,7 @@ static void fn_region_leave_printf_va_fl(
 {
        const char *event_name = "region_leave";
        struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
-       if (ctx->nr_open_regions <= tr2env_event_nesting_wanted) {
+       if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
                struct json_writer jw = JSON_WRITER_INIT;
                double t_rel = (double)us_elapsed_region / 1000000.0;
 
@@ -508,7 +511,7 @@ static void fn_data_fl(const char *file, int line, uint64_t us_elapsed_absolute,
 {
        const char *event_name = "data";
        struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
-       if (ctx->nr_open_regions <= tr2env_event_nesting_wanted) {
+       if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
                struct json_writer jw = JSON_WRITER_INIT;
                double t_abs = (double)us_elapsed_absolute / 1000000.0;
                double t_rel = (double)us_elapsed_region / 1000000.0;
@@ -536,7 +539,7 @@ static void fn_data_json_fl(const char *file, int line,
 {
        const char *event_name = "data_json";
        struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
-       if (ctx->nr_open_regions <= tr2env_event_nesting_wanted) {
+       if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
                struct json_writer jw = JSON_WRITER_INIT;
                double t_abs = (double)us_elapsed_absolute / 1000000.0;
                double t_rel = (double)us_elapsed_region / 1000000.0;
index 1a07d70abd6de281fc2a865f026fbb2e426adf96..00b116d797c844cd7320542a9829e94ee1e0311c 100644 (file)
@@ -4,20 +4,20 @@
 #include "quote.h"
 #include "version.h"
 #include "trace2/tr2_dst.h"
+#include "trace2/tr2_sysenv.h"
 #include "trace2/tr2_tbuf.h"
 #include "trace2/tr2_tgt.h"
 #include "trace2/tr2_tls.h"
 
-static struct tr2_dst tr2dst_normal = { "GIT_TR2", 0, 0, 0 };
+static struct tr2_dst tr2dst_normal = { TR2_SYSENV_NORMAL, 0, 0, 0 };
 
 /*
- * Set this environment variable to true to omit the "<time> <file>:<line>"
+ * Use the TR2_SYSENV_NORMAL_BRIEF setting to omit the "<time> <file>:<line>"
  * fields from each line written to the builtin normal target.
  *
  * Unit tests may want to use this to help with testing.
  */
-#define TR2_ENVVAR_NORMAL_BRIEF "GIT_TR2_BRIEF"
-static int tr2env_normal_brief;
+static int tr2env_normal_be_brief;
 
 #define TR2FMT_NORMAL_FL_WIDTH (50)
 
@@ -25,15 +25,15 @@ static int fn_init(void)
 {
        int want = tr2_dst_trace_want(&tr2dst_normal);
        int want_brief;
-       char *brief;
+       const char *brief;
 
        if (!want)
                return want;
 
-       brief = getenv(TR2_ENVVAR_NORMAL_BRIEF);
+       brief = tr2_sysenv_get(TR2_SYSENV_NORMAL_BRIEF);
        if (brief && *brief &&
            ((want_brief = git_parse_maybe_bool(brief)) != -1))
-               tr2env_normal_brief = want_brief;
+               tr2env_normal_be_brief = want_brief;
 
        return want;
 }
@@ -47,7 +47,7 @@ static void normal_fmt_prepare(const char *file, int line, struct strbuf *buf)
 {
        strbuf_setlen(buf, 0);
 
-       if (!tr2env_normal_brief) {
+       if (!tr2env_normal_be_brief) {
                struct tr2_tbuf tb_now;
 
                tr2_tbuf_local_time(&tb_now);
@@ -81,7 +81,8 @@ static void fn_version_fl(const char *file, int line)
        strbuf_release(&buf_payload);
 }
 
-static void fn_start_fl(const char *file, int line, const char **argv)
+static void fn_start_fl(const char *file, int line,
+                       uint64_t us_elapsed_absolute, const char **argv)
 {
        struct strbuf buf_payload = STRBUF_INIT;
 
index 2a866d701b201d36521cbd7d860d23f378a0f5b7..ea0cbbe13ee06629b2619704a4f9ae6714dc1b7d 100644 (file)
@@ -6,20 +6,20 @@
 #include "json-writer.h"
 #include "trace2/tr2_dst.h"
 #include "trace2/tr2_sid.h"
+#include "trace2/tr2_sysenv.h"
 #include "trace2/tr2_tbuf.h"
 #include "trace2/tr2_tgt.h"
 #include "trace2/tr2_tls.h"
 
-static struct tr2_dst tr2dst_perf = { "GIT_TR2_PERF", 0, 0, 0 };
+static struct tr2_dst tr2dst_perf = { TR2_SYSENV_PERF, 0, 0, 0 };
 
 /*
- * Set this environment variable to true to omit the "<time> <file>:<line>"
+ * Use TR2_SYSENV_PERF_BRIEF to omit the "<time> <file>:<line>"
  * fields from each line written to the builtin performance target.
  *
  * Unit tests may want to use this to help with testing.
  */
-#define TR2_ENVVAR_PERF_BRIEF "GIT_TR2_PERF_BRIEF"
-static int tr2env_perf_brief;
+static int tr2env_perf_be_brief;
 
 #define TR2FMT_PERF_FL_WIDTH (50)
 #define TR2FMT_PERF_MAX_EVENT_NAME (12)
@@ -36,17 +36,17 @@ static int fn_init(void)
 {
        int want = tr2_dst_trace_want(&tr2dst_perf);
        int want_brief;
-       char *brief;
+       const char *brief;
 
        if (!want)
                return want;
 
        strbuf_addchars(&dots, '.', TR2_DOTS_BUFFER_SIZE);
 
-       brief = getenv(TR2_ENVVAR_PERF_BRIEF);
+       brief = tr2_sysenv_get(TR2_SYSENV_PERF_BRIEF);
        if (brief && *brief &&
            ((want_brief = git_parse_maybe_bool(brief)) != -1))
-               tr2env_perf_brief = want_brief;
+               tr2env_perf_be_brief = want_brief;
 
        return want;
 }
@@ -77,7 +77,7 @@ static void perf_fmt_prepare(const char *event_name,
 
        strbuf_setlen(buf, 0);
 
-       if (!tr2env_perf_brief) {
+       if (!tr2env_perf_be_brief) {
                struct tr2_tbuf tb_now;
 
                tr2_tbuf_local_time(&tb_now);
@@ -159,15 +159,16 @@ static void fn_version_fl(const char *file, int line)
        strbuf_release(&buf_payload);
 }
 
-static void fn_start_fl(const char *file, int line, const char **argv)
+static void fn_start_fl(const char *file, int line,
+                       uint64_t us_elapsed_absolute, const char **argv)
 {
        const char *event_name = "start";
        struct strbuf buf_payload = STRBUF_INIT;
 
        sq_quote_argv_pretty(&buf_payload, argv);
 
-       perf_io_write_fl(file, line, event_name, NULL, NULL, NULL, NULL,
-                        &buf_payload);
+       perf_io_write_fl(file, line, event_name, NULL, &us_elapsed_absolute,
+                        NULL, NULL, &buf_payload);
        strbuf_release(&buf_payload);
 }
 
index 8e65b0361dbedb7360d3d0f30229875faf5088d4..e76d8c5d92aec764280506bb78cd7e4a3e48eeb2 100644 (file)
 #define TR2_REGION_NESTING_INITIAL_SIZE (100)
 
 static struct tr2tls_thread_ctx *tr2tls_thread_main;
-static uint64_t tr2tls_us_start_main;
+static uint64_t tr2tls_us_start_process;
 
 static pthread_mutex_t tr2tls_mutex;
 static pthread_key_t tr2tls_key;
 
 static int tr2_next_thread_id; /* modify under lock */
 
-struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_name)
+void tr2tls_start_process_clock(void)
+{
+       if (tr2tls_us_start_process)
+               return;
+
+       /*
+        * Keep the absolute start time of the process (i.e. the main
+        * process) in a fixed variable since other threads need to
+        * access it.  This allows them to do that without a lock on
+        * main thread's array data (because of reallocs).
+        */
+       tr2tls_us_start_process = getnanotime() / 1000;
+}
+
+struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_name,
+                                            uint64_t us_thread_start)
 {
-       uint64_t us_now = getnanotime() / 1000;
        struct tr2tls_thread_ctx *ctx = xcalloc(1, sizeof(*ctx));
 
        /*
@@ -29,7 +43,7 @@ struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_name)
         */
        ctx->alloc = TR2_REGION_NESTING_INITIAL_SIZE;
        ctx->array_us_start = (uint64_t *)xcalloc(ctx->alloc, sizeof(uint64_t));
-       ctx->array_us_start[ctx->nr_open_regions++] = us_now;
+       ctx->array_us_start[ctx->nr_open_regions++] = us_thread_start;
 
        ctx->thread_id = tr2tls_locked_increment(&tr2_next_thread_id);
 
@@ -55,7 +69,7 @@ struct tr2tls_thread_ctx *tr2tls_get_self(void)
         * here and silently continue.
         */
        if (!ctx)
-               ctx = tr2tls_create_self("unknown");
+               ctx = tr2tls_create_self("unknown", getnanotime() / 1000);
 
        return ctx;
 }
@@ -124,22 +138,18 @@ uint64_t tr2tls_absolute_elapsed(uint64_t us)
        if (!tr2tls_thread_main)
                return 0;
 
-       return us - tr2tls_us_start_main;
+       return us - tr2tls_us_start_process;
 }
 
 void tr2tls_init(void)
 {
+       tr2tls_start_process_clock();
+
        pthread_key_create(&tr2tls_key, NULL);
        init_recursive_mutex(&tr2tls_mutex);
 
-       tr2tls_thread_main = tr2tls_create_self("main");
-       /*
-        * Keep a copy of the absolute start time of the main thread
-        * in a fixed variable since other threads need to access it.
-        * This also eliminates the need to lock accesses to the main
-        * thread's array (because of reallocs).
-        */
-       tr2tls_us_start_main = tr2tls_thread_main->array_us_start[0];
+       tr2tls_thread_main =
+               tr2tls_create_self("main", tr2tls_us_start_process);
 }
 
 void tr2tls_release(void)
index bb80e3f8e7570533883e71741b9aa35d43362599..b1e327a928e2ba084714770c85c15a219dab35f3 100644 (file)
@@ -31,7 +31,8 @@ struct tr2tls_thread_ctx {
  * In this and all following functions the term "self" refers to the
  * current thread.
  */
-struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_name);
+struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_name,
+                                            uint64_t us_thread_start);
 
 /*
  * Get our TLS data.
@@ -94,4 +95,9 @@ void tr2tls_release(void);
  */
 int tr2tls_locked_increment(int *p);
 
+/*
+ * Capture the process start time and do nothing else.
+ */
+void tr2tls_start_process_clock(void);
+
 #endif /* TR2_TLS_H */
index f2ee7c4f499a0937ba4c7148db045665fcb7e4cf..06e06d3d8937bc553ef42cd895ee7132c6e5639c 100644 (file)
@@ -134,7 +134,7 @@ struct transport {
 #define TRANSPORT_PUSH_OPTIONS                 (1<<14)
 #define TRANSPORT_RECURSE_SUBMODULES_ONLY      (1<<15)
 
-extern int transport_summary_width(const struct ref *refs);
+int transport_summary_width(const struct ref *refs);
 
 /* Returns a transport suitable for the url */
 struct transport *transport_get(struct remote *, const char *);
@@ -263,5 +263,5 @@ void transport_print_push_status(const char *dest, struct ref *refs,
                  int verbose, int porcelain, unsigned int *reject_reasons);
 
 typedef void alternate_ref_fn(const struct object_id *oid, void *);
-extern void for_each_alternate_ref(alternate_ref_fn, void *);
+void for_each_alternate_ref(alternate_ref_fn, void *);
 #endif
index 3aa381b6a3dd20e4d98f781dde6bcf27bc8b055b..161e2400f443460fc6606e97d4e356c1f0b478ed 100644 (file)
@@ -67,8 +67,8 @@ struct traverse_info {
 };
 
 int get_tree_entry(const struct object_id *, const char *, struct object_id *, unsigned short *);
-extern char *make_traverse_path(char *path, const struct traverse_info *info, const struct name_entry *n);
-extern void setup_traverse_info(struct traverse_info *info, const char *base);
+char *make_traverse_path(char *path, const struct traverse_info *info, const struct name_entry *n);
+void setup_traverse_info(struct traverse_info *info, const char *base);
 
 static inline int traverse_path_len(const struct traverse_info *info, const struct name_entry *n)
 {
index d2ea5eb20d90557de4dc979d98a9479e0c2e7d9b..24298913c0d7932e20f4677d3b8a4ea62ed69f8d 100644 (file)
@@ -1069,6 +1069,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
                allow_ref_in_want = git_config_bool(var, value);
        } else if (!strcmp("uploadpack.allowsidebandall", var)) {
                allow_sideband_all = git_config_bool(var, value);
+       } else if (!strcmp("core.precomposeunicode", var)) {
+               precomposed_unicode = git_config_bool(var, value);
        }
 
        if (current_config_scope() != CONFIG_SCOPE_REPO) {
index cab2178796a6406ed154c56bc9e06e54ba41c6f6..4bafe16a22c37d3eac65690cc6f1cc68476cf94c 100644 (file)
@@ -13,11 +13,11 @@ void upload_pack(struct upload_pack_options *options);
 struct repository;
 struct argv_array;
 struct packet_reader;
-extern int upload_pack_v2(struct repository *r, struct argv_array *keys,
-                         struct packet_reader *request);
+int upload_pack_v2(struct repository *r, struct argv_array *keys,
+                  struct packet_reader *request);
 
 struct strbuf;
-extern int upload_pack_advertise(struct repository *r,
-                                struct strbuf *value);
+int upload_pack_advertise(struct repository *r,
+                         struct strbuf *value);
 
 #endif /* UPLOAD_PACK_H */
diff --git a/url.h b/url.h
index f311c40a4680bfedf0ad2d511a5599fb5dcabd6e..00b7d58c33e38b2a48e4e2ab557239b1ed0c759d 100644 (file)
--- a/url.h
+++ b/url.h
@@ -3,14 +3,14 @@
 
 struct strbuf;
 
-extern int is_url(const char *url);
-extern int is_urlschemechar(int first_flag, int ch);
-extern char *url_decode(const char *url);
-extern char *url_decode_mem(const char *url, int len);
-extern char *url_decode_parameter_name(const char **query);
-extern char *url_decode_parameter_value(const char **query);
+int is_url(const char *url);
+int is_urlschemechar(int first_flag, int ch);
+char *url_decode(const char *url);
+char *url_decode_mem(const char *url, int len);
+char *url_decode_parameter_name(const char **query);
+char *url_decode_parameter_value(const char **query);
 
-extern void end_url_with_slash(struct strbuf *buf, const char *url);
-extern void str_end_url_with_slash(const char *url, char **dest);
+void end_url_with_slash(struct strbuf *buf, const char *url);
+void str_end_url_with_slash(const char *url, char **dest);
 
 #endif /* URL_H */
index e482148248d2dac64656bd9a66af0bd6224ea929..eed5f292354cfef466f15f29ef944450e10d4d1a 100644 (file)
@@ -33,7 +33,7 @@ struct url_info {
                                 * '?...' and '#...' portion; will always be >= 1 */
 };
 
-extern char *url_normalize(const char *, struct url_info *);
+char *url_normalize(const char *, struct url_info *);
 
 struct urlmatch_item {
        size_t hostmatch_len;
@@ -52,6 +52,6 @@ struct urlmatch_config {
        int (*cascade_fn)(const char *var, const char *value, void *cb);
 };
 
-extern int urlmatch_config_entry(const char *var, const char *value, void *cb);
+int urlmatch_config_entry(const char *var, const char *value, void *cb);
 
 #endif /* URL_MATCH_H */
diff --git a/utf8.h b/utf8.h
index 84efbfcb1fa163b5b799add81b4464ff6eb88611..fcd5167bafb38ddafc3c4e22b642b87fb935c8e1 100644 (file)
--- a/utf8.h
+++ b/utf8.h
@@ -16,7 +16,7 @@ __attribute__((format (printf, 2, 3)))
 int utf8_fprintf(FILE *, const char *, ...);
 
 extern const char utf8_bom[];
-extern int skip_utf8_bom(char **, size_t);
+int skip_utf8_bom(char **, size_t);
 
 void strbuf_add_wrapped_text(struct strbuf *buf,
                const char *text, int indent, int indent2, int width);
index c1c44d9a6bde4853f55d6c8d7cd59ad159ef4abb..f78bb0ca528dcd2b955fba8ca1d9e3db7f776abb 100644 (file)
--- a/varint.h
+++ b/varint.h
@@ -1,7 +1,7 @@
 #ifndef VARINT_H
 #define VARINT_H
 
-extern int encode_varint(uintmax_t, unsigned char *);
-extern uintmax_t decode_varint(const unsigned char **);
+int encode_varint(uintmax_t, unsigned char *);
+uintmax_t decode_varint(const unsigned char **);
 
 #endif /* VARINT_H */
index 189c32d84c3c654c0a16bfe71284b24029724019..a7fc0999cb63c2abd9dd01f14aacabf40d986b13 100644 (file)
@@ -13,6 +13,6 @@ struct sliding_view {
 
 #define SLIDING_VIEW_INIT(input, len)  { (input), 0, 0, (len), STRBUF_INIT }
 
-extern int move_window(struct sliding_view *view, off_t off, size_t width);
+int move_window(struct sliding_view *view, off_t off, size_t width);
 
 #endif
index 10a2cbc40ec1c1ec7a97e967e3420b0b819f6641..625d950bb89405a5607b4d313d4ac3f80f14c49c 100644 (file)
@@ -4,7 +4,7 @@
 struct line_buffer;
 struct sliding_view;
 
-extern int svndiff0_apply(struct line_buffer *delta, off_t delta_len,
-               struct sliding_view *preimage, FILE *postimage);
+int svndiff0_apply(struct line_buffer *delta, off_t delta_len,
+                  struct sliding_view *preimage, FILE *postimage);
 
 #endif
index 9e3b0b7b6f9bd2aad3de9094febb8ad76aa45caf..caecc7a281cc6778447a5c70bc7a756306bbbd3b 100644 (file)
@@ -30,37 +30,37 @@ struct worktree {
  * The caller is responsible for freeing the memory from the returned
  * worktree(s).
  */
-extern struct worktree **get_worktrees(unsigned flags);
+struct worktree **get_worktrees(unsigned flags);
 
 /*
  * Returns 1 if linked worktrees exist, 0 otherwise.
  */
-extern int submodule_uses_worktrees(const char *path);
+int submodule_uses_worktrees(const char *path);
 
 /*
  * Return git dir of the worktree. Note that the path may be relative.
  * If wt is NULL, git dir of current worktree is returned.
  */
-extern const char *get_worktree_git_dir(const struct worktree *wt);
+const char *get_worktree_git_dir(const struct worktree *wt);
 
 /*
  * Search a worktree that can be unambiguously identified by
  * "arg". "prefix" must not be NULL.
  */
-extern struct worktree *find_worktree(struct worktree **list,
-                                     const char *prefix,
-                                     const char *arg);
+struct worktree *find_worktree(struct worktree **list,
+                              const char *prefix,
+                              const char *arg);
 
 /*
  * Return true if the given worktree is the main one.
  */
-extern int is_main_worktree(const struct worktree *wt);
+int is_main_worktree(const struct worktree *wt);
 
 /*
  * Return the reason string if the given worktree is locked or NULL
  * otherwise.
  */
-extern const char *worktree_lock_reason(struct worktree *wt);
+const char *worktree_lock_reason(struct worktree *wt);
 
 #define WT_VALIDATE_WORKTREE_MISSING_OK (1 << 0)
 
@@ -68,28 +68,28 @@ extern const char *worktree_lock_reason(struct worktree *wt);
  * Return zero if the worktree is in good condition. Error message is
  * returned if "errmsg" is not NULL.
  */
-extern int validate_worktree(const struct worktree *wt,
-                            struct strbuf *errmsg,
-                            unsigned flags);
+int validate_worktree(const struct worktree *wt,
+                     struct strbuf *errmsg,
+                     unsigned flags);
 
 /*
  * Update worktrees/xxx/gitdir with the new path.
  */
-extern void update_worktree_location(struct worktree *wt,
-                                    const char *path_);
+void update_worktree_location(struct worktree *wt,
+                             const char *path_);
 
 /*
  * Free up the memory for worktree(s)
  */
-extern void free_worktrees(struct worktree **);
+void free_worktrees(struct worktree **);
 
 /*
  * Check if a per-worktree symref points to a ref in the main worktree
  * or any linked worktree, and return the worktree that holds the ref,
  * or NULL otherwise. The result may be destroyed by the next call.
  */
-extern const struct worktree *find_shared_symref(const char *symref,
-                                                const char *target);
+const struct worktree *find_shared_symref(const char *symref,
+                                         const char *target);
 
 /*
  * Similar to head_ref() for all HEADs _except_ one from the current
@@ -104,8 +104,8 @@ int is_worktree_being_bisected(const struct worktree *wt, const char *target);
  * Similar to git_path() but can produce paths for a specified
  * worktree instead of current one
  */
-extern const char *worktree_git_path(const struct worktree *wt,
-                                    const char *fmt, ...)
+const char *worktree_git_path(const struct worktree *wt,
+                             const char *fmt, ...)
        __attribute__((format (printf, 2, 3)));
 
 /*
index f4fa98263857015b3d86e05df42e59591e74109a..e065558c312eefb4c3d5f8bf91dd8358069e0faa 100644 (file)
@@ -17,6 +17,7 @@
 #include "utf8.h"
 #include "worktree.h"
 #include "lockfile.h"
+#include "sequencer.h"
 
 static const char cut_line[] =
 "------------------------ >8 ------------------------\n";
@@ -1386,12 +1387,22 @@ static void show_rebase_in_progress(struct wt_status *s,
 static void show_cherry_pick_in_progress(struct wt_status *s,
                                         const char *color)
 {
-       status_printf_ln(s, color, _("You are currently cherry-picking commit %s."),
-                       find_unique_abbrev(&s->state.cherry_pick_head_oid, DEFAULT_ABBREV));
+       if (is_null_oid(&s->state.cherry_pick_head_oid))
+               status_printf_ln(s, color,
+                       _("Cherry-pick currently in progress."));
+       else
+               status_printf_ln(s, color,
+                       _("You are currently cherry-picking commit %s."),
+                       find_unique_abbrev(&s->state.cherry_pick_head_oid,
+                                          DEFAULT_ABBREV));
+
        if (s->hints) {
                if (has_unmerged(s))
                        status_printf_ln(s, color,
                                _("  (fix conflicts and run \"git cherry-pick --continue\")"));
+               else if (is_null_oid(&s->state.cherry_pick_head_oid))
+                       status_printf_ln(s, color,
+                               _("  (run \"git cherry-pick --continue\" to continue)"));
                else
                        status_printf_ln(s, color,
                                _("  (all conflicts fixed: run \"git cherry-pick --continue\")"));
@@ -1404,12 +1415,21 @@ static void show_cherry_pick_in_progress(struct wt_status *s,
 static void show_revert_in_progress(struct wt_status *s,
                                    const char *color)
 {
-       status_printf_ln(s, color, _("You are currently reverting commit %s."),
-                        find_unique_abbrev(&s->state.revert_head_oid, DEFAULT_ABBREV));
+       if (is_null_oid(&s->state.revert_head_oid))
+               status_printf_ln(s, color,
+                       _("Revert currently in progress."));
+       else
+               status_printf_ln(s, color,
+                       _("You are currently reverting commit %s."),
+                       find_unique_abbrev(&s->state.revert_head_oid,
+                                          DEFAULT_ABBREV));
        if (s->hints) {
                if (has_unmerged(s))
                        status_printf_ln(s, color,
                                _("  (fix conflicts and run \"git revert --continue\")"));
+               else if (is_null_oid(&s->state.revert_head_oid))
+                       status_printf_ln(s, color,
+                               _("  (run \"git revert --continue\" to continue)"));
                else
                        status_printf_ln(s, color,
                                _("  (all conflicts fixed: run \"git revert --continue\")"));
@@ -1580,6 +1600,7 @@ void wt_status_get_state(struct repository *r,
 {
        struct stat st;
        struct object_id oid;
+       enum replay_action action;
 
        if (!stat(git_path_merge_head(r), &st)) {
                wt_status_check_rebase(NULL, state);
@@ -1597,7 +1618,15 @@ void wt_status_get_state(struct repository *r,
                state->revert_in_progress = 1;
                oidcpy(&state->revert_head_oid, &oid);
        }
-
+       if (!sequencer_get_last_command(r, &action)) {
+               if (action == REPLAY_PICK) {
+                       state->cherry_pick_in_progress = 1;
+                       oidcpy(&state->cherry_pick_head_oid, &null_oid);
+               } else {
+                       state->revert_in_progress = 1;
+                       oidcpy(&state->revert_head_oid, &null_oid);
+               }
+       }
        if (get_detached_from)
                wt_status_get_detached_from(r, state);
 }
index 2d41fffd4c618b5d7b816146d9df684b195535e3..ede4246bbd3397086f90217539a2d07a35a4b986 100644 (file)
@@ -27,9 +27,9 @@ int read_mmfile(mmfile_t *ptr, const char *filename);
 void read_mmblob(mmfile_t *ptr, const struct object_id *oid);
 int buffer_is_binary(const char *ptr, unsigned long size);
 
-extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags);
-extern void xdiff_clear_find_func(xdemitconf_t *xecfg);
-extern int git_xmerge_config(const char *var, const char *value, void *cb);
+void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags);
+void xdiff_clear_find_func(xdemitconf_t *xecfg);
+int git_xmerge_config(const char *var, const char *value, void *cb);
 extern int git_xmerge_style;
 
 /*
@@ -46,14 +46,14 @@ void discard_hunk_line(void *priv,
  * The `flags` given as XDF_WHITESPACE_FLAGS determine how white spaces
  * are treated for the comparision.
  */
-extern int xdiff_compare_lines(const char *l1, long s1,
-                              const char *l2, long s2, long flags);
+int xdiff_compare_lines(const char *l1, long s1,
+                       const char *l2, long s2, long flags);
 
 /*
  * Returns a hash of the string s of length len.
  * The `flags` given as XDF_WHITESPACE_FLAGS determine how white spaces
  * are treated for the hash.
  */
-extern unsigned long xdiff_hash_string(const char *s, size_t len, long flags);
+unsigned long xdiff_hash_string(const char *s, size_t len, long flags);
 
 #endif