diff options
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=' ' @@ -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 @@ -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); @@ -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 */ @@ -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 @@ -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 */ @@ -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)); @@ -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 @@ -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 @@ -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 */ @@ -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 @@ -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); + } } @@ -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; @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) @@ -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 @@ -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)); @@ -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, @@ -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); @@ -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) { \ @@ -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 @@ -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 */ @@ -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 */ @@ -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 { @@ -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); @@ -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 */ @@ -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); @@ -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, @@ -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); @@ -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 @@ -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 */ @@ -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; @@ -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); @@ -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 */ @@ -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 */ @@ -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); @@ -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 |