summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes/2.22.0.txt39
-rw-r--r--Documentation/config.txt2
-rw-r--r--Documentation/config/pack.txt4
-rw-r--r--Documentation/config/repack.txt2
-rw-r--r--Documentation/config/trace2.txt56
-rw-r--r--Documentation/git-ls-files.txt2
-rw-r--r--Documentation/revisions.txt29
-rw-r--r--Documentation/technical/api-trace2.txt184
-rw-r--r--Documentation/trace2-target-values.txt10
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile14
-rw-r--r--advice.h2
-rw-r--r--archive.h24
-rw-r--r--bisect.h26
-rw-r--r--blame.h2
-rw-r--r--branch.c4
-rw-r--r--branch.h14
-rw-r--r--builtin.h254
-rw-r--r--builtin/clone.c6
-rw-r--r--builtin/commit.c3
-rw-r--r--builtin/pack-objects.c2
-rw-r--r--builtin/rebase--interactive.c377
-rw-r--r--builtin/rebase.c578
-rw-r--r--builtin/repack.c5
-rw-r--r--builtin/submodule--helper.c2
-rw-r--r--builtin/tag.c2
-rw-r--r--bulk-checkin.h10
-rw-r--r--cache.h356
-rw-r--r--checkout.h6
-rw-r--r--column.h16
-rw-r--r--commit.h116
-rw-r--r--common-main.c8
-rw-r--r--compat/access.c31
-rw-r--r--compat/fileno.c2
-rw-r--r--compat/mingw.c2
-rw-r--r--compat/win32/trace2_win32_process_info.c50
-rw-r--r--config.c30
-rw-r--r--config.h231
-rw-r--r--config.mak.uname1
-rw-r--r--connect.h22
-rw-r--r--connected.c17
-rw-r--r--connected.h8
-rw-r--r--contrib/diff-highlight/DiffHighlight.pm7
-rw-r--r--csum-file.h20
-rw-r--r--decorate.h4
-rw-r--r--delta.h14
-rw-r--r--dir.h140
-rw-r--r--exec-cmd.h16
-rw-r--r--fmt-merge-msg.h2
-rw-r--r--fsmonitor.h14
-rw-r--r--gettext.h8
-rw-r--r--git-compat-util.h144
-rw-r--r--grep.h22
-rw-r--r--hashmap.h30
-rw-r--r--help.h36
-rw-r--r--http.h62
-rw-r--r--khash.h16
-rw-r--r--kwset.h10
-rw-r--r--line-log.h16
-rw-r--r--lockfile.h12
-rw-r--r--ls-refs.h4
-rw-r--r--mailinfo.h6
-rw-r--r--merge-blobs.h6
-rw-r--r--object-store.h32
-rw-r--r--object.h12
-rw-r--r--oidmap.h12
-rw-r--r--pack.h26
-rw-r--r--parse-options-cb.c34
-rw-r--r--parse-options.h4
-rw-r--r--path.h42
-rw-r--r--pkt-line.h10
-rw-r--r--ppc/sha1.c4
-rw-r--r--prio-queue.h10
-rw-r--r--protocol.h6
-rw-r--r--quote.h34
-rw-r--r--reachable.h8
-rw-r--r--read-cache.c2
-rw-r--r--reflog-walk.h28
-rw-r--r--refs.h2
-rw-r--r--remote.h24
-rw-r--r--replace-object.h4
-rw-r--r--resolve-undo.h14
-rw-r--r--run-command.h8
-rw-r--r--sequencer.c128
-rw-r--r--sequencer.h10
-rw-r--r--serve.h6
-rw-r--r--sha1-lookup.h8
-rw-r--r--streaming.h8
-rw-r--r--string-list.h4
-rw-r--r--sub-process.h8
-rw-r--r--submodule-config.h22
-rwxr-xr-xt/perf/aggregate.perl4
-rwxr-xr-xt/perf/p5302-pack-index.sh31
-rwxr-xr-xt/perf/p5310-pack-bitmaps.sh3
-rwxr-xr-xt/perf/p5311-pack-bitmaps-fetch.sh1
-rwxr-xr-xt/perf/p5600-partial-clone.sh26
-rwxr-xr-xt/t0210-trace2-normal.sh49
-rwxr-xr-xt/t0211-trace2-perf.sh43
-rwxr-xr-xt/t0212-trace2-event.sh42
-rwxr-xr-xt/t3507-cherry-pick-conflict.sh39
-rwxr-xr-xt/t5310-pack-bitmaps.sh5
-rwxr-xr-xt/t7004-tag.sh2
-rwxr-xr-xt/t7512-status-help.sh36
-rwxr-xr-xt/t7700-repack.sh19
-rw-r--r--tag.h16
-rw-r--r--tempfile.h30
-rw-r--r--trace.h44
-rw-r--r--trace2.c23
-rw-r--r--trace2.h43
-rw-r--r--trace2/tr2_cfg.c7
-rw-r--r--trace2/tr2_dst.c36
-rw-r--r--trace2/tr2_dst.h3
-rw-r--r--trace2/tr2_sid.c53
-rw-r--r--trace2/tr2_sysenv.c127
-rw-r--r--trace2/tr2_sysenv.h36
-rw-r--r--trace2/tr2_tbuf.c19
-rw-r--r--trace2/tr2_tbuf.h5
-rw-r--r--trace2/tr2_tgt.h1
-rw-r--r--trace2/tr2_tgt_event.c53
-rw-r--r--trace2/tr2_tgt_normal.c19
-rw-r--r--trace2/tr2_tgt_perf.c23
-rw-r--r--trace2/tr2_tls.c38
-rw-r--r--trace2/tr2_tls.h8
-rw-r--r--transport.h4
-rw-r--r--tree-walk.h4
-rw-r--r--upload-pack.h8
-rw-r--r--url.h16
-rw-r--r--urlmatch.h4
-rw-r--r--utf8.h2
-rw-r--r--varint.h4
-rw-r--r--vcs-svn/sliding_window.h2
-rw-r--r--vcs-svn/svndiff.h4
-rw-r--r--worktree.h36
-rw-r--r--wt-status.c39
-rw-r--r--xdiff-interface.h12
135 files changed, 2796 insertions, 1873 deletions
diff --git a/Documentation/RelNotes/2.22.0.txt b/Documentation/RelNotes/2.22.0.txt
index 776e15512b..114f147fd6 100644
--- a/Documentation/RelNotes/2.22.0.txt
+++ b/Documentation/RelNotes/2.22.0.txt
@@ -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).
diff --git a/Documentation/config.txt b/Documentation/config.txt
index d87846faa6..7e2a6f61f5 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -422,6 +422,8 @@ include::config/submodule.txt[]
include::config/tag.txt[]
+include::config/trace2.txt[]
+
include::config/transfer.txt[]
include::config/uploadarchive.txt[]
diff --git a/Documentation/config/pack.txt b/Documentation/config/pack.txt
index 425c73aa52..9cdcfa7324 100644
--- a/Documentation/config/pack.txt
+++ b/Documentation/config/pack.txt
@@ -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.
diff --git a/Documentation/config/repack.txt b/Documentation/config/repack.txt
index a5c37813fd..9c413e177e 100644
--- a/Documentation/config/repack.txt
+++ b/Documentation/config/repack.txt
@@ -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
index 0000000000..a5f409c1c1
--- /dev/null
+++ b/Documentation/config/trace2.txt
@@ -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.
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 5298f1bc30..8461c0e83e 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -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
diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt
index 2337a995ec..82c1e5754e 100644
--- a/Documentation/revisions.txt
+++ b/Documentation/revisions.txt
@@ -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
diff --git a/Documentation/technical/api-trace2.txt b/Documentation/technical/api-trace2.txt
index d0948ba250..9e585b8e79 100644
--- a/Documentation/technical/api-trace2.txt
+++ b/Documentation/technical/api-trace2.txt
@@ -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
index 0000000000..27d3c64e66
--- /dev/null
+++ b/Documentation/trace2-target-values.txt
@@ -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.
+--
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 3fc4065da2..8a5009caf9 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.21.GIT
+DEF_VER=v2.22.0-rc0
LF='
'
diff --git a/Makefile b/Makefile
index 5143cab9bd..f965509b3c 100644
--- 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
@@ -1833,6 +1836,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
diff --git a/advice.h b/advice.h
index cb5d361614..e50f02cdfe 100644
--- 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);
diff --git a/archive.h b/archive.h
index dd022a6b46..e60e3dd31c 100644
--- 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 */
diff --git a/bisect.h b/bisect.h
index 821d16e4dd..4e69a11ea8 100644
--- 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 2a285eb027..d62f80fa74 100644
--- 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 */
diff --git a/branch.c b/branch.c
index 28b81a7e02..643694542a 100644
--- 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"
@@ -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));
diff --git a/branch.h b/branch.h
index 29c1afa4d0..6f38db14e9 100644
--- 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
diff --git a/builtin.h b/builtin.h
index ac552ff0d2..ec7e0954c4 100644
--- 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
diff --git a/builtin/clone.c b/builtin/clone.c
index 31a47d190a..ffdd94e8f6 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -660,7 +660,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 +670,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 +1232,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);
diff --git a/builtin/commit.c b/builtin/commit.c
index bd4b180c43..1c9e8e2228 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -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));
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index d7743f110b..9f424aabab 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -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;
diff --git a/builtin/rebase--interactive.c b/builtin/rebase--interactive.c
deleted file mode 100644
index 4535523bf5..0000000000
--- a/builtin/rebase--interactive.c
+++ /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;
-}
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 966b953e86..ba3a574e40 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -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);
diff --git a/builtin/repack.c b/builtin/repack.c
index 67f8978043..caca113927 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -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;
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 8c72ea864c..0bf4aa088e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -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 */
diff --git a/builtin/tag.c b/builtin/tag.c
index 1debd3a11c..ef37dccf86 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -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^{}");
diff --git a/bulk-checkin.h b/bulk-checkin.h
index f438f93811..b26f3dc3b7 100644
--- a/bulk-checkin.h
+++ b/bulk-checkin.h
@@ -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 67cc2e1806..fa8ede9a2d 100644
--- a/cache.h
+++ b/cache.h
@@ -352,10 +352,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 +545,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 +554,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 +588,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 +598,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 +617,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 +634,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 +674,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 +706,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 +719,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 +746,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 +755,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 +777,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 +798,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 +821,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 +834,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 +1022,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 +1246,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 +1290,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 +1393,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 +1409,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 +1418,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 +1454,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 +1492,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 +1562,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 +1595,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 +1612,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 +1628,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 +1649,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 +1676,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 +1694,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 +1706,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 +1715,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 +1741,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 +1751,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 +1804,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 +1880,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 */
diff --git a/checkout.h b/checkout.h
index 6b2073310c..1152133bd7 100644
--- a/checkout.h
+++ b/checkout.h
@@ -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 */
diff --git a/column.h b/column.h
index 2567a5cf4d..448c7440b3 100644
--- 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
diff --git a/commit.h b/commit.h
index cc19cb5314..f5295ca7f3 100644
--- 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 */
diff --git a/common-main.c b/common-main.c
index d484aec209..582a7b1886 100644
--- a/common-main.c
+++ b/common-main.c
@@ -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
index 0000000000..19fda3e877
--- /dev/null
+++ b/compat/access.c
@@ -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;
+}
diff --git a/compat/fileno.c b/compat/fileno.c
index 7b105f4cd7..8e80ef335d 100644
--- a/compat/fileno.c
+++ b/compat/fileno.c
@@ -1,4 +1,4 @@
-#define COMPAT_CODE
+#define COMPAT_CODE_FILENO
#include "../git-compat-util.h"
int git_fileno(FILE *stream)
diff --git a/compat/mingw.c b/compat/mingw.c
index 6b04514cdc..a2f74aca6a 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -2569,6 +2569,8 @@ void mingw_startup(void)
wchar_t **wenv, **wargv;
_startupinfo si;
+ trace2_initialize_clock();
+
maybe_redirect_std_handles();
/* get wide char arguments and environment */
diff --git a/compat/win32/trace2_win32_process_info.c b/compat/win32/trace2_win32_process_info.c
index 52bd62034b..8ccbd1c2c6 100644
--- a/compat/win32/trace2_win32_process_info.c
+++ b/compat/win32/trace2_win32_process_info.c
@@ -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);
+ }
}
diff --git a/config.c b/config.c
index c2846df3f1..296a6d9cc4 100644
--- 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;
diff --git a/config.h b/config.h
index ee5d3fa7b4..f0ed464004 100644
--- 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)
diff --git a/config.mak.uname b/config.mak.uname
index 6f92f4746e..b71688eeb7 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -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
diff --git a/connect.h b/connect.h
index 32aff60979..5f2382e018 100644
--- 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
diff --git a/connected.c b/connected.c
index 1bba888eff..1ab481fed6 100644
--- a/connected.c
+++ b/connected.c
@@ -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);
diff --git a/connected.h b/connected.h
index 8d5a6b3ad6..ce2e7d8f2e 100644
--- a/connected.h
+++ b/connected.h
@@ -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 }
diff --git a/contrib/diff-highlight/DiffHighlight.pm b/contrib/diff-highlight/DiffHighlight.pm
index 536754583b..7440aa1c46 100644
--- a/contrib/diff-highlight/DiffHighlight.pm
+++ b/contrib/diff-highlight/DiffHighlight.pm
@@ -4,6 +4,11 @@ use 5.008;
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;
}
diff --git a/csum-file.h b/csum-file.h
index 3bf7184736..a98b1eee53 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -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)
{
diff --git a/decorate.h b/decorate.h
index 9014c1e996..ee43dee1f0 100644
--- a/decorate.h
+++ b/decorate.h
@@ -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 9b67531dfa..2df5fe13d9 100644
--- 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 c23313b021..680079bbe3 100644
--- 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
diff --git a/exec-cmd.h b/exec-cmd.h
index 2522453cda..8cd1df28d3 100644
--- a/exec-cmd.h
+++ b/exec-cmd.h
@@ -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 */
diff --git a/fmt-merge-msg.h b/fmt-merge-msg.h
index b28d3a6113..01e3aa88c5 100644
--- a/fmt-merge-msg.h
+++ b/fmt-merge-msg.h
@@ -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 */
diff --git a/fsmonitor.h b/fsmonitor.h
index 01017c43aa..8489fa3244 100644
--- a/fsmonitor.h
+++ b/fsmonitor.h
@@ -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
diff --git a/gettext.h b/gettext.h
index 71255e503e..bee52eb113 100644
--- a/gettext.h
+++ b/gettext.h
@@ -28,11 +28,11 @@
#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
diff --git a/git-compat-util.h b/git-compat-util.h
index 4386b3e1c8..cc0e7e9733 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -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)
diff --git a/grep.h b/grep.h
index fb04893721..1875880f37 100644
--- 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
diff --git a/hashmap.h b/hashmap.h
index d375d9cce7..f95593b6cf 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -104,11 +104,11 @@
* `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 a141e209ae..b8780fbd0f 100644
--- 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.h b/http.h
index ddfe52f023..b429f1cf04 100644
--- 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 a09163b3e3..af747a683f 100644
--- 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 583f6268ef..df99a92178 100644
--- 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);
diff --git a/line-log.h b/line-log.h
index e2a5ee7c6d..8ee7a2bd4a 100644
--- a/line-log.h
+++ b/line-log.h
@@ -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 */
diff --git a/lockfile.h b/lockfile.h
index 35403ccc0d..9843053ce8 100644
--- a/lockfile.h
+++ b/lockfile.h
@@ -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
diff --git a/ls-refs.h b/ls-refs.h
index b62877e8da..7e5646f5f6 100644
--- 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 */
diff --git a/mailinfo.h b/mailinfo.h
index 6830e1e625..79b1d6774e 100644
--- a/mailinfo.h
+++ b/mailinfo.h
@@ -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 */
diff --git a/merge-blobs.h b/merge-blobs.h
index cc31038b80..13cf9669e5 100644
--- a/merge-blobs.h
+++ b/merge-blobs.h
@@ -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/object-store.h b/object-store.h
index b086f5ecdb..46a1da79cc 100644
--- a/object-store.h
+++ b/object-store.h
@@ -162,10 +162,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 +180,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 +227,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 */
diff --git a/object.h b/object.h
index 796792cb32..4526979ccf 100644
--- 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 */
diff --git a/oidmap.h b/oidmap.h
index 72430b611e..7a939461ff 100644
--- 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 da99fdd1d2..9fc0945ac9 100644
--- 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
diff --git a/parse-options-cb.c b/parse-options-cb.c
index 6e2e8d6273..4b95d04a37 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -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;
diff --git a/parse-options.h b/parse-options.h
index 1dd3523c15..bd00cf0049 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -277,8 +277,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 651e6157fc..2ba6ca58c8 100644
--- 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:
diff --git a/pkt-line.h b/pkt-line.h
index c36cb788ed..5c62015db4 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -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
diff --git a/ppc/sha1.c b/ppc/sha1.c
index ec6a1926d4..1b705cee1f 100644
--- a/ppc/sha1.c
+++ b/ppc/sha1.c
@@ -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)
{
diff --git a/prio-queue.h b/prio-queue.h
index 682e51867a..4f9a37e6be 100644
--- a/prio-queue.h
+++ b/prio-queue.h
@@ -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 */
diff --git a/protocol.h b/protocol.h
index 2ad35e433c..cef1a4a01c 100644
--- a/protocol.h
+++ b/protocol.h
@@ -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 ea992dcc91..fb08dc085c 100644
--- 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
diff --git a/reachable.h b/reachable.h
index 18b0f9f2f0..5df932ad8f 100644
--- a/reachable.h
+++ b/reachable.h
@@ -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
diff --git a/read-cache.c b/read-cache.c
index 61b043bac3..4fad4e3f9a 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -3131,7 +3131,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)
diff --git a/reflog-walk.h b/reflog-walk.h
index cb3e73755d..f26408f6cc 100644
--- a/reflog-walk.h
+++ b/reflog-walk.h
@@ -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 8f9cbf8a93..2727405b61 100644
--- 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,
diff --git a/remote.h b/remote.h
index 6a1795947e..83e885672b 100644
--- 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
diff --git a/replace-object.h b/replace-object.h
index 16528df942..04ed7a85a2 100644
--- a/replace-object.h
+++ b/replace-object.h
@@ -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
diff --git a/resolve-undo.h b/resolve-undo.h
index fbe348efac..2b3f0f901e 100644
--- a/resolve-undo.h
+++ b/resolve-undo.h
@@ -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
diff --git a/run-command.h b/run-command.h
index a6950691c0..f769e03f01 100644
--- a/run-command.h
+++ b/run-command.h
@@ -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 */
diff --git a/sequencer.c b/sequencer.c
index 4407a3f978..f88a97fb10 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -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))
diff --git a/sequencer.h b/sequencer.h
index 75e292c03b..0c494b83d4 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -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 fe65ba9f46..42ddca7f8b 100644
--- 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 */
diff --git a/sha1-lookup.h b/sha1-lookup.h
index 7678b23b36..5afcd011c6 100644
--- a/sha1-lookup.h
+++ b/sha1-lookup.h
@@ -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
diff --git a/streaming.h b/streaming.h
index 32f4626771..f465a3cd31 100644
--- a/streaming.h
+++ b/streaming.h
@@ -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 */
diff --git a/string-list.h b/string-list.h
index 18c718c12c..f964399949 100644
--- a/string-list.h
+++ b/string-list.h
@@ -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,
diff --git a/sub-process.h b/sub-process.h
index 71b18ad5af..5c182fad98 100644
--- a/sub-process.h
+++ b/sub-process.h
@@ -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
diff --git a/submodule-config.h b/submodule-config.h
index 4dc9b0771c..1b4e2da658 100644
--- a/submodule-config.h
+++ b/submodule-config.h
@@ -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 */
diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl
index 494907a892..76dd48f890 100755
--- a/t/perf/aggregate.perl
+++ b/t/perf/aggregate.perl
@@ -3,7 +3,6 @@
use lib '../../perl/build/lib';
use strict;
use warnings;
-use JSON;
use Getopt::Long;
use Git;
@@ -342,7 +341,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: $!";
diff --git a/t/perf/p5302-pack-index.sh b/t/perf/p5302-pack-index.sh
index 99bdb16c85..a9b3e112d9 100755
--- a/t/perf/p5302-pack-index.sh
+++ b/t/perf/p5302-pack-index.sh
@@ -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
diff --git a/t/perf/p5310-pack-bitmaps.sh b/t/perf/p5310-pack-bitmaps.sh
index bb91dbb173..6a3a42531b 100755
--- a/t/perf/p5310-pack-bitmaps.sh
+++ b/t/perf/p5310-pack-bitmaps.sh
@@ -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' '
diff --git a/t/perf/p5311-pack-bitmaps-fetch.sh b/t/perf/p5311-pack-bitmaps-fetch.sh
index b04575951f..47c3fd7581 100755
--- a/t/perf/p5311-pack-bitmaps-fetch.sh
+++ b/t/perf/p5311-pack-bitmaps-fetch.sh
@@ -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
index 0000000000..3e04bd2ae1
--- /dev/null
+++ b/t/perf/p5600-partial-clone.sh
@@ -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
diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh
index 819430658b..71194a3623 100755
--- a/t/t0210-trace2-normal.sh
+++ b/t/t0210-trace2-normal.sh
@@ -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
diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh
index 953e2f7847..b501e867af 100755
--- a/t/t0211-trace2-perf.sh
+++ b/t/t0211-trace2-perf.sh
@@ -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
diff --git a/t/t0212-trace2-event.sh b/t/t0212-trace2-event.sh
index 028b6c5671..59adae8123 100755
--- a/t/t0212-trace2-event.sh
+++ b/t/t0212-trace2-event.sh
@@ -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
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index 1a8818fbe0..9b9b4ca8d4 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -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 &&
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index 82d7f7f6a5..a26c8ba9a2 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -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
)
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index e285686662..6aeeb279a0 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -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^{}
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 458608cc1e..c1eb72555d 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -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 &&
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index 6162e2a8e6..86d05160a3 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -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
diff --git a/tag.h b/tag.h
index e669c3e497..03265fbfe2 100644
--- 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 */
diff --git a/tempfile.h b/tempfile.h
index 61d8dc4d1b..cddda0a33c 100644
--- a/tempfile.h
+++ b/tempfile.h
@@ -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 171b256d26..9fa3e7a594 100644
--- 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;
diff --git a/trace2.c b/trace2.c
index 8bbad56887..c7b4f14d29 100644
--- 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);
diff --git a/trace2.h b/trace2.h
index b330a54a89..f189ef5984 100644
--- a/trace2.h
+++ b/trace2.h
@@ -20,8 +20,26 @@ struct json_writer;
*/
/*
+ * 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
diff --git a/trace2/tr2_cfg.c b/trace2/tr2_cfg.c
index b329921ac5..caa7f06948 100644
--- a/trace2/tr2_cfg.c
+++ b/trace2/tr2_cfg.c
@@ -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;
diff --git a/trace2/tr2_dst.c b/trace2/tr2_dst.c
index c3d82ca6a4..5dda0ca1cd 100644
--- a/trace2/tr2_dst.c
+++ b/trace2/tr2_dst.c
@@ -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);
}
diff --git a/trace2/tr2_dst.h b/trace2/tr2_dst.h
index 9a64f05b02..3adf3bac13 100644
--- a/trace2/tr2_dst.h
+++ b/trace2/tr2_dst.h
@@ -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;
diff --git a/trace2/tr2_sid.c b/trace2/tr2_sid.c
index 984524a43c..5047095478 100644
--- a/trace2/tr2_sid.c
+++ b/trace2/tr2_sid.c
@@ -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"
@@ -7,6 +8,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
index 0000000000..9025b86303
--- /dev/null
+++ b/trace2/tr2_sysenv.c
@@ -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
index 0000000000..369b20bd87
--- /dev/null
+++ b/trace2/tr2_sysenv.h
@@ -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 */
diff --git a/trace2/tr2_tbuf.c b/trace2/tr2_tbuf.c
index 0844910423..2498482d9a 100644
--- a/trace2/tr2_tbuf.c
+++ b/trace2/tr2_tbuf.c
@@ -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);
+}
diff --git a/trace2/tr2_tbuf.h b/trace2/tr2_tbuf.h
index 9cdefa3957..fa853d8f42 100644
--- a/trace2/tr2_tbuf.h
+++ b/trace2/tr2_tbuf.h
@@ -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 */
diff --git a/trace2/tr2_tgt.h b/trace2/tr2_tgt.h
index 297bb8ffbe..7b90469212 100644
--- a/trace2/tr2_tgt.h
+++ b/trace2/tr2_tgt.h
@@ -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);
diff --git a/trace2/tr2_tgt_event.c b/trace2/tr2_tgt_event.c
index 1cf4f62441..c2852d1bd2 100644
--- a/trace2/tr2_tgt_event.c
+++ b/trace2/tr2_tgt_event.c
@@ -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;
diff --git a/trace2/tr2_tgt_normal.c b/trace2/tr2_tgt_normal.c
index 1a07d70abd..00b116d797 100644
--- a/trace2/tr2_tgt_normal.c
+++ b/trace2/tr2_tgt_normal.c
@@ -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;
diff --git a/trace2/tr2_tgt_perf.c b/trace2/tr2_tgt_perf.c
index 2a866d701b..ea0cbbe13e 100644
--- a/trace2/tr2_tgt_perf.c
+++ b/trace2/tr2_tgt_perf.c
@@ -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);
}
diff --git a/trace2/tr2_tls.c b/trace2/tr2_tls.c
index 8e65b0361d..e76d8c5d92 100644
--- a/trace2/tr2_tls.c
+++ b/trace2/tr2_tls.c
@@ -10,16 +10,30 @@
#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)
diff --git a/trace2/tr2_tls.h b/trace2/tr2_tls.h
index bb80e3f8e7..b1e327a928 100644
--- a/trace2/tr2_tls.h
+++ b/trace2/tr2_tls.h
@@ -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 */
diff --git a/transport.h b/transport.h
index f2ee7c4f49..06e06d3d89 100644
--- a/transport.h
+++ b/transport.h
@@ -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
diff --git a/tree-walk.h b/tree-walk.h
index 3aa381b6a3..161e2400f4 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -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)
{
diff --git a/upload-pack.h b/upload-pack.h
index cab2178796..4bafe16a22 100644
--- a/upload-pack.h
+++ b/upload-pack.h
@@ -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 f311c40a46..00b7d58c33 100644
--- 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 */
diff --git a/urlmatch.h b/urlmatch.h
index e482148248..eed5f29235 100644
--- a/urlmatch.h
+++ b/urlmatch.h
@@ -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 84efbfcb1f..fcd5167baf 100644
--- 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);
diff --git a/varint.h b/varint.h
index c1c44d9a6b..f78bb0ca52 100644
--- 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 */
diff --git a/vcs-svn/sliding_window.h b/vcs-svn/sliding_window.h
index 189c32d84c..a7fc0999cb 100644
--- a/vcs-svn/sliding_window.h
+++ b/vcs-svn/sliding_window.h
@@ -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
diff --git a/vcs-svn/svndiff.h b/vcs-svn/svndiff.h
index 10a2cbc40e..625d950bb8 100644
--- a/vcs-svn/svndiff.h
+++ b/vcs-svn/svndiff.h
@@ -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
diff --git a/worktree.h b/worktree.h
index 9e3b0b7b6f..caecc7a281 100644
--- a/worktree.h
+++ b/worktree.h
@@ -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)));
/*
diff --git a/wt-status.c b/wt-status.c
index f4fa982638..e065558c31 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -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);
}
diff --git a/xdiff-interface.h b/xdiff-interface.h
index 2d41fffd4c..ede4246bbd 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -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