aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/CodingGuidelines58
-rw-r--r--Documentation/RelNotes/2.48.0.txt35
-rw-r--r--Documentation/asciidoc.conf20
-rw-r--r--Documentation/asciidoctor-extensions.rb87
-rw-r--r--Documentation/git-clone.txt78
-rw-r--r--Documentation/git-config.txt2
-rw-r--r--Documentation/git-init.txt35
-rw-r--r--Documentation/git-maintenance.txt4
-rw-r--r--Documentation/howto/maintain-git.txt44
-rw-r--r--Documentation/urls.txt26
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile1
l---------RelNotes2
-rw-r--r--bloom.c8
-rw-r--r--branch.c8
-rw-r--r--builtin/annotate.c20
-rw-r--r--builtin/clone.c27
-rw-r--r--builtin/config.c4
-rw-r--r--builtin/index-pack.c7
-rw-r--r--builtin/pack-redundant.c40
-rw-r--r--builtin/receive-pack.c5
-rw-r--r--builtin/revert.c17
-rw-r--r--builtin/send-pack.c1
-rw-r--r--builtin/stash.c4
-rwxr-xr-xci/install-dependencies.sh1
-rw-r--r--diff-lib.c4
-rw-r--r--diff.c32
-rw-r--r--diff.h3
-rw-r--r--diffcore-break.c8
-rw-r--r--diffcore-pickaxe.c4
-rw-r--r--diffcore-rename.c3
-rw-r--r--diffcore-rotate.c3
-rw-r--r--diffcore.h10
-rw-r--r--graph.c29
-rw-r--r--line-log.c85
-rw-r--r--log-tree.c11
-rw-r--r--merge-ort.c2
-rw-r--r--midx-write.c5
-rw-r--r--pack-bitmap-write.c9
-rw-r--r--pack-bitmap.c4
-rw-r--r--pack-write.c42
-rw-r--r--pack.h4
-rw-r--r--pseudo-merge.c23
-rw-r--r--pseudo-merge.h2
-rw-r--r--range-diff.c4
-rw-r--r--read-cache.c1
-rw-r--r--refs/reftable-backend.c39
-rw-r--r--reftable/basics.c97
-rw-r--r--reftable/basics.h28
-rw-r--r--reftable/block.c29
-rw-r--r--reftable/block.h4
-rw-r--r--reftable/blocksource.c25
-rw-r--r--reftable/error.c2
-rw-r--r--reftable/iter.c22
-rw-r--r--reftable/iter.h2
-rw-r--r--reftable/merged.c84
-rw-r--r--reftable/merged.h6
-rw-r--r--reftable/pq.c9
-rw-r--r--reftable/pq.h2
-rw-r--r--reftable/publicbasics.c66
-rw-r--r--reftable/reader.c70
-rw-r--r--reftable/reader.h6
-rw-r--r--reftable/record.c174
-rw-r--r--reftable/record.h6
-rw-r--r--reftable/reftable-basics.h18
-rw-r--r--reftable/reftable-error.h3
-rw-r--r--reftable/reftable-malloc.h18
-rw-r--r--reftable/reftable-merged.h8
-rw-r--r--reftable/reftable-reader.h8
-rw-r--r--reftable/reftable-stack.h8
-rw-r--r--reftable/reftable-writer.h12
-rw-r--r--reftable/stack.c187
-rw-r--r--reftable/tree.c42
-rw-r--r--reftable/tree.h21
-rw-r--r--reftable/writer.c154
-rw-r--r--remote.c15
-rw-r--r--remote.h4
-rw-r--r--revision.c14
-rw-r--r--scalar.c1
-rw-r--r--shell.c6
-rw-r--r--submodule-config.c15
-rw-r--r--submodule-config.h3
-rw-r--r--t/helper/test-partial-clone.c2
-rw-r--r--t/helper/test-proc-receive.c7
-rw-r--r--t/helper/test-reftable.c10
-rwxr-xr-xt/t0410-partial-clone.sh1
-rwxr-xr-xt/t0450-txt-doc-vs-help.sh11
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh1
-rwxr-xr-xt/t3207-branch-submodule.sh1
-rwxr-xr-xt/t3427-rebase-subtree.sh1
-rwxr-xr-xt/t3514-cherry-pick-revert-gpg.sh1
-rwxr-xr-xt/t3909-stash-pathspec-file.sh1
-rwxr-xr-xt/t4211-line-log.sh28
-rwxr-xr-xt/t5323-pack-redundant.sh1
-rwxr-xr-xt/t5327-multi-pack-bitmaps-rev.sh1
-rwxr-xr-xt/t5333-pseudo-merge-bitmaps.sh1
-rwxr-xr-xt/t5334-incremental-multi-pack-index.sh2
-rwxr-xr-xt/t5411-proc-receive-hook.sh1
-rwxr-xr-xt/t5545-push-options.sh1
-rwxr-xr-xt/t5730-protocol-v2-bundle-uri-file.sh1
-rwxr-xr-xt/t5731-protocol-v2-bundle-uri-git.sh1
-rwxr-xr-xt/t5732-protocol-v2-bundle-uri-http.sh1
-rwxr-xr-xt/t6012-rev-list-simplify.sh1
-rwxr-xr-xt/t6016-rev-list-graph-simplify-history.sh1
-rwxr-xr-xt/t7003-filter-branch.sh1
-rwxr-xr-xt/t8001-annotate.sh1
-rwxr-xr-xt/t9210-scalar.sh1
-rwxr-xr-xt/t9211-scalar-clone.sh1
-rwxr-xr-xt/t9350-fast-export.sh1
-rwxr-xr-xt/t9400-git-cvsserver-server.sh1
-rwxr-xr-xt/t9402-git-cvsserver-refs.sh1
-rwxr-xr-xt/t9850-shell.sh2
-rw-r--r--t/unit-tests/lib-reftable.c8
-rw-r--r--t/unit-tests/t-reftable-basics.c11
-rw-r--r--t/unit-tests/t-reftable-block.c24
-rw-r--r--t/unit-tests/t-reftable-merged.c16
-rw-r--r--t/unit-tests/t-reftable-readwrite.c65
-rw-r--r--t/unit-tests/t-reftable-stack.c6
-rw-r--r--t/unit-tests/t-reftable-tree.c10
-rw-r--r--wt-status.c6
120 files changed, 1574 insertions, 689 deletions
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index 3263245b03..30fda4142c 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -828,78 +828,80 @@ Markup:
_<new-branch-name>_
_<template-directory>_
- A placeholder is not enclosed in backticks, as it is not a literal.
-
When needed, use a distinctive identifier for placeholders, usually
made of a qualification and a type:
_<git-dir>_
_<key-id>_
- When literal and placeholders are mixed, each markup is applied for
- each sub-entity. If they are stuck, a special markup, called
- unconstrained formatting is required.
- Unconstrained formating for placeholders is __<like-this>__
- Unconstrained formatting for literal formatting is ++like this++
- `--jobs` _<n>_
- ++--sort=++__<key>__
- __<directory>__++/.git++
- ++remote.++__<name>__++.mirror++
+ Git's Asciidoc processor has been tailored to treat backticked text
+ as complex synopsis. When literal and placeholders are mixed, you can
+ use the backtick notation which will take care of correctly typesetting
+ the content.
+ `--jobs <n>`
+ `--sort=<key>`
+ `<directory>/.git`
+ `remote.<name>.mirror`
+ `ssh://[<user>@]<host>[:<port>]/<path-to-git-repo>`
- caveat: ++ unconstrained format is not verbatim and may expand
- content. Use Asciidoc escapes inside them.
+As a side effect, backquoted placeholders are correctly typeset, but
+this style is not recommended.
Synopsis Syntax
- Syntax grammar is formatted neither as literal nor as placeholder.
+ The synopsis (a paragraph with [synopsis] attribute) is automatically
+ formatted by the toolchain and does not need typesetting.
A few commented examples follow to provide reference when writing or
modifying command usage strings and synopsis sections in the manual
pages:
Possibility of multiple occurrences is indicated by three dots:
- _<file>_...
+ <file>...
(One or more of <file>.)
Optional parts are enclosed in square brackets:
- [_<file>_...]
+ [<file>...]
(Zero or more of <file>.)
- ++--exec-path++[++=++__<path>__]
+ An optional parameter needs to be typeset with unconstrained pairs
+ [<repository>]
+
+ --exec-path[=<path>]
(Option with an optional argument. Note that the "=" is inside the
brackets.)
- [_<patch>_...]
+ [<patch>...]
(Zero or more of <patch>. Note that the dots are inside, not
outside the brackets.)
Multiple alternatives are indicated with vertical bars:
- [`-q` | `--quiet`]
- [`--utf8` | `--no-utf8`]
+ [-q | --quiet]
+ [--utf8 | --no-utf8]
Use spacing around "|" token(s), but not immediately after opening or
before closing a [] or () pair:
- Do: [`-q` | `--quiet`]
- Don't: [`-q`|`--quiet`]
+ Do: [-q | --quiet]
+ Don't: [-q|--quiet]
Don't use spacing around "|" tokens when they're used to separate the
alternate arguments of an option:
- Do: ++--track++[++=++(`direct`|`inherit`)]`
- Don't: ++--track++[++=++(`direct` | `inherit`)]
+ Do: --track[=(direct|inherit)]
+ Don't: --track[=(direct | inherit)]
Parentheses are used for grouping:
- [(_<rev>_ | _<range>_)...]
+ [(<rev>|<range>)...]
(Any number of either <rev> or <range>. Parens are needed to make
it clear that "..." pertains to both <rev> and <range>.)
- [(`-p` _<parent>_)...]
+ [(-p <parent>)...]
(Any number of option -p, each with one <parent> argument.)
- `git remote set-head` _<name>_ (`-a` | `-d` | _<branch>_)
+ git remote set-head <name> (-a|-d|<branch>)
(One and only one of "-a", "-d" or "<branch>" _must_ (no square
brackets) be provided.)
And a somewhat more contrived example:
- `--diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]`
+ --diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]
Here "=" is outside the brackets, because "--diff-filter=" is a
valid usage. "*" has its own pair of brackets, because it can
(optionally) be specified only when one or more of the letters is
diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt
new file mode 100644
index 0000000000..11d02d09aa
--- /dev/null
+++ b/Documentation/RelNotes/2.48.0.txt
@@ -0,0 +1,35 @@
+Git v2.48 Release Notes
+=======================
+
+UI, Workflows & Features
+------------------------
+
+Performance, Internal Implementation, Development Support etc.
+--------------------------------------------------------------
+
+ * Document "amlog" notes.
+ (merge ddfb5bcfc6 tb/notes-amlog-doc later to maint).
+
+ * The way AsciiDoc is used for SYNOPSIS part of the manual pages has
+ been revamped. The sources, at least for the simple cases, got
+ vastly pleasant to work with.
+
+ * The reftable library is now prepared to expect that the memory
+ allocation function given to it may fail to allocate and to deal
+ with such an error.
+
+
+Fixes since v2.47
+-----------------
+
+ * Doc update to clarify how periodical maintenance are scheduled,
+ spread across time to avoid thundering hurds.
+ (merge 3d6ab4177d sk/doc-maintenance-schedule later to maint).
+
+ * Use after free and double freeing at the end in "git log -L... -p"
+ had been identified and fixed.
+ (merge fc5589d6c1 ds/line-log-asan-fix later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+ (merge 66893a14d0 ps/leakfixes-part-8 later to maint).
+ (merge 1164e270b5 jk/output-prefix-cleanup later to maint).
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index 60f76f43ed..f6da6d1fbd 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -28,6 +28,10 @@ ifdef::backend-docbook[]
{0#<citerefentry>}
{0#<refentrytitle>{target}</refentrytitle><manvolnum>{0}</manvolnum>}
{0#</citerefentry>}
+
+[literal-inlinemacro]
+{eval:re.sub(r'(&lt;[-a-zA-Z0-9.]+&gt;)', r'<emphasis>\1</emphasis>', re.sub(r'([\[\s|()>]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1<literal>\2</literal>', re.sub(r'(\.\.\.?)([^\]$.])', r'<literal>\1</literal>\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))}
+
endif::backend-docbook[]
ifdef::backend-docbook[]
@@ -56,4 +60,20 @@ ifdef::backend-xhtml11[]
git-relative-html-prefix=
[linkgit-inlinemacro]
<a href="{git-relative-html-prefix}{target}.html">{target}{0?({0})}</a>
+
+[literal-inlinemacro]
+{eval:re.sub(r'(&lt;[-a-zA-Z0-9.]+&gt;)', r'<em>\1</em>', re.sub(r'([\[\s|()>]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1<code>\2</code>', re.sub(r'(\.\.\.?)([^\]$.])', r'<code>\1</code>\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))}
+
+endif::backend-xhtml11[]
+
+ifdef::backend-docbook[]
+ifdef::doctype-manpage[]
+[paradef-default]
+synopsis-style=template="verseparagraph",filter="sed 's!&#8230;\\(\\]\\|$\\)!<phrase>\\0</phrase>!g;s!\\([\\[ |()]\\|^\\|\\]\\|&gt;\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|&#8230;\\)!\\1<literal>\\2</literal>!g;s!&lt;[-a-zA-Z0-9.]\\+&gt;!<emphasis>\\0</emphasis>!g'"
+endif::doctype-manpage[]
+endif::backend-docbook[]
+
+ifdef::backend-xhtml11[]
+[paradef-default]
+synopsis-style=template="verseparagraph",filter="sed 's!&#8230;\\(\\]\\|$\\)!<span>\\0</span>!g;s!\\([\\[ |()]\\|^\\|\\]\\|&gt;\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|&#8230;\\)!\\1<code>\\2</code>!g;s!&lt;[-a-zA-Z0-9.]\\+&gt;!<em>\\0</em>!g'"
endif::backend-xhtml11[]
diff --git a/Documentation/asciidoctor-extensions.rb b/Documentation/asciidoctor-extensions.rb
index d906a00803..cb24480b63 100644
--- a/Documentation/asciidoctor-extensions.rb
+++ b/Documentation/asciidoctor-extensions.rb
@@ -1,5 +1,7 @@
require 'asciidoctor'
require 'asciidoctor/extensions'
+require 'asciidoctor/converter/docbook5'
+require 'asciidoctor/converter/html5'
module Git
module Documentation
@@ -39,10 +41,95 @@ module Git
output
end
end
+
+ class SynopsisBlock < Asciidoctor::Extensions::BlockProcessor
+
+ use_dsl
+ named :synopsis
+ parse_content_as :simple
+
+ def process parent, reader, attrs
+ outlines = reader.lines.map do |l|
+ l.gsub(/(\.\.\.?)([^\]$.])/, '`\1`\2')
+ .gsub(%r{([\[\] |()>]|^)([-a-zA-Z0-9:+=~@,/_^\$]+)}, '\1{empty}`\2`{empty}')
+ .gsub(/(<[-a-zA-Z0-9.]+>)/, '__\\1__')
+ .gsub(']', ']{empty}')
+ end
+ create_block parent, :verse, outlines, attrs
+ end
+ end
+
+ class GitDBConverter < Asciidoctor::Converter::DocBook5Converter
+
+ extend Asciidoctor::Converter::Config
+ register_for 'docbook5'
+
+ def convert_inline_quoted node
+ if (type = node.type) == :asciimath
+ # NOTE fop requires jeuclid to process mathml markup
+ asciimath_available? ? %(<inlineequation>#{(::AsciiMath.parse node.text).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'}</inlineequation>) : %(<inlineequation><mathphrase><![CDATA[#{node.text}]]></mathphrase></inlineequation>)
+ elsif type == :latexmath
+ # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math
+ %(<inlineequation><alt><![CDATA[#{equation = node.text}]]></alt><mathphrase><![CDATA[#{equation}]]></mathphrase></inlineequation>)
+ elsif type == :monospaced
+ node.text.gsub(/(\.\.\.?)([^\]$.])/, '<literal>\1</literal>\2')
+ .gsub(%r{([\[\s|()>.]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<literal>\2</literal>')
+ .gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '<emphasis>\1</emphasis>')
+ else
+ open, close, supports_phrase = QUOTE_TAGS[type]
+ text = node.text
+ if node.role
+ if supports_phrase
+ quoted_text = %(#{open}<phrase role="#{node.role}">#{text}</phrase>#{close})
+ else
+ quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close})
+ end
+ else
+ quoted_text = %(#{open}#{text}#{close})
+ end
+ node.id ? %(<anchor#{common_attributes node.id, nil, text}/>#{quoted_text}) : quoted_text
+ end
+ end
+ end
+
+ # register a html5 converter that takes in charge to convert monospaced text into Git style synopsis
+ class GitHTMLConverter < Asciidoctor::Converter::Html5Converter
+
+ extend Asciidoctor::Converter::Config
+ register_for 'html5'
+
+ def convert_inline_quoted node
+ if node.type == :monospaced
+ node.text.gsub(/(\.\.\.?)([^\]$.])/, '<code>\1</code>\2')
+ .gsub(%r{([\[\s|()>.]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<code>\2</code>')
+ .gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '<em>\1</em>')
+
+ else
+ open, close, tag = QUOTE_TAGS[node.type]
+ if node.id
+ class_attr = node.role ? %( class="#{node.role}") : ''
+ if tag
+ %(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close})
+ else
+ %(<span id="#{node.id}"#{class_attr}>#{open}#{node.text}#{close}</span>)
+ end
+ elsif node.role
+ if tag
+ %(#{open.chop} class="#{node.role}">#{node.text}#{close})
+ else
+ %(<span class="#{node.role}">#{open}#{node.text}#{close}</span>)
+ end
+ else
+ %(#{open}#{node.text}#{close})
+ end
+ end
+ end
+ end
end
end
Asciidoctor::Extensions.register do
inline_macro Git::Documentation::LinkGitProcessor, :linkgit
+ block Git::Documentation::SynopsisBlock
postprocessor Git::Documentation::DocumentPostProcessor
end
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 8e925db7e9..9c13f847da 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -8,16 +8,16 @@ git-clone - Clone a repository into a new directory
SYNOPSIS
--------
-[verse]
-`git clone` [++--template=++__<template-directory>__]
- [`-l`] [`-s`] [`--no-hardlinks`] [`-q`] [`-n`] [`--bare`] [`--mirror`]
- [`-o` _<name>_] [`-b` _<name>_] [`-u` _<upload-pack>_] [`--reference` _<repository>_]
- [`--dissociate`] [`--separate-git-dir` _<git-dir>_]
- [`--depth` _<depth>_] [`--`[`no-`]{empty}`single-branch`] [`--no-tags`]
- [++--recurse-submodules++[++=++__<pathspec>__]] [++--++[++no-++]{empty}++shallow-submodules++]
- [`--`[`no-`]{empty}`remote-submodules`] [`--jobs` _<n>_] [`--sparse`] [`--`[`no-`]{empty}`reject-shallow`]
- [++--filter=++__<filter-spec>__] [`--also-filter-submodules`]] [`--`] _<repository>_
- [_<directory>_]
+[synopsis]
+git clone [--template=<template-directory>]
+ [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
+ [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
+ [--dissociate] [--separate-git-dir <git-dir>]
+ [--depth <depth>] [--[no-]single-branch] [--no-tags]
+ [--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules]
+ [--[no-]remote-submodules] [--jobs <n>] [--sparse] [--[no-]reject-shallow]
+ [--filter=<filter-spec>] [--also-filter-submodules]] [--] <repository>
+ [<directory>]
DESCRIPTION
-----------
@@ -52,7 +52,7 @@ OPTIONS
to save space when possible.
+
If the repository is specified as a local path (e.g., `/path/to/repo`),
-this is the default, and --local is essentially a no-op. If the
+this is the default, and `--local` is essentially a no-op. If the
repository is specified as a URL, then this flag is ignored (and we
never use the local optimizations). Specifying `--no-local` will
override the default when `/path/to/repo` is given, using the regular
@@ -64,8 +64,8 @@ prevent the unintentional copying of files by dereferencing the symbolic
links.
+
*NOTE*: this operation can race with concurrent modification to the
-source repository, similar to running `cp -r src dst` while modifying
-`src`.
+source repository, similar to running `cp -r <src> <dst>` while modifying
+_<src>_.
`--no-hardlinks`::
Force the cloning process from a repository on a local
@@ -101,7 +101,7 @@ If you want to break the dependency of a repository cloned with `--shared` on
its source repository, you can simply run `git repack -a` to copy all
objects from the source repository into a pack in the cloned repository.
-`--reference`[`-if-able`] _<repository>_::
+`--reference[-if-able] <repository>`::
If the reference _<repository>_ is on the local machine,
automatically setup `.git/objects/info/alternates` to
obtain objects from the reference _<repository>_. Using
@@ -142,17 +142,17 @@ objects from the source repository into a pack in the cloned repository.
is specified. This flag forces progress status even if the
standard error stream is not directed to a terminal.
-++--server-option=++__<option>__::
+`--server-option=<option>`::
Transmit the given string to the server when communicating using
protocol version 2. The given string must not contain a NUL or LF
character. The server's handling of server options, including
unknown ones, is server-specific.
- When multiple ++--server-option=++__<option>__ are given, they are all
+ When multiple `--server-option=<option>` are given, they are all
sent to the other side in the order listed on the command line.
`-n`::
`--no-checkout`::
- No checkout of HEAD is performed after the clone is complete.
+ No checkout of `HEAD` is performed after the clone is complete.
`--`[`no-`]`reject-shallow`::
Fail if the source repository is a shallow repository.
@@ -162,7 +162,7 @@ objects from the source repository into a pack in the cloned repository.
`--bare`::
Make a 'bare' Git repository. That is, instead of
creating _<directory>_ and placing the administrative
- files in _<directory>_`/.git`, make the _<directory>_
+ files in `<directory>/.git`, make the _<directory>_
itself the `$GIT_DIR`. This obviously implies the `--no-checkout`
because there is nowhere to check out the working tree.
Also the branch heads at the remote are copied directly
@@ -177,13 +177,13 @@ objects from the source repository into a pack in the cloned repository.
linkgit:git-sparse-checkout[1] command can be used to grow the
working directory as needed.
-++--filter=++__<filter-spec>__::
+`--filter=<filter-spec>`::
Use the partial clone feature and request that the server sends
a subset of reachable objects according to a given object filter.
When using `--filter`, the supplied _<filter-spec>_ is used for
the partial clone filter. For example, `--filter=blob:none` will
filter out all blobs (file contents) until needed by Git. Also,
- ++--filter=blob:limit=++__<size>__ will filter out all blobs of size
+ `--filter=blob:limit=<size>` will filter out all blobs of size
at least _<size>_. For more details on filter specifications, see
the `--filter` option in linkgit:git-rev-list[1].
@@ -208,11 +208,11 @@ objects from the source repository into a pack in the cloned repository.
`-b` _<name>_::
`--branch` _<name>_::
- Instead of pointing the newly created HEAD to the branch pointed
- to by the cloned repository's HEAD, point to _<name>_ branch
+ Instead of pointing the newly created `HEAD` to the branch pointed
+ to by the cloned repository's `HEAD`, point to _<name>_ branch
instead. In a non-bare repository, this is the branch that will
be checked out.
- `--branch` can also take tags and detaches the HEAD at that commit
+ `--branch` can also take tags and detaches the `HEAD` at that commit
in the resulting repository.
`-u` _<upload-pack>_::
@@ -221,12 +221,12 @@ objects from the source repository into a pack in the cloned repository.
via ssh, this specifies a non-default path for the command
run on the other end.
-++--template=++__<template-directory>__::
+`--template=<template-directory>`::
Specify the directory from which templates will be used;
(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
-`-c` __<key>__++=++__<value>__::
-`--config` __<key>__++=++__<value>__::
+`-c` `<key>=<value>`::
+`--config` `<key>=<value>`::
Set a configuration variable in the newly-created repository;
this takes effect immediately after the repository is
initialized, but before the remote history is fetched or any
@@ -239,25 +239,25 @@ objects from the source repository into a pack in the cloned repository.
Due to limitations of the current implementation, some configuration
variables do not take effect until after the initial fetch and checkout.
Configuration variables known to not take effect are:
-++remote.++__<name>__++.mirror++ and ++remote.++__<name>__++.tagOpt++. Use the
+`remote.<name>.mirror` and `remote.<name>.tagOpt`. Use the
corresponding `--mirror` and `--no-tags` options instead.
-`--depth` _<depth>_::
+`--depth <depth>`::
Create a 'shallow' clone with a history truncated to the
specified number of commits. Implies `--single-branch` unless
`--no-single-branch` is given to fetch the histories near the
tips of all branches. If you want to clone submodules shallowly,
also pass `--shallow-submodules`.
-++--shallow-since=++__<date>__::
+`--shallow-since=<date>`::
Create a shallow clone with a history after the specified time.
-++--shallow-exclude=++__<revision>__::
+`--shallow-exclude=<revision>`::
Create a shallow clone with a history, excluding commits
reachable from a specified remote branch or tag. This option
can be specified multiple times.
-`--`[`no-`]`single-branch`::
+`--[no-]single-branch`::
Clone only the history leading to the tip of a single branch,
either specified by the `--branch` option or the primary
branch remote's `HEAD` points at.
@@ -279,13 +279,13 @@ maintain a branch with no references other than a single cloned
branch. This is useful e.g. to maintain minimal clones of the default
branch of some repository for search indexing.
-`--recurse-submodules`[`=`{empty}__<pathspec>__]::
+`--recurse-submodules[=<pathspec>]`::
After the clone is created, initialize and clone submodules
- within based on the provided _<pathspec>_. If no _=<pathspec>_ is
+ within based on the provided _<pathspec>_. If no `=<pathspec>` is
provided, all submodules are initialized and cloned.
This option can be given multiple times for pathspecs consisting
of multiple entries. The resulting clone has `submodule.active` set to
- the provided pathspec, or "." (meaning all submodules) if no
+ the provided pathspec, or "`.`" (meaning all submodules) if no
pathspec is provided.
+
Submodules are initialized and cloned using their default settings. This is
@@ -295,23 +295,23 @@ the clone is finished. This option is ignored if the cloned repository does
not have a worktree/checkout (i.e. if any of `--no-checkout`/`-n`, `--bare`,
or `--mirror` is given)
-`--`[`no-`]`shallow-submodules`::
+`--[no-]shallow-submodules`::
All submodules which are cloned will be shallow with a depth of 1.
-`--`[`no-`]`remote-submodules`::
+`--[no-]remote-submodules`::
All submodules which are cloned will use the status of the submodule's
remote-tracking branch to update the submodule, rather than the
superproject's recorded SHA-1. Equivalent to passing `--remote` to
`git submodule update`.
-`--separate-git-dir=`{empty}__<git-dir>__::
+`--separate-git-dir=<git-dir>`::
Instead of placing the cloned repository where it is supposed
to be, place the cloned repository at the specified directory,
then make a filesystem-agnostic Git symbolic link to there.
The result is Git repository can be separated from working
tree.
-`--ref-format=`{empty}__<ref-format>__::
+`--ref-format=<ref-format>`::
Specify the given ref storage format for the repository. The valid values are:
+
@@ -334,7 +334,7 @@ _<directory>_::
for `host.xz:foo/.git`). Cloning into an existing directory
is only allowed if the directory is empty.
-`--bundle-uri=`{empty}__<uri>__::
+`--bundle-uri=<uri>`::
Before fetching from the remote, fetch a bundle from the given
_<uri>_ and unbundle the data into the local repository. The refs
in the bundle will be stored under the hidden `refs/bundle/*`
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 7f81fbbea8..3e420177c1 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -12,7 +12,7 @@ SYNOPSIS
'git config list' [<file-option>] [<display-option>] [--includes]
'git config get' [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>
'git config set' [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>
-'git config unset' [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>
+'git config unset' [<file-option>] [--all] [--value=<value>] [--fixed-value] <name>
'git config rename-section' [<file-option>] <old-name> <new-name>
'git config remove-section' [<file-option>] <name>
'git config edit' [<file-option>]
diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index daff93bd16..315f7f7530 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -8,12 +8,12 @@ git-init - Create an empty Git repository or reinitialize an existing one
SYNOPSIS
--------
-[verse]
-`git init` [`-q` | `--quiet`] [`--bare`] [++--template=++__<template-directory>__]
- [`--separate-git-dir` _<git-dir>_] [++--object-format=++__<format>__]
- [++--ref-format=++__<format>__]
- [`-b` _<branch-name>_ | ++--initial-branch=++__<branch-name>__]
- [++--shared++[++=++__<permissions>__]] [_<directory>_]
+[synopsis]
+git init [-q | --quiet] [--bare] [--template=<template-directory>]
+ [--separate-git-dir <git-dir>] [--object-format=<format>]
+ [--ref-format=<format>]
+ [-b <branch-name> | --initial-branch=<branch-name>]
+ [--shared[=<permissions>]] [<directory>]
DESCRIPTION
@@ -25,11 +25,11 @@ directory with subdirectories for `objects`, `refs/heads`,
commits will be created (see the `--initial-branch` option below
for its name).
-If the `$GIT_DIR` environment variable is set then it specifies a path
+If the `GIT_DIR` environment variable is set then it specifies a path
to use instead of `./.git` for the base of the repository.
If the object storage directory is specified via the
-`$GIT_OBJECT_DIRECTORY` environment variable then the sha1 directories
+`GIT_OBJECT_DIRECTORY` environment variable then the sha1 directories
are created underneath; otherwise, the default `$GIT_DIR/objects`
directory is used.
@@ -51,26 +51,22 @@ Only print error and warning messages; all other output will be suppressed.
Create a bare repository. If `GIT_DIR` environment is not set, it is set to the
current working directory.
-++--object-format=++__<format>__::
-
+`--object-format=<format>`::
Specify the given object _<format>_ (hash algorithm) for the repository. The valid
values are `sha1` and (if enabled) `sha256`. `sha1` is the default.
+
include::object-format-disclaimer.txt[]
-++--ref-format=++__<format>__::
-
+`--ref-format=<format>`::
Specify the given ref storage _<format>_ for the repository. The valid values are:
+
include::ref-storage-format.txt[]
-++--template=++__<template-directory>__::
-
+`--template=<template-directory>`::
Specify the directory from which templates will be used. (See the "TEMPLATE
DIRECTORY" section below.)
-++--separate-git-dir=++__<git-dir>__::
-
+`--separate-git-dir=<git-dir>`::
Instead of initializing the repository as a directory to either `$GIT_DIR` or
`./.git/`, create a text file there containing the path to the actual
repository. This file acts as a filesystem-agnostic Git symbolic link to the
@@ -78,15 +74,14 @@ repository.
+
If this is a reinitialization, the repository will be moved to the specified path.
-`-b` _<branch-name>_::
-++--initial-branch=++__<branch-name>__::
-
+`-b <branch-name>`::
+`--initial-branch=<branch-name>`::
Use _<branch-name>_ for the initial branch in the newly created
repository. If not specified, fall back to the default name (currently
`master`, but this is subject to change in the future; the name can be
customized via the `init.defaultBranch` configuration variable).
-++--shared++[++=++(`false`|`true`|`umask`|`group`|`all`|`world`|`everybody`|_<perm>_)]::
+`--shared[=(false|true|umask|group|all|world|everybody|<perm>)]`::
Specify that the Git repository is to be shared amongst several users. This
allows users belonging to the same group to push into that
diff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.txt
index 9d96819133..6e6651309d 100644
--- a/Documentation/git-maintenance.txt
+++ b/Documentation/git-maintenance.txt
@@ -220,7 +220,9 @@ on an hourly basis. Each run executes the "hourly" tasks. At midnight,
that process also executes the "daily" tasks. At midnight on the first day
of the week, that process also executes the "weekly" tasks. A single
process iterates over each registered repository, performing the scheduled
-tasks for that frequency. Depending on the number of registered
+tasks for that frequency. The processes are scheduled to a random minute of
+the hour per client to spread out the load that multiple clients might
+generate (e.g. from prefetching). Depending on the number of registered
repositories and their sizes, this process may take longer than an hour.
In this case, multiple `git maintenance run` commands may run on the same
repository at the same time, colliding on the object database lock. This
diff --git a/Documentation/howto/maintain-git.txt b/Documentation/howto/maintain-git.txt
index e797b32522..45e2599c5d 100644
--- a/Documentation/howto/maintain-git.txt
+++ b/Documentation/howto/maintain-git.txt
@@ -137,6 +137,13 @@ Note that before v1.9.0 release, the version numbers used to be
structured slightly differently. vX.Y.Z were feature releases while
vX.Y.Z.W were maintenance releases for vX.Y.Z.
+Because most of the lines of code in Git are written by individual
+contributors, and contributions come in the form of e-mailed patches
+published on the mailing list, the project maintains a mapping from
+individual commits to the Message-Id of the e-mail that resulted in
+the commit, to help tracking the origin of the changes. The notes
+in "refs/notes/amlog" are used for this purpose, and are published
+along with the broken-out branches to the maintainer's repository.
A Typical Git Day
-----------------
@@ -180,6 +187,43 @@ by doing the following:
In practice, almost no patch directly goes to 'master' or
'maint'.
+ Applying the e-mailed patches using "git am" automatically records
+ the mappings from 'Message-Id' to the applied commit in the "amlog"
+ notes. Periodically check that this is working with "git show -s
+ --notes=amlog $commit".
+
+ This mapping is maintained with the aid of the "post-applypatch"
+ hook found in the 'todo' branch. That hook should be installed
+ before applying patches. It is also helpful to carry forward any
+ relevant amlog entries when rebasing, so the following config may
+ be useful:
+
+ [notes]
+ rewriteRef = refs/notes/amlog
+
+ Avoid "cherry-pick", as it does not propagate notes by design. Use
+ either "git commit --amend" or "git rebase" to make corrections to
+ an existing commit, even for a single-patch topic.
+
+ Make sure that a push refspec for 'refs/notes/amlog' is in the
+ remote configuration for publishing repositories. A few sample
+ configurations look like the following:
+
+ [remote "github"]
+ url = https://github.com/gitster/git
+ pushurl = github.com:gitster/git.git
+ mirror
+
+ [remote "github2"]
+ url = https://github.com/git/git
+ fetch = +refs/heads/*:refs/remotes/github2/*
+ pushurl = github.com:git/git.git
+ push = refs/heads/maint:refs/heads/maint
+ push = refs/heads/master:refs/heads/master
+ push = refs/heads/next:refs/heads/next
+ push = +refs/heads/seen:refs/heads/seen
+ push = +refs/notes/amlog
+
- Review the last issue of "What's cooking" message, review the
topics ready for merging (topic->master and topic->maint). Use
"Meta/cook -w" script (where Meta/ contains a checkout of the
diff --git a/Documentation/urls.txt b/Documentation/urls.txt
index 7cec85aef1..9c871e716a 100644
--- a/Documentation/urls.txt
+++ b/Documentation/urls.txt
@@ -10,19 +10,19 @@ Git supports ssh, git, http, and https protocols (in addition, ftp
and ftps can be used for fetching, but this is inefficient and
deprecated; do not use them).
-The native transport (i.e. git:// URL) does no authentication and
+The native transport (i.e. `git://` URL) does no authentication and
should be used with caution on unsecured networks.
The following syntaxes may be used with them:
-- ++ssh://++{startsb}__<user>__++@++{endsb}__<host>__{startsb}++:++__<port>__{endsb}++/++__<path-to-git-repo>__
-- ++git://++__<host>__{startsb}:__<port>__{endsb}++/++__<path-to-git-repo>__
-- ++http++{startsb}++s++{endsb}++://++__<host>__{startsb}++:++__<port>__{endsb}++/++__<path-to-git-repo>__
-- ++ftp++{startsb}++s++{endsb}++://++__<host>__{startsb}++:++__<port>__{endsb}++/++__<path-to-git-repo>__
+- `ssh://[<user>@]<host>[:<port>]/<path-to-git-repo>`
+- `git://<host>[:<port>]/<path-to-git-repo>`
+- `http[s]://<host>[:<port>]/<path-to-git-repo>`
+- `ftp[s]://<host>[:<port>]/<path-to-git-repo>`
An alternative scp-like syntax may also be used with the ssh protocol:
-- {startsb}__<user>__++@++{endsb}__<host>__++:/++__<path-to-git-repo>__
+- `[<user>@]<host>:/<path-to-git-repo>`
This syntax is only recognized if there are no slashes before the
first colon. This helps differentiate a local path that contains a
@@ -30,17 +30,17 @@ colon. For example the local path `foo:bar` could be specified as an
absolute path or `./foo:bar` to avoid being misinterpreted as an ssh
url.
-The ssh and git protocols additionally support ++~++__<username>__ expansion:
+The ssh and git protocols additionally support `~<username>` expansion:
-- ++ssh://++{startsb}__<user>__++@++{endsb}__<host>__{startsb}++:++__<port>__{endsb}++/~++__<user>__++/++__<path-to-git-repo>__
-- ++git://++__<host>__{startsb}++:++__<port>__{endsb}++/~++__<user>__++/++__<path-to-git-repo>__
-- {startsb}__<user>__++@++{endsb}__<host>__++:~++__<user>__++/++__<path-to-git-repo>__
+- `ssh://[<user>@]<host>[:<port>]/~<user>/<path-to-git-repo>`
+- `git://<host>[:<port>]/~<user>/<path-to-git-repo>`
+- `[<user>@]<host>:~<user>/<path-to-git-repo>`
For local repositories, also supported by Git natively, the following
syntaxes may be used:
- `/path/to/repo.git/`
-- ++file:///path/to/repo.git/++
+- `file:///path/to/repo.git/`
ifndef::git-clone[]
These two syntaxes are mostly equivalent, except when cloning, when
@@ -57,11 +57,11 @@ endif::git-clone[]
accept a suitable bundle file. See linkgit:git-bundle[1].
When Git doesn't know how to handle a certain transport protocol, it
-attempts to use the `remote-`{empty}__<transport>__ remote helper, if one
+attempts to use the `remote-<transport>` remote helper, if one
exists. To explicitly request a remote helper, the following syntax
may be used:
-- _<transport>_::__<address>__
+- `<transport>::<address>`
where _<address>_ may be a path, a server and path, or an arbitrary
URL-like string recognized by the specific remote helper being
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index b3265f7bec..78e8631f67 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.47.0
+DEF_VER=v2.47.GIT
LF='
'
diff --git a/Makefile b/Makefile
index 2dde1fd2b8..feeed6f932 100644
--- a/Makefile
+++ b/Makefile
@@ -2717,7 +2717,6 @@ REFTABLE_OBJS += reftable/error.o
REFTABLE_OBJS += reftable/block.o
REFTABLE_OBJS += reftable/blocksource.o
REFTABLE_OBJS += reftable/iter.o
-REFTABLE_OBJS += reftable/publicbasics.o
REFTABLE_OBJS += reftable/merged.o
REFTABLE_OBJS += reftable/pq.o
REFTABLE_OBJS += reftable/reader.o
diff --git a/RelNotes b/RelNotes
index 0104513a31..061d699283 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.47.0.txt \ No newline at end of file
+Documentation/RelNotes/2.48.0.txt \ No newline at end of file
diff --git a/bloom.c b/bloom.c
index c915f8b1ba..c428634105 100644
--- a/bloom.c
+++ b/bloom.c
@@ -476,8 +476,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
*last_slash = '\0';
} while (*path);
-
- diff_free_filepair(diff_queued_diff.queue[i]);
}
if (hashmap_get_size(&pathmap) > settings->max_changed_paths) {
@@ -508,8 +506,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
cleanup:
hashmap_clear_and_free(&pathmap, struct pathmap_hash_entry, entry);
} else {
- for (i = 0; i < diff_queued_diff.nr; i++)
- diff_free_filepair(diff_queued_diff.queue[i]);
init_truncated_large_filter(filter, settings->hash_version);
if (computed)
@@ -519,9 +515,7 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
if (computed)
*computed |= BLOOM_COMPUTED;
- free(diff_queued_diff.queue);
- DIFF_QUEUE_CLEAR(&diff_queued_diff);
-
+ diff_queue_clear(&diff_queued_diff);
return filter;
}
diff --git a/branch.c b/branch.c
index 08fa4094d2..44977ad0aa 100644
--- a/branch.c
+++ b/branch.c
@@ -738,6 +738,7 @@ static int submodule_create_branch(struct repository *r,
strbuf_release(&child_err);
strbuf_release(&out_buf);
+ free(out_prefix);
return ret;
}
@@ -794,7 +795,7 @@ void create_branches_recursively(struct repository *r, const char *name,
create_branch(r, name, start_committish, force, 0, reflog, quiet,
BRANCH_TRACK_NEVER, dry_run);
if (dry_run)
- return;
+ goto out;
/*
* NEEDSWORK If tracking was set up in the superproject but not the
* submodule, users might expect "git branch --recurse-submodules" to
@@ -815,8 +816,11 @@ void create_branches_recursively(struct repository *r, const char *name,
die(_("submodule '%s': cannot create branch '%s'"),
submodule_entry_list.entries[i].submodule->name,
name);
- repo_clear(submodule_entry_list.entries[i].repo);
}
+
+out:
+ submodule_entry_list_release(&submodule_entry_list);
+ free(branch_point);
}
void remove_merge_branch_state(struct repository *r)
diff --git a/builtin/annotate.c b/builtin/annotate.c
index a99179fe4d..03413c7df8 100644
--- a/builtin/annotate.c
+++ b/builtin/annotate.c
@@ -15,13 +15,23 @@ int cmd_annotate(int argc,
struct repository *repo UNUSED)
{
struct strvec args = STRVEC_INIT;
- int i;
+ const char **args_copy;
+ int ret;
strvec_pushl(&args, "annotate", "-c", NULL);
-
- for (i = 1; i < argc; i++) {
+ for (int i = 1; i < argc; i++)
strvec_push(&args, argv[i]);
- }
- return cmd_blame(args.nr, args.v, prefix, the_repository);
+ /*
+ * `cmd_blame()` ends up modifying the array, which causes memory leaks
+ * if we didn't copy the array here.
+ */
+ CALLOC_ARRAY(args_copy, args.nr + 1);
+ COPY_ARRAY(args_copy, args.v, args.nr);
+
+ ret = cmd_blame(args.nr, args_copy, prefix, the_repository);
+
+ strvec_clear(&args);
+ free(args_copy);
+ return ret;
}
diff --git a/builtin/clone.c b/builtin/clone.c
index e77339c847..59fcb317a6 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1403,8 +1403,17 @@ int cmd_clone(int argc,
* data from the --bundle-uri option.
*/
if (bundle_uri) {
+ struct remote_state *state;
int has_heuristic = 0;
+ /*
+ * We need to save the remote state as our remote's lifetime is
+ * tied to it.
+ */
+ state = the_repository->remote_state;
+ the_repository->remote_state = NULL;
+ repo_clear(the_repository);
+
/* At this point, we need the_repository to match the cloned repo. */
if (repo_init(the_repository, git_dir, work_tree))
warning(_("failed to initialize the repo, skipping bundle URI"));
@@ -1413,6 +1422,10 @@ int cmd_clone(int argc,
bundle_uri);
else if (has_heuristic)
git_config_set_gently("fetch.bundleuri", bundle_uri);
+
+ remote_state_clear(the_repository->remote_state);
+ free(the_repository->remote_state);
+ the_repository->remote_state = state;
} else {
/*
* Populate transport->got_remote_bundle_uri and
@@ -1422,12 +1435,26 @@ int cmd_clone(int argc,
if (transport->bundles &&
hashmap_get_size(&transport->bundles->bundles)) {
+ struct remote_state *state;
+
+ /*
+ * We need to save the remote state as our remote's
+ * lifetime is tied to it.
+ */
+ state = the_repository->remote_state;
+ the_repository->remote_state = NULL;
+ repo_clear(the_repository);
+
/* At this point, we need the_repository to match the cloned repo. */
if (repo_init(the_repository, git_dir, work_tree))
warning(_("failed to initialize the repo, skipping bundle URI"));
else if (fetch_bundle_list(the_repository,
transport->bundles))
warning(_("failed to fetch advertised bundles"));
+
+ remote_state_clear(the_repository->remote_state);
+ free(the_repository->remote_state);
+ the_repository->remote_state = state;
} else {
clear_bundle_list(transport->bundles);
FREE_AND_NULL(transport->bundles);
diff --git a/builtin/config.c b/builtin/config.c
index d8fd3def0e..cba7022108 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -19,7 +19,7 @@ static const char *const builtin_config_usage[] = {
N_("git config list [<file-option>] [<display-option>] [--includes]"),
N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>"),
N_("git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
- N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
+ N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name>"),
N_("git config rename-section [<file-option>] <old-name> <new-name>"),
N_("git config remove-section [<file-option>] <name>"),
N_("git config edit [<file-option>]"),
@@ -43,7 +43,7 @@ static const char *const builtin_config_set_usage[] = {
};
static const char *const builtin_config_unset_usage[] = {
- N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
+ N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name>"),
NULL
};
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index e228c56ff2..9d23b41b3a 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1505,7 +1505,7 @@ static void rename_tmp_packfile(const char **final_name,
struct strbuf *name, unsigned char *hash,
const char *ext, int make_read_only_if_same)
{
- if (*final_name != curr_name) {
+ if (!*final_name || strcmp(*final_name, curr_name)) {
if (!*final_name)
*final_name = odb_pack_name(name, hash, ext);
if (finalize_object_file(curr_name, *final_name))
@@ -1726,7 +1726,7 @@ int cmd_index_pack(int argc,
{
int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index;
const char *curr_index;
- const char *curr_rev_index = NULL;
+ char *curr_rev_index = NULL;
const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL;
const char *keep_msg = NULL;
const char *promisor_msg = NULL;
@@ -1968,8 +1968,7 @@ int cmd_index_pack(int argc,
free((void *) curr_pack);
if (!index_name)
free((void *) curr_index);
- if (!rev_index_name)
- free((void *) curr_rev_index);
+ free(curr_rev_index);
/*
* Let the caller know this pack is not self contained
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index 81f4494d46..5809613002 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -69,6 +69,15 @@ static inline void llist_init(struct llist **list)
(*list)->size = 0;
}
+static void llist_free(struct llist *list)
+{
+ for (struct llist_item *i = list->front, *next; i; i = next) {
+ next = i->next;
+ llist_item_put(i);
+ }
+ free(list);
+}
+
static struct llist * llist_copy(struct llist *list)
{
struct llist *ret;
@@ -206,6 +215,14 @@ static inline struct pack_list * pack_list_insert(struct pack_list **pl,
return p;
}
+static void pack_list_free(struct pack_list *pl)
+{
+ for (struct pack_list *next; pl; pl = next) {
+ next = pl->next;
+ free(pl);
+ }
+}
+
static inline size_t pack_list_size(struct pack_list *pl)
{
size_t ret = 0;
@@ -419,7 +436,8 @@ static void minimize(struct pack_list **min)
/* return if there are no objects missing from the unique set */
if (missing->size == 0) {
- free(missing);
+ llist_free(missing);
+ pack_list_free(non_unique);
return;
}
@@ -434,6 +452,8 @@ static void minimize(struct pack_list **min)
}
while (non_unique) {
+ struct pack_list *next;
+
/* sort the non_unique packs, greater size of remaining_objects first */
sort_pack_list(&non_unique);
if (non_unique->remaining_objects->size == 0)
@@ -444,8 +464,14 @@ static void minimize(struct pack_list **min)
for (pl = non_unique->next; pl && pl->remaining_objects->size > 0; pl = pl->next)
llist_sorted_difference_inplace(pl->remaining_objects, non_unique->remaining_objects);
- non_unique = non_unique->next;
+ next = non_unique->next;
+ free(non_unique);
+ non_unique = next;
}
+
+ pack_list_free(non_unique);
+ llist_free(unique_pack_objects);
+ llist_free(missing);
}
static void load_all_objects(void)
@@ -565,7 +591,6 @@ static void load_all(void)
int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) {
int i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl;
struct llist *ignore;
- struct object_id *oid;
char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */
if (argc == 2 && !strcmp(argv[1], "-h"))
@@ -625,11 +650,11 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s
/* ignore objects given on stdin */
llist_init(&ignore);
if (!isatty(0)) {
+ struct object_id oid;
while (fgets(buf, sizeof(buf), stdin)) {
- oid = xmalloc(sizeof(*oid));
- if (get_oid_hex(buf, oid))
+ if (get_oid_hex(buf, &oid))
die("Bad object ID on stdin: %s", buf);
- llist_insert_sorted_unique(ignore, oid, NULL);
+ llist_insert_sorted_unique(ignore, &oid, NULL);
}
}
llist_sorted_difference_inplace(all_objects, ignore);
@@ -671,5 +696,8 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s
fprintf(stderr, "%luMB of redundant packs in total.\n",
(unsigned long)pack_set_bytecount(red)/(1024*1024));
+ pack_list_free(red);
+ pack_list_free(min);
+ llist_free(ignore);
return 0;
}
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 536d22761d..ab5b20e39c 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -374,6 +374,7 @@ static void write_head_info(void)
struct command {
struct command *next;
const char *error_string;
+ char *error_string_owned;
struct ref_push_report *report;
unsigned int skip_update:1,
did_not_exist:1,
@@ -1083,7 +1084,7 @@ static int read_proc_receive_report(struct packet_reader *reader,
hint->run_proc_receive |= RUN_PROC_RECEIVE_RETURNED;
if (!strcmp(head, "ng")) {
if (p)
- hint->error_string = xstrdup(p);
+ hint->error_string = hint->error_string_owned = xstrdup(p);
else
hint->error_string = "failed";
code = -1;
@@ -2054,6 +2055,8 @@ static void free_commands(struct command *commands)
while (commands) {
struct command *next = commands->next;
+ ref_push_report_free(commands->report);
+ free(commands->error_string_owned);
free(commands);
commands = next;
}
diff --git a/builtin/revert.c b/builtin/revert.c
index 55ba1092c5..b7917dddd3 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -110,6 +110,9 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
const char * const * usage_str = revert_or_cherry_pick_usage(opts);
const char *me = action_name(opts);
const char *cleanup_arg = NULL;
+ const char sentinel_value;
+ const char *strategy = &sentinel_value;
+ const char *gpg_sign = &sentinel_value;
enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED;
int cmd = 0;
struct option base_options[] = {
@@ -125,10 +128,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
OPT_CALLBACK('m', "mainline", opts, N_("parent-number"),
N_("select mainline parent"), option_parse_m),
OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
- OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")),
+ OPT_STRING(0, "strategy", &strategy, N_("strategy"), N_("merge strategy")),
OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"),
N_("option for merge strategy")),
- { OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"),
+ { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
OPT_END()
};
@@ -240,8 +243,14 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
usage_with_options(usage_str, options);
/* These option values will be free()d */
- opts->gpg_sign = xstrdup_or_null(opts->gpg_sign);
- opts->strategy = xstrdup_or_null(opts->strategy);
+ if (gpg_sign != &sentinel_value) {
+ free(opts->gpg_sign);
+ opts->gpg_sign = xstrdup_or_null(gpg_sign);
+ }
+ if (strategy != &sentinel_value) {
+ free(opts->strategy);
+ opts->strategy = xstrdup_or_null(strategy);
+ }
if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM"))
opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM"));
free(options);
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 8b1d46e79a..59b626aae8 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -340,6 +340,7 @@ int cmd_send_pack(int argc,
/* stable plumbing output; do not modify or localize */
fprintf(stderr, "Everything up-to-date\n");
+ string_list_clear(&push_options, 0);
free_refs(remote_refs);
free_refs(local_refs);
refspec_clear(&rs);
diff --git a/builtin/stash.c b/builtin/stash.c
index f1acc918d0..1399a1bbe2 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1759,7 +1759,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
int quiet = 0;
int pathspec_file_nul = 0;
const char *stash_msg = NULL;
- const char *pathspec_from_file = NULL;
+ char *pathspec_from_file = NULL;
struct pathspec ps;
struct option options[] = {
OPT_BOOL('k', "keep-index", &keep_index,
@@ -1821,7 +1821,9 @@ static int push_stash(int argc, const char **argv, const char *prefix,
ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
include_untracked, only_staged);
+
clear_pathspec(&ps);
+ free(pathspec_from_file);
return ret;
}
diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index 08656a1530..126e570eb4 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -119,6 +119,7 @@ Documentation)
test -n "$ALREADY_HAVE_ASCIIDOCTOR" ||
sudo gem install --version 1.5.8 asciidoctor
+ sudo gem install concurrent-ruby
;;
esac
diff --git a/diff-lib.c b/diff-lib.c
index a680768ee7..6b14b95962 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -701,7 +701,7 @@ int index_differs_from(struct repository *r,
return (has_changes != 0);
}
-static struct strbuf *idiff_prefix_cb(struct diff_options *opt UNUSED, void *data)
+static const char *idiff_prefix_cb(struct diff_options *opt UNUSED, void *data)
{
return data;
}
@@ -716,7 +716,7 @@ void show_interdiff(const struct object_id *oid1, const struct object_id *oid2,
opts.output_format = DIFF_FORMAT_PATCH;
opts.output_prefix = idiff_prefix_cb;
strbuf_addchars(&prefix, ' ', indent);
- opts.output_prefix_data = &prefix;
+ opts.output_prefix_data = prefix.buf;
diff_setup_done(&opts);
diff_tree_oid(oid1, oid2, "", &opts);
diff --git a/diff.c b/diff.c
index 173cbe2bed..dceac20d18 100644
--- a/diff.c
+++ b/diff.c
@@ -2317,12 +2317,9 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix)
const char *diff_line_prefix(struct diff_options *opt)
{
- struct strbuf *msgbuf;
- if (!opt->output_prefix)
- return "";
-
- msgbuf = opt->output_prefix(opt, opt->output_prefix_data);
- return msgbuf->buf;
+ return opt->output_prefix ?
+ opt->output_prefix(opt, opt->output_prefix_data) :
+ "";
}
static unsigned long sane_truncate_line(char *line, unsigned long len)
@@ -5400,7 +5397,6 @@ static int diff_opt_line_prefix(const struct option *opt,
BUG_ON_OPT_NEG(unset);
options->line_prefix = optarg;
- options->line_prefix_length = strlen(options->line_prefix);
graph_setup_line_prefix(options);
return 0;
}
@@ -5983,11 +5979,18 @@ void diff_free_filepair(struct diff_filepair *p)
free(p);
}
-void diff_free_queue(struct diff_queue_struct *q)
+void diff_queue_init(struct diff_queue_struct *q)
+{
+ struct diff_queue_struct blank = DIFF_QUEUE_INIT;
+ memcpy(q, &blank, sizeof(*q));
+}
+
+void diff_queue_clear(struct diff_queue_struct *q)
{
for (int i = 0; i < q->nr; i++)
diff_free_filepair(q->queue[i]);
free(q->queue);
+ diff_queue_init(q);
}
const char *diff_aligned_abbrev(const struct object_id *oid, int len)
@@ -6551,8 +6554,7 @@ int diff_flush_patch_id(struct diff_options *options, struct object_id *oid, int
struct diff_queue_struct *q = &diff_queued_diff;
int result = diff_get_patch_id(options, oid, diff_header_only);
- diff_free_queue(q);
- DIFF_QUEUE_CLEAR(q);
+ diff_queue_clear(q);
return result;
}
@@ -6835,8 +6837,7 @@ void diff_flush(struct diff_options *options)
}
free_queue:
- diff_free_queue(q);
- DIFF_QUEUE_CLEAR(q);
+ diff_queue_clear(q);
diff_free(options);
/*
@@ -6867,9 +6868,7 @@ static void diffcore_apply_filter(struct diff_options *options)
{
int i;
struct diff_queue_struct *q = &diff_queued_diff;
- struct diff_queue_struct outq;
-
- DIFF_QUEUE_CLEAR(&outq);
+ struct diff_queue_struct outq = DIFF_QUEUE_INIT;
if (!options->filter)
return;
@@ -6962,8 +6961,7 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
{
int i;
struct diff_queue_struct *q = &diff_queued_diff;
- struct diff_queue_struct outq;
- DIFF_QUEUE_CLEAR(&outq);
+ struct diff_queue_struct outq = DIFF_QUEUE_INIT;
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
diff --git a/diff.h b/diff.h
index 0cde3b34e2..5c8de79535 100644
--- a/diff.h
+++ b/diff.h
@@ -94,7 +94,7 @@ typedef void (*add_remove_fn_t)(struct diff_options *options,
typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
struct diff_options *options, void *data);
-typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data);
+typedef const char *(*diff_prefix_fn_t)(struct diff_options *opt, void *data);
#define DIFF_FORMAT_RAW 0x0001
#define DIFF_FORMAT_DIFFSTAT 0x0002
@@ -274,7 +274,6 @@ struct diff_options {
const char *single_follow;
const char *a_prefix, *b_prefix;
const char *line_prefix;
- size_t line_prefix_length;
/**
* collection of boolean options that affects the operation, but some do
diff --git a/diffcore-break.c b/diffcore-break.c
index 02735f80c6..c4c2173f30 100644
--- a/diffcore-break.c
+++ b/diffcore-break.c
@@ -131,7 +131,7 @@ static int should_break(struct repository *r,
void diffcore_break(struct repository *r, int break_score)
{
struct diff_queue_struct *q = &diff_queued_diff;
- struct diff_queue_struct outq;
+ struct diff_queue_struct outq = DIFF_QUEUE_INIT;
/* When the filepair has this much edit (insert and delete),
* it is first considered to be a rewrite and broken into a
@@ -178,8 +178,6 @@ void diffcore_break(struct repository *r, int break_score)
if (!merge_score)
merge_score = DEFAULT_MERGE_SCORE;
- DIFF_QUEUE_CLEAR(&outq);
-
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
int score;
@@ -275,11 +273,9 @@ static void merge_broken(struct diff_filepair *p,
void diffcore_merge_broken(void)
{
struct diff_queue_struct *q = &diff_queued_diff;
- struct diff_queue_struct outq;
+ struct diff_queue_struct outq = DIFF_QUEUE_INIT;
int i, j;
- DIFF_QUEUE_CLEAR(&outq);
-
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
if (!p)
diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c
index b195fa4eb3..43fef8e8ba 100644
--- a/diffcore-pickaxe.c
+++ b/diffcore-pickaxe.c
@@ -182,9 +182,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
regex_t *regexp, kwset_t kws, pickaxe_fn fn)
{
int i;
- struct diff_queue_struct outq;
-
- DIFF_QUEUE_CLEAR(&outq);
+ struct diff_queue_struct outq = DIFF_QUEUE_INIT;
if (o->pickaxe_opts & DIFF_PICKAXE_ALL) {
/* Showing the whole changeset if needle exists */
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 3d6826baa3..1b1c1a6a1f 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -1388,7 +1388,7 @@ void diffcore_rename_extended(struct diff_options *options,
int detect_rename = options->detect_rename;
int minimum_score = options->rename_score;
struct diff_queue_struct *q = &diff_queued_diff;
- struct diff_queue_struct outq;
+ struct diff_queue_struct outq = DIFF_QUEUE_INIT;
struct diff_score *mx;
int i, j, rename_count, skip_unmodified = 0;
int num_destinations, dst_cnt;
@@ -1638,7 +1638,6 @@ void diffcore_rename_extended(struct diff_options *options,
* are recorded in rename_dst. The original list is still in *q.
*/
trace2_region_enter("diff", "write back to queue", options->repo);
- DIFF_QUEUE_CLEAR(&outq);
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
struct diff_filepair *pair_to_free = NULL;
diff --git a/diffcore-rotate.c b/diffcore-rotate.c
index 533986cf63..73ca20b331 100644
--- a/diffcore-rotate.c
+++ b/diffcore-rotate.c
@@ -10,7 +10,7 @@
void diffcore_rotate(struct diff_options *opt)
{
struct diff_queue_struct *q = &diff_queued_diff;
- struct diff_queue_struct outq;
+ struct diff_queue_struct outq = DIFF_QUEUE_INIT;
int rotate_to, i;
if (!q->nr)
@@ -31,7 +31,6 @@ void diffcore_rotate(struct diff_options *opt)
return;
}
- DIFF_QUEUE_CLEAR(&outq);
rotate_to = i;
for (i = rotate_to; i < q->nr; i++)
diff --git a/diffcore.h b/diffcore.h
index 1701ed50b9..2feb325031 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -153,18 +153,16 @@ struct diff_queue_struct {
int nr;
};
-#define DIFF_QUEUE_CLEAR(q) \
- do { \
- (q)->queue = NULL; \
- (q)->nr = (q)->alloc = 0; \
- } while (0)
+#define DIFF_QUEUE_INIT { 0 }
+
+void diff_queue_init(struct diff_queue_struct *q);
+void diff_queue_clear(struct diff_queue_struct *q);
extern struct diff_queue_struct diff_queued_diff;
struct diff_filepair *diff_queue(struct diff_queue_struct *,
struct diff_filespec *,
struct diff_filespec *);
void diff_q(struct diff_queue_struct *, struct diff_filepair *);
-void diff_free_queue(struct diff_queue_struct *q);
/* dir_rename_relevance: the reason we want rename information for a dir */
enum dir_rename_relevance {
diff --git a/graph.c b/graph.c
index 091c14cf4f..bf000fdbe1 100644
--- a/graph.c
+++ b/graph.c
@@ -76,10 +76,7 @@ static void graph_show_line_prefix(const struct diff_options *diffopt)
if (!diffopt || !diffopt->line_prefix)
return;
- fwrite(diffopt->line_prefix,
- sizeof(char),
- diffopt->line_prefix_length,
- diffopt->file);
+ fputs(diffopt->line_prefix, diffopt->file);
}
static const char **column_colors;
@@ -312,22 +309,28 @@ struct git_graph {
* stored as an index into the array column_colors.
*/
unsigned short default_column_color;
+
+ /*
+ * Scratch buffer for generating prefixes to be used with
+ * diff_output_prefix_callback().
+ */
+ struct strbuf prefix_buf;
};
-static struct strbuf *diff_output_prefix_callback(struct diff_options *opt, void *data)
+static const char *diff_output_prefix_callback(struct diff_options *opt, void *data)
{
struct git_graph *graph = data;
- static struct strbuf msgbuf = STRBUF_INIT;
assert(opt);
- strbuf_reset(&msgbuf);
+ if (!graph)
+ return opt->line_prefix;
+
+ strbuf_reset(&graph->prefix_buf);
if (opt->line_prefix)
- strbuf_add(&msgbuf, opt->line_prefix,
- opt->line_prefix_length);
- if (graph)
- graph_padding_line(graph, &msgbuf);
- return &msgbuf;
+ strbuf_addstr(&graph->prefix_buf, opt->line_prefix);
+ graph_padding_line(graph, &graph->prefix_buf);
+ return graph->prefix_buf.buf;
}
static const struct diff_options *default_diffopt;
@@ -397,6 +400,7 @@ struct git_graph *graph_init(struct rev_info *opt)
* The diff output prefix callback, with this we can make
* all the diff output to align with the graph lines.
*/
+ strbuf_init(&graph->prefix_buf, 0);
opt->diffopt.output_prefix = diff_output_prefix_callback;
opt->diffopt.output_prefix_data = graph;
@@ -412,6 +416,7 @@ void graph_clear(struct git_graph *graph)
free(graph->new_columns);
free(graph->mapping);
free(graph->old_mapping);
+ strbuf_release(&graph->prefix_buf);
free(graph);
}
diff --git a/line-log.c b/line-log.c
index 67c80b39a0..bca9bd8040 100644
--- a/line-log.c
+++ b/line-log.c
@@ -248,8 +248,10 @@ static void line_log_data_init(struct line_log_data *r)
static void line_log_data_clear(struct line_log_data *r)
{
range_set_release(&r->ranges);
+ free(r->path);
if (r->pair)
diff_free_filepair(r->pair);
+ diff_ranges_release(&r->diff);
}
static void free_line_log_data(struct line_log_data *r)
@@ -571,7 +573,8 @@ parse_lines(struct repository *r, struct commit *commit,
struct line_log_data *p;
for_each_string_list_item(item, args) {
- const char *name_part, *range_part;
+ const char *name_part;
+ char *range_part;
char *full_name;
struct diff_filespec *spec;
long begin = 0, end = 0;
@@ -615,6 +618,7 @@ parse_lines(struct repository *r, struct commit *commit,
free_filespec(spec);
FREE_AND_NULL(ends);
+ free(range_part);
}
for (p = ranges; p; p = p->next)
@@ -760,15 +764,13 @@ static void parse_pathspec_from_ranges(struct pathspec *pathspec,
{
struct line_log_data *r;
struct strvec array = STRVEC_INIT;
- const char **paths;
for (r = range; r; r = r->next)
strvec_push(&array, r->path);
- paths = strvec_detach(&array);
- parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL, "", paths);
- /* strings are now owned by pathspec */
- free(paths);
+ parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL, "", array.v);
+
+ strvec_clear(&array);
}
void line_log_init(struct rev_info *rev, const char *prefix, struct string_list *args)
@@ -781,21 +783,22 @@ void line_log_init(struct rev_info *rev, const char *prefix, struct string_list
add_line_range(rev, commit, range);
parse_pathspec_from_ranges(&rev->diffopt.pathspec, range);
+
+ free_line_log_data(range);
}
static void move_diff_queue(struct diff_queue_struct *dst,
struct diff_queue_struct *src)
{
assert(src != dst);
- memcpy(dst, src, sizeof(struct diff_queue_struct));
- DIFF_QUEUE_CLEAR(src);
+ memcpy(dst, src, sizeof(*dst));
+ diff_queue_init(src);
}
static void filter_diffs_for_paths(struct line_log_data *range, int keep_deletions)
{
int i;
- struct diff_queue_struct outq;
- DIFF_QUEUE_CLEAR(&outq);
+ struct diff_queue_struct outq = DIFF_QUEUE_INIT;
for (i = 0; i < diff_queued_diff.nr; i++) {
struct diff_filepair *p = diff_queued_diff.queue[i];
@@ -850,12 +853,12 @@ static void queue_diffs(struct line_log_data *range,
clear_pathspec(&opt->pathspec);
parse_pathspec_from_ranges(&opt->pathspec, range);
}
- DIFF_QUEUE_CLEAR(&diff_queued_diff);
+ diff_queue_clear(&diff_queued_diff);
diff_tree_oid(parent_tree_oid, tree_oid, "", opt);
if (opt->detect_rename && diff_might_be_rename()) {
/* must look at the full tree diff to detect renames */
clear_pathspec(&opt->pathspec);
- DIFF_QUEUE_CLEAR(&diff_queued_diff);
+ diff_queue_clear(&diff_queued_diff);
diff_tree_oid(parent_tree_oid, tree_oid, "", opt);
@@ -897,16 +900,6 @@ static void print_line(const char *prefix, char first,
fputs("\\ No newline at end of file\n", file);
}
-static char *output_prefix(struct diff_options *opt)
-{
- if (opt->output_prefix) {
- struct strbuf *sb = opt->output_prefix(opt, opt->output_prefix_data);
- return sb->buf;
- } else {
- return xstrdup("");
- }
-}
-
static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *range)
{
unsigned int i, j = 0;
@@ -916,7 +909,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang
struct diff_ranges *diff = &range->diff;
struct diff_options *opt = &rev->diffopt;
- char *prefix = output_prefix(opt);
+ const char *prefix = diff_line_prefix(opt);
const char *c_reset = diff_get_color(opt->use_color, DIFF_RESET);
const char *c_frag = diff_get_color(opt->use_color, DIFF_FRAGINFO);
const char *c_meta = diff_get_color(opt->use_color, DIFF_METAINFO);
@@ -1003,7 +996,6 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang
out:
free(p_ends);
free(t_ends);
- free(prefix);
}
/*
@@ -1012,10 +1004,9 @@ out:
*/
static void dump_diff_hacky(struct rev_info *rev, struct line_log_data *range)
{
- char *prefix = output_prefix(&rev->diffopt);
+ const char *prefix = diff_line_prefix(&rev->diffopt);
fprintf(rev->diffopt.file, "%s\n", prefix);
- free(prefix);
while (range) {
dump_diff_hacky_one(rev, range);
@@ -1097,7 +1088,7 @@ static struct diff_filepair *diff_filepair_dup(struct diff_filepair *pair)
static void free_diffqueues(int n, struct diff_queue_struct *dq)
{
for (int i = 0; i < n; i++)
- diff_free_queue(&dq[i]);
+ diff_queue_clear(&dq[i]);
free(dq);
}
@@ -1132,10 +1123,18 @@ static int process_all_files(struct line_log_data **range_out,
while (rg && strcmp(rg->path, pair->two->path))
rg = rg->next;
assert(rg);
+ if (rg->pair)
+ diff_free_filepair(rg->pair);
rg->pair = diff_filepair_dup(queue->queue[i]);
+ diff_ranges_release(&rg->diff);
memcpy(&rg->diff, pairdiff, sizeof(struct diff_ranges));
+ FREE_AND_NULL(pairdiff);
+ }
+
+ if (pairdiff) {
+ diff_ranges_release(pairdiff);
+ free(pairdiff);
}
- free(pairdiff);
}
return changed;
@@ -1200,7 +1199,7 @@ static int process_ranges_ordinary_commit(struct rev_info *rev, struct commit *c
if (parent)
add_line_range(rev, parent, parent_range);
free_line_log_data(parent_range);
- diff_free_queue(&queue);
+ diff_queue_clear(&queue);
return changed;
}
@@ -1213,12 +1212,13 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
struct commit_list *p;
int i;
int nparents = commit_list_count(commit->parents);
+ int ret;
if (nparents > 1 && rev->first_parent_only)
nparents = 1;
ALLOC_ARRAY(diffqueues, nparents);
- ALLOC_ARRAY(cand, nparents);
+ CALLOC_ARRAY(cand, nparents);
ALLOC_ARRAY(parents, nparents);
p = commit->parents;
@@ -1230,7 +1230,6 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
for (i = 0; i < nparents; i++) {
int changed;
- cand[i] = NULL;
changed = process_all_files(&cand[i], rev, &diffqueues[i], range);
if (!changed) {
/*
@@ -1238,13 +1237,10 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
* don't follow any other path in history
*/
add_line_range(rev, parents[i], cand[i]);
- clear_commit_line_range(rev, commit);
commit_list_append(parents[i], &commit->parents);
- free(parents);
- free(cand);
- free_diffqueues(nparents, diffqueues);
- /* NEEDSWORK leaking like a sieve */
- return 0;
+
+ ret = 0;
+ goto out;
}
}
@@ -1252,18 +1248,25 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
* No single parent took the blame. We add the candidates
* from the above loop to the parents.
*/
- for (i = 0; i < nparents; i++) {
+ for (i = 0; i < nparents; i++)
add_line_range(rev, parents[i], cand[i]);
- }
+ ret = 1;
+
+out:
clear_commit_line_range(rev, commit);
free(parents);
+ for (i = 0; i < nparents; i++) {
+ if (!cand[i])
+ continue;
+ line_log_data_clear(cand[i]);
+ free(cand[i]);
+ }
free(cand);
free_diffqueues(nparents, diffqueues);
- return 1;
+ return ret;
/* NEEDSWORK evil merge detection stuff */
- /* NEEDSWORK leaking like a sieve */
}
int line_log_process_ranges_arbitrary_commit(struct rev_info *rev, struct commit *commit)
diff --git a/log-tree.c b/log-tree.c
index 3758e0d3b8..ba5632805e 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -675,7 +675,7 @@ static void show_diff_of_diff(struct rev_info *opt)
struct diff_queue_struct dq;
memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff));
- DIFF_QUEUE_CLEAR(&diff_queued_diff);
+ diff_queue_init(&diff_queued_diff);
fprintf_ln(opt->diffopt.file, "\n%s", opt->idiff_title);
show_interdiff(opt->idiff_oid1, opt->idiff_oid2, 2,
@@ -694,7 +694,7 @@ static void show_diff_of_diff(struct rev_info *opt)
};
memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff));
- DIFF_QUEUE_CLEAR(&diff_queued_diff);
+ diff_queue_init(&diff_queued_diff);
fprintf_ln(opt->diffopt.file, "\n%s", opt->rdiff_title);
/*
@@ -922,12 +922,7 @@ int log_tree_diff_flush(struct rev_info *opt)
* diff/diffstat output for readability.
*/
int pch = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_PATCH;
- if (opt->diffopt.output_prefix) {
- struct strbuf *msg = NULL;
- msg = opt->diffopt.output_prefix(&opt->diffopt,
- opt->diffopt.output_prefix_data);
- fwrite(msg->buf, msg->len, 1, opt->diffopt.file);
- }
+ fputs(diff_line_prefix(&opt->diffopt), opt->diffopt.file);
/*
* We may have shown three-dashes line early
diff --git a/merge-ort.c b/merge-ort.c
index 8b81153e8f..11029c10be 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -3536,7 +3536,7 @@ simple_cleanup:
/* Free memory for renames->pairs[] and combined */
for (s = MERGE_SIDE1; s <= MERGE_SIDE2; s++) {
free(renames->pairs[s].queue);
- DIFF_QUEUE_CLEAR(&renames->pairs[s]);
+ diff_queue_init(&renames->pairs[s]);
}
for (i = 0; i < combined.nr; i++)
pool_diff_free_filepair(&opt->priv->pool, combined.queue[i]);
diff --git a/midx-write.c b/midx-write.c
index 1ef62c4f4b..b3a5f6c516 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -649,7 +649,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,
struct write_midx_context *ctx)
{
struct strbuf buf = STRBUF_INIT;
- const char *tmp_file;
+ char *tmp_file;
trace2_region_enter("midx", "write_midx_reverse_index", the_repository);
@@ -662,6 +662,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,
die(_("cannot store reverse index file"));
strbuf_release(&buf);
+ free(tmp_file);
trace2_region_leave("midx", "write_midx_reverse_index", the_repository);
}
@@ -1445,6 +1446,8 @@ static int write_midx_internal(const char *object_dir,
return -1;
}
+ strbuf_release(&final_midx_name);
+
keep_hashes[ctx.num_multi_pack_indexes_before] =
xstrdup(hash_to_hex(midx_hash));
diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index 4dc0fe8e40..49758e2525 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -64,6 +64,12 @@ static void free_pseudo_merge_commit_idx(struct pseudo_merge_commit_idx *idx)
free(idx);
}
+static void pseudo_merge_group_release_cb(void *payload, const char *name UNUSED)
+{
+ pseudo_merge_group_release(payload);
+ free(payload);
+}
+
void bitmap_writer_free(struct bitmap_writer *writer)
{
uint32_t i;
@@ -82,6 +88,8 @@ void bitmap_writer_free(struct bitmap_writer *writer)
kh_foreach_value(writer->pseudo_merge_commits, idx,
free_pseudo_merge_commit_idx(idx));
kh_destroy_oid_map(writer->pseudo_merge_commits);
+ string_list_clear_func(&writer->pseudo_merge_groups,
+ pseudo_merge_group_release_cb);
for (i = 0; i < writer->selected_nr; i++) {
struct bitmapped_commit *bc = &writer->selected[i];
@@ -905,6 +913,7 @@ static void write_pseudo_merges(struct bitmap_writer *writer,
for (i = 0; i < writer->pseudo_merges_nr; i++)
bitmap_free(commits_bitmap[i]);
+ oid_array_clear(&commits);
free(pseudo_merge_ofs);
free(commits_bitmap);
}
diff --git a/pack-bitmap.c b/pack-bitmap.c
index 9d9b8c4bfb..32b222a7af 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -1390,8 +1390,8 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
}
base = bitmap_new();
- if (!cascade_pseudo_merges_1(bitmap_git, base, roots_bitmap))
- bitmap_free(roots_bitmap);
+ cascade_pseudo_merges_1(bitmap_git, base, roots_bitmap);
+ bitmap_free(roots_bitmap);
}
/*
diff --git a/pack-write.c b/pack-write.c
index f415604c15..8c7dfddc5a 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -213,15 +213,15 @@ static void write_rev_trailer(struct hashfile *f, const unsigned char *hash)
hashwrite(f, hash, the_hash_algo->rawsz);
}
-const char *write_rev_file(const char *rev_name,
- struct pack_idx_entry **objects,
- uint32_t nr_objects,
- const unsigned char *hash,
- unsigned flags)
+char *write_rev_file(const char *rev_name,
+ struct pack_idx_entry **objects,
+ uint32_t nr_objects,
+ const unsigned char *hash,
+ unsigned flags)
{
uint32_t *pack_order;
uint32_t i;
- const char *ret;
+ char *ret;
if (!(flags & WRITE_REV) && !(flags & WRITE_REV_VERIFY))
return NULL;
@@ -239,13 +239,14 @@ const char *write_rev_file(const char *rev_name,
return ret;
}
-const char *write_rev_file_order(const char *rev_name,
- uint32_t *pack_order,
- uint32_t nr_objects,
- const unsigned char *hash,
- unsigned flags)
+char *write_rev_file_order(const char *rev_name,
+ uint32_t *pack_order,
+ uint32_t nr_objects,
+ const unsigned char *hash,
+ unsigned flags)
{
struct hashfile *f;
+ char *path;
int fd;
if ((flags & WRITE_REV) && (flags & WRITE_REV_VERIFY))
@@ -255,12 +256,13 @@ const char *write_rev_file_order(const char *rev_name,
if (!rev_name) {
struct strbuf tmp_file = STRBUF_INIT;
fd = odb_mkstemp(&tmp_file, "pack/tmp_rev_XXXXXX");
- rev_name = strbuf_detach(&tmp_file, NULL);
+ path = strbuf_detach(&tmp_file, NULL);
} else {
unlink(rev_name);
fd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
+ path = xstrdup(rev_name);
}
- f = hashfd(fd, rev_name);
+ f = hashfd(fd, path);
} else if (flags & WRITE_REV_VERIFY) {
struct stat statbuf;
if (stat(rev_name, &statbuf)) {
@@ -271,22 +273,24 @@ const char *write_rev_file_order(const char *rev_name,
die_errno(_("could not stat: %s"), rev_name);
}
f = hashfd_check(rev_name);
- } else
+ path = xstrdup(rev_name);
+ } else {
return NULL;
+ }
write_rev_header(f);
write_rev_index_positions(f, pack_order, nr_objects);
write_rev_trailer(f, hash);
- if (rev_name && adjust_shared_perm(rev_name) < 0)
- die(_("failed to make %s readable"), rev_name);
+ if (adjust_shared_perm(path) < 0)
+ die(_("failed to make %s readable"), path);
finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,
CSUM_HASH_IN_STREAM | CSUM_CLOSE |
((flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));
- return rev_name;
+ return path;
}
static void write_mtimes_header(struct hashfile *f)
@@ -550,7 +554,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
unsigned char hash[],
char **idx_tmp_name)
{
- const char *rev_tmp_name = NULL;
+ char *rev_tmp_name = NULL;
char *mtimes_tmp_name = NULL;
if (adjust_shared_perm(pack_tmp_name))
@@ -576,7 +580,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
if (mtimes_tmp_name)
rename_tmp_packfile(name_buffer, mtimes_tmp_name, "mtimes");
- free((char *)rev_tmp_name);
+ free(rev_tmp_name);
free(mtimes_tmp_name);
}
diff --git a/pack.h b/pack.h
index 3ab9e3f60c..02bbdfb19c 100644
--- a/pack.h
+++ b/pack.h
@@ -96,8 +96,8 @@ struct ref;
void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought);
-const char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
-const char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
+char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
+char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
/*
* The "hdr" output buffer should be at least this big, which will handle sizes
diff --git a/pseudo-merge.c b/pseudo-merge.c
index 10ebd9a4e9..bb59965ed2 100644
--- a/pseudo-merge.c
+++ b/pseudo-merge.c
@@ -87,7 +87,7 @@ static void pseudo_merge_group_init(struct pseudo_merge_group *group)
{
memset(group, 0, sizeof(struct pseudo_merge_group));
- strmap_init_with_options(&group->matches, NULL, 0);
+ strmap_init_with_options(&group->matches, NULL, 1);
group->decay = DEFAULT_PSEUDO_MERGE_DECAY;
group->max_merges = DEFAULT_PSEUDO_MERGE_MAX_MERGES;
@@ -97,6 +97,25 @@ static void pseudo_merge_group_init(struct pseudo_merge_group *group)
group->stable_size = DEFAULT_PSEUDO_MERGE_STABLE_SIZE;
}
+void pseudo_merge_group_release(struct pseudo_merge_group *group)
+{
+ struct hashmap_iter iter;
+ struct strmap_entry *e;
+
+ regfree(group->pattern);
+ free(group->pattern);
+
+ strmap_for_each_entry(&group->matches, &iter, e) {
+ struct pseudo_merge_matches *matches = e->value;
+ free(matches->stable);
+ free(matches->unstable);
+ free(matches);
+ }
+ strmap_clear(&group->matches, 0);
+
+ free(group->merges);
+}
+
static int pseudo_merge_config(const char *var, const char *value,
const struct config_context *ctx,
void *cb_data)
@@ -256,7 +275,7 @@ static int find_pseudo_merge_group_for_ref(const char *refname,
matches = strmap_get(&group->matches, group_name.buf);
if (!matches) {
matches = xcalloc(1, sizeof(*matches));
- strmap_put(&group->matches, strbuf_detach(&group_name, NULL),
+ strmap_put(&group->matches, group_name.buf,
matches);
}
diff --git a/pseudo-merge.h b/pseudo-merge.h
index 4b5febaa63..29df8a32ec 100644
--- a/pseudo-merge.h
+++ b/pseudo-merge.h
@@ -51,6 +51,8 @@ struct pseudo_merge_group {
timestamp_t stable_threshold;
};
+void pseudo_merge_group_release(struct pseudo_merge_group *group);
+
struct pseudo_merge_matches {
struct commit **stable;
struct commit **unstable;
diff --git a/range-diff.c b/range-diff.c
index bbb0952264..10885ba301 100644
--- a/range-diff.c
+++ b/range-diff.c
@@ -480,7 +480,7 @@ static void patch_diff(const char *a, const char *b,
diff_flush(diffopt);
}
-static struct strbuf *output_prefix_cb(struct diff_options *opt UNUSED, void *data)
+static const char *output_prefix_cb(struct diff_options *opt UNUSED, void *data)
{
return data;
}
@@ -508,7 +508,7 @@ static void output(struct string_list *a, struct string_list *b,
opts.flags.suppress_hunk_header_line_count = 1;
opts.output_prefix = output_prefix_cb;
strbuf_addstr(&indent, " ");
- opts.output_prefix_data = &indent;
+ opts.output_prefix_data = indent.buf;
diff_setup_done(&opts);
/*
diff --git a/read-cache.c b/read-cache.c
index 3c078afadb..1148a55873 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -3125,6 +3125,7 @@ out:
if (f)
free_hashfile(f);
strbuf_release(&sb);
+ free(eoie_c);
free(ieot);
return ret;
}
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 3c96fbf66f..3c6107c7ce 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1320,7 +1320,9 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
struct reftable_log_record log = {0};
struct reftable_iterator it = {0};
- reftable_stack_init_log_iterator(arg->stack, &it);
+ ret = reftable_stack_init_log_iterator(arg->stack, &it);
+ if (ret < 0)
+ goto done;
/*
* When deleting refs we also delete all reflog entries
@@ -1690,7 +1692,10 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
* copy over all log entries from the old reflog. Last but not least,
* when renaming we also have to delete all the old reflog entries.
*/
- reftable_stack_init_log_iterator(arg->stack, &it);
+ ret = reftable_stack_init_log_iterator(arg->stack, &it);
+ if (ret < 0)
+ goto done;
+
ret = reftable_iterator_seek_log(&it, arg->oldname);
if (ret < 0)
goto done;
@@ -1911,7 +1916,10 @@ static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftabl
if (ret < 0)
goto done;
- reftable_stack_init_log_iterator(stack, &iter->iter);
+ ret = reftable_stack_init_log_iterator(stack, &iter->iter);
+ if (ret < 0)
+ goto done;
+
ret = reftable_iterator_seek_log(&iter->iter, "");
if (ret < 0)
goto done;
@@ -1978,7 +1986,10 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
if (refs->err < 0)
return refs->err;
- reftable_stack_init_log_iterator(stack, &it);
+ ret = reftable_stack_init_log_iterator(stack, &it);
+ if (ret < 0)
+ goto done;
+
ret = reftable_iterator_seek_log(&it, refname);
while (!ret) {
ret = reftable_iterator_next_log(&it, &log);
@@ -1994,6 +2005,7 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
break;
}
+done:
reftable_log_record_release(&log);
reftable_iterator_destroy(&it);
return ret;
@@ -2015,7 +2027,10 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
if (refs->err < 0)
return refs->err;
- reftable_stack_init_log_iterator(stack, &it);
+ ret = reftable_stack_init_log_iterator(stack, &it);
+ if (ret < 0)
+ goto done;
+
ret = reftable_iterator_seek_log(&it, refname);
while (!ret) {
struct reftable_log_record log = {0};
@@ -2065,7 +2080,10 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
if (ret < 0)
goto done;
- reftable_stack_init_log_iterator(stack, &it);
+ ret = reftable_stack_init_log_iterator(stack, &it);
+ if (ret < 0)
+ goto done;
+
ret = reftable_iterator_seek_log(&it, refname);
if (ret < 0)
goto done;
@@ -2171,7 +2189,9 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da
reftable_writer_set_limits(writer, ts, ts);
- reftable_stack_init_log_iterator(arg->stack, &it);
+ ret = reftable_stack_init_log_iterator(arg->stack, &it);
+ if (ret < 0)
+ goto out;
/*
* In order to delete a table we need to delete all reflog entries one
@@ -2195,6 +2215,7 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da
ret = reftable_writer_add_log(writer, &tombstone);
}
+out:
reftable_log_record_release(&log);
reftable_iterator_destroy(&it);
return ret;
@@ -2333,7 +2354,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
if (ret < 0)
goto done;
- reftable_stack_init_log_iterator(stack, &it);
+ ret = reftable_stack_init_log_iterator(stack, &it);
+ if (ret < 0)
+ goto done;
ret = reftable_iterator_seek_log(&it, refname);
if (ret < 0)
diff --git a/reftable/basics.c b/reftable/basics.c
index 0058619ca6..9a949e5cf8 100644
--- a/reftable/basics.c
+++ b/reftable/basics.c
@@ -6,7 +6,68 @@ license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/
+#define REFTABLE_ALLOW_BANNED_ALLOCATORS
#include "basics.h"
+#include "reftable-basics.h"
+
+static void *(*reftable_malloc_ptr)(size_t sz);
+static void *(*reftable_realloc_ptr)(void *, size_t);
+static void (*reftable_free_ptr)(void *);
+
+void *reftable_malloc(size_t sz)
+{
+ if (reftable_malloc_ptr)
+ return (*reftable_malloc_ptr)(sz);
+ return malloc(sz);
+}
+
+void *reftable_realloc(void *p, size_t sz)
+{
+ if (reftable_realloc_ptr)
+ return (*reftable_realloc_ptr)(p, sz);
+ return realloc(p, sz);
+}
+
+void reftable_free(void *p)
+{
+ if (reftable_free_ptr)
+ reftable_free_ptr(p);
+ else
+ free(p);
+}
+
+void *reftable_calloc(size_t nelem, size_t elsize)
+{
+ void *p;
+
+ if (nelem && elsize > SIZE_MAX / nelem)
+ return NULL;
+
+ p = reftable_malloc(nelem * elsize);
+ if (!p)
+ return NULL;
+
+ memset(p, 0, nelem * elsize);
+ return p;
+}
+
+char *reftable_strdup(const char *str)
+{
+ size_t len = strlen(str);
+ char *result = reftable_malloc(len + 1);
+ if (!result)
+ return NULL;
+ memcpy(result, str, len + 1);
+ return result;
+}
+
+void reftable_set_alloc(void *(*malloc)(size_t),
+ void *(*realloc)(void *, size_t), void (*free)(void *))
+{
+ reftable_malloc_ptr = malloc;
+ reftable_realloc_ptr = realloc;
+ reftable_free_ptr = free;
+}
void put_be24(uint8_t *out, uint32_t i)
{
@@ -75,14 +136,14 @@ size_t names_length(const char **names)
return p - names;
}
-void parse_names(char *buf, int size, char ***namesp)
+char **parse_names(char *buf, int size)
{
char **names = NULL;
size_t names_cap = 0;
size_t names_len = 0;
-
char *p = buf;
char *end = buf + size;
+
while (p < end) {
char *next = strchr(p, '\n');
if (next && next < end) {
@@ -91,15 +152,29 @@ void parse_names(char *buf, int size, char ***namesp)
next = end;
}
if (p < next) {
- REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap);
- names[names_len++] = xstrdup(p);
+ char **names_grown = names;
+ REFTABLE_ALLOC_GROW(names_grown, names_len + 1, names_cap);
+ if (!names_grown)
+ goto err;
+ names = names_grown;
+
+ names[names_len] = reftable_strdup(p);
+ if (!names[names_len++])
+ goto err;
}
p = next + 1;
}
REFTABLE_REALLOC_ARRAY(names, names_len + 1);
names[names_len] = NULL;
- *namesp = names;
+
+ return names;
+
+err:
+ for (size_t i = 0; i < names_len; i++)
+ reftable_free(names[i]);
+ reftable_free(names);
+ return NULL;
}
int names_equal(const char **a, const char **b)
@@ -121,3 +196,15 @@ int common_prefix_size(struct strbuf *a, struct strbuf *b)
return p;
}
+
+int hash_size(uint32_t id)
+{
+ switch (id) {
+ case 0:
+ case GIT_SHA1_FORMAT_ID:
+ return GIT_SHA1_RAWSZ;
+ case GIT_SHA256_FORMAT_ID:
+ return GIT_SHA256_RAWSZ;
+ }
+ abort();
+}
diff --git a/reftable/basics.h b/reftable/basics.h
index c8fec68d4e..4c9ef0fe6c 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -14,6 +14,7 @@ https://developers.google.com/open-source/licenses/bsd
*/
#include "system.h"
+#include "reftable-basics.h"
/* Bigendian en/decoding of integers */
@@ -37,9 +38,12 @@ size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args);
*/
void free_names(char **a);
-/* parse a newline separated list of names. `size` is the length of the buffer,
- * without terminating '\0'. Empty names are discarded. */
-void parse_names(char *buf, int size, char ***namesp);
+/*
+ * Parse a newline separated list of names. `size` is the length of the buffer,
+ * without terminating '\0'. Empty names are discarded. Returns a `NULL`
+ * pointer when allocations fail.
+ */
+char **parse_names(char *buf, int size);
/* compares two NULL-terminated arrays of strings. */
int names_equal(const char **a, const char **b);
@@ -53,6 +57,7 @@ void *reftable_malloc(size_t sz);
void *reftable_realloc(void *p, size_t sz);
void reftable_free(void *p);
void *reftable_calloc(size_t nelem, size_t elsize);
+char *reftable_strdup(const char *str);
#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc)))
#define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x)))
@@ -66,9 +71,26 @@ void *reftable_calloc(size_t nelem, size_t elsize);
REFTABLE_REALLOC_ARRAY(x, alloc); \
} \
} while (0)
+#define REFTABLE_FREE_AND_NULL(p) do { reftable_free(p); (p) = NULL; } while (0)
+
+#ifndef REFTABLE_ALLOW_BANNED_ALLOCATORS
+# define REFTABLE_BANNED(func) use_reftable_##func##_instead
+# undef malloc
+# define malloc(sz) REFTABLE_BANNED(malloc)
+# undef realloc
+# define realloc(ptr, sz) REFTABLE_BANNED(realloc)
+# undef free
+# define free(ptr) REFTABLE_BANNED(free)
+# undef calloc
+# define calloc(nelem, elsize) REFTABLE_BANNED(calloc)
+# undef strdup
+# define strdup(str) REFTABLE_BANNED(strdup)
+#endif
/* Find the longest shared prefix size of `a` and `b` */
struct strbuf;
int common_prefix_size(struct strbuf *a, struct strbuf *b);
+int hash_size(uint32_t id);
+
#endif
diff --git a/reftable/block.c b/reftable/block.c
index 00030eee06..8d41a2f99e 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -52,6 +52,8 @@ static int block_writer_register_restart(struct block_writer *w, int n,
return -1;
if (is_restart) {
REFTABLE_ALLOC_GROW(w->restarts, w->restart_len + 1, w->restart_cap);
+ if (!w->restarts)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
w->restarts[w->restart_len++] = w->next;
}
@@ -63,8 +65,8 @@ static int block_writer_register_restart(struct block_writer *w, int n,
return 0;
}
-void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
- uint32_t block_size, uint32_t header_off, int hash_size)
+int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
+ uint32_t block_size, uint32_t header_off, int hash_size)
{
bw->buf = buf;
bw->hash_size = hash_size;
@@ -78,8 +80,12 @@ void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
bw->last_key.len = 0;
if (!bw->zstream) {
REFTABLE_CALLOC_ARRAY(bw->zstream, 1);
+ if (!bw->zstream)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
deflateInit(bw->zstream, 9);
}
+
+ return 0;
}
uint8_t block_writer_type(struct block_writer *bw)
@@ -163,6 +169,10 @@ int block_writer_finish(struct block_writer *w)
*/
compressed_len = deflateBound(w->zstream, src_len);
REFTABLE_ALLOC_GROW(w->compressed, compressed_len, w->compressed_cap);
+ if (!w->compressed) {
+ ret = REFTABLE_OUT_OF_MEMORY_ERROR;
+ return ret;
+ }
w->zstream->next_out = w->compressed;
w->zstream->avail_out = compressed_len;
@@ -219,12 +229,21 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
/* Log blocks specify the *uncompressed* size in their header. */
REFTABLE_ALLOC_GROW(br->uncompressed_data, sz,
br->uncompressed_cap);
+ if (!br->uncompressed_data) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
/* Copy over the block header verbatim. It's not compressed. */
memcpy(br->uncompressed_data, block->data, block_header_skip);
if (!br->zstream) {
REFTABLE_CALLOC_ARRAY(br->zstream, 1);
+ if (!br->zstream) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+
err = inflateInit(br->zstream);
} else {
err = inflateReset(br->zstream);
@@ -532,9 +551,9 @@ done:
void block_writer_release(struct block_writer *bw)
{
deflateEnd(bw->zstream);
- FREE_AND_NULL(bw->zstream);
- FREE_AND_NULL(bw->restarts);
- FREE_AND_NULL(bw->compressed);
+ REFTABLE_FREE_AND_NULL(bw->zstream);
+ REFTABLE_FREE_AND_NULL(bw->restarts);
+ REFTABLE_FREE_AND_NULL(bw->compressed);
strbuf_release(&bw->last_key);
/* the block is not owned. */
}
diff --git a/reftable/block.h b/reftable/block.h
index 1c8f25ee6e..18d7ea0337 100644
--- a/reftable/block.h
+++ b/reftable/block.h
@@ -45,8 +45,8 @@ struct block_writer {
/*
* initializes the blockwriter to write `typ` entries, using `buf` as temporary
* storage. `buf` is not owned by the block_writer. */
-void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
- uint32_t block_size, uint32_t header_off, int hash_size);
+int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
+ uint32_t block_size, uint32_t header_off, int hash_size);
/* returns the block type (eg. 'r' for ref records. */
uint8_t block_writer_type(struct block_writer *bw);
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index e93cac9bb6..a2a6a196d5 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -30,6 +30,8 @@ static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,
struct strbuf *b = v;
assert(off + size <= b->len);
REFTABLE_CALLOC_ARRAY(dest->data, size);
+ if (!dest->data)
+ return -1;
memcpy(dest->data, b->buf + off, size);
dest->len = size;
return size;
@@ -98,27 +100,40 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
{
struct file_block_source *p;
struct stat st;
- int fd;
+ int fd, err;
fd = open(name, O_RDONLY);
if (fd < 0) {
if (errno == ENOENT)
return REFTABLE_NOT_EXIST_ERROR;
- return -1;
+ err = -1;
+ goto out;
}
if (fstat(fd, &st) < 0) {
- close(fd);
- return REFTABLE_IO_ERROR;
+ err = REFTABLE_IO_ERROR;
+ goto out;
}
REFTABLE_CALLOC_ARRAY(p, 1);
+ if (!p) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
+
p->size = st.st_size;
p->data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- close(fd);
assert(!bs->ops);
bs->ops = &file_vtable;
bs->arg = p;
+
+ err = 0;
+
+out:
+ if (fd >= 0)
+ close(fd);
+ if (err < 0)
+ reftable_free(p);
return 0;
}
diff --git a/reftable/error.c b/reftable/error.c
index a25f28a43e..660d029617 100644
--- a/reftable/error.c
+++ b/reftable/error.c
@@ -35,6 +35,8 @@ const char *reftable_error_str(int err)
return "entry too large";
case REFTABLE_OUTDATED_ERROR:
return "data concurrently modified";
+ case REFTABLE_OUT_OF_MEMORY_ERROR:
+ return "out of memory";
case -1:
return "general error";
default:
diff --git a/reftable/iter.c b/reftable/iter.c
index 416a9f6996..d926db653b 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -181,14 +181,20 @@ static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
}
}
-int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
+int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest,
struct reftable_reader *r, uint8_t *oid,
int oid_len, uint64_t *offsets, int offset_len)
{
struct indexed_table_ref_iter empty = INDEXED_TABLE_REF_ITER_INIT;
- struct indexed_table_ref_iter *itr = reftable_calloc(1, sizeof(*itr));
+ struct indexed_table_ref_iter *itr;
int err = 0;
+ itr = reftable_calloc(1, sizeof(*itr));
+ if (!itr) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
+
*itr = empty;
itr->r = r;
strbuf_add(&itr->oid, oid, oid_len);
@@ -197,10 +203,16 @@ int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
itr->offset_len = offset_len;
err = indexed_table_ref_iter_next_block(itr);
+ if (err < 0)
+ goto out;
+
+ *dest = itr;
+ err = 0;
+
+out:
if (err < 0) {
+ *dest = NULL;
reftable_free(itr);
- } else {
- *dest = itr;
}
return err;
}
@@ -225,7 +237,7 @@ void reftable_iterator_destroy(struct reftable_iterator *it)
return;
it->ops->close(it->iter_arg);
it->ops = NULL;
- FREE_AND_NULL(it->iter_arg);
+ REFTABLE_FREE_AND_NULL(it->iter_arg);
}
int reftable_iterator_seek_ref(struct reftable_iterator *it,
diff --git a/reftable/iter.h b/reftable/iter.h
index befc4597df..b3225bc7ad 100644
--- a/reftable/iter.h
+++ b/reftable/iter.h
@@ -82,7 +82,7 @@ void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
struct indexed_table_ref_iter *itr);
/* Takes ownership of `offsets` */
-int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
+int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest,
struct reftable_reader *r, uint8_t *oid,
int oid_len, uint64_t *offsets, int offset_len);
diff --git a/reftable/merged.c b/reftable/merged.c
index 128a810c55..514d6facf4 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -30,22 +30,6 @@ struct merged_iter {
ssize_t advance_index;
};
-static void merged_iter_init(struct merged_iter *mi,
- struct reftable_merged_table *mt,
- uint8_t typ)
-{
- memset(mi, 0, sizeof(*mi));
- mi->advance_index = -1;
- mi->suppress_deletions = mt->suppress_deletions;
-
- REFTABLE_CALLOC_ARRAY(mi->subiters, mt->readers_len);
- for (size_t i = 0; i < mt->readers_len; i++) {
- reftable_record_init(&mi->subiters[i].rec, typ);
- reader_init_iter(mt->readers[i], &mi->subiters[i].iter, typ);
- }
- mi->subiters_len = mt->readers_len;
-}
-
static void merged_iter_close(void *p)
{
struct merged_iter *mi = p;
@@ -70,7 +54,10 @@ static int merged_iter_advance_subiter(struct merged_iter *mi, size_t idx)
if (err)
return err;
- merged_iter_pqueue_add(&mi->pq, &e);
+ err = merged_iter_pqueue_add(&mi->pq, &e);
+ if (err)
+ return err;
+
return 0;
}
@@ -216,6 +203,9 @@ int reftable_merged_table_new(struct reftable_merged_table **dest,
}
REFTABLE_CALLOC_ARRAY(m, 1);
+ if (!m)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
m->readers = readers;
m->readers_len = n;
m->min = first_min;
@@ -244,25 +234,63 @@ reftable_merged_table_min_update_index(struct reftable_merged_table *mt)
return mt->min;
}
-void merged_table_init_iter(struct reftable_merged_table *mt,
- struct reftable_iterator *it,
- uint8_t typ)
+int merged_table_init_iter(struct reftable_merged_table *mt,
+ struct reftable_iterator *it,
+ uint8_t typ)
{
- struct merged_iter *mi = reftable_malloc(sizeof(*mi));
- merged_iter_init(mi, mt, typ);
+ struct merged_subiter *subiters;
+ struct merged_iter *mi = NULL;
+ int ret;
+
+ REFTABLE_CALLOC_ARRAY(subiters, mt->readers_len);
+ if (!subiters) {
+ ret = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
+
+ for (size_t i = 0; i < mt->readers_len; i++) {
+ reftable_record_init(&subiters[i].rec, typ);
+ ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ);
+ if (ret < 0)
+ goto out;
+ }
+
+ REFTABLE_CALLOC_ARRAY(mi, 1);
+ if (!mi) {
+ ret = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
+ mi->advance_index = -1;
+ mi->suppress_deletions = mt->suppress_deletions;
+ mi->subiters = subiters;
+ mi->subiters_len = mt->readers_len;
+
iterator_from_merged_iter(it, mi);
+ ret = 0;
+
+out:
+ if (ret < 0) {
+ for (size_t i = 0; subiters && i < mt->readers_len; i++) {
+ reftable_iterator_destroy(&subiters[i].iter);
+ reftable_record_release(&subiters[i].rec);
+ }
+ reftable_free(subiters);
+ reftable_free(mi);
+ }
+
+ return ret;
}
-void reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt,
- struct reftable_iterator *it)
+int reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt,
+ struct reftable_iterator *it)
{
- merged_table_init_iter(mt, it, BLOCK_TYPE_REF);
+ return merged_table_init_iter(mt, it, BLOCK_TYPE_REF);
}
-void reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt,
- struct reftable_iterator *it)
+int reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt,
+ struct reftable_iterator *it)
{
- merged_table_init_iter(mt, it, BLOCK_TYPE_LOG);
+ return merged_table_init_iter(mt, it, BLOCK_TYPE_LOG);
}
uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt)
diff --git a/reftable/merged.h b/reftable/merged.h
index de5fd33f01..89bd0c4b35 100644
--- a/reftable/merged.h
+++ b/reftable/merged.h
@@ -26,8 +26,8 @@ struct reftable_merged_table {
struct reftable_iterator;
-void merged_table_init_iter(struct reftable_merged_table *mt,
- struct reftable_iterator *it,
- uint8_t typ);
+int merged_table_init_iter(struct reftable_merged_table *mt,
+ struct reftable_iterator *it,
+ uint8_t typ);
#endif
diff --git a/reftable/pq.c b/reftable/pq.c
index 2b5b7d1c0e..6ee1164dd3 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -8,6 +8,7 @@ https://developers.google.com/open-source/licenses/bsd
#include "pq.h"
+#include "reftable-error.h"
#include "reftable-record.h"
#include "system.h"
#include "basics.h"
@@ -44,11 +45,13 @@ struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
return e;
}
-void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e)
+int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e)
{
size_t i = 0;
REFTABLE_ALLOC_GROW(pq->heap, pq->len + 1, pq->cap);
+ if (!pq->heap)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
pq->heap[pq->len++] = *e;
i = pq->len - 1;
@@ -59,10 +62,12 @@ void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry
SWAP(pq->heap[j], pq->heap[i]);
i = j;
}
+
+ return 0;
}
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq)
{
- FREE_AND_NULL(pq->heap);
+ REFTABLE_FREE_AND_NULL(pq->heap);
memset(pq, 0, sizeof(*pq));
}
diff --git a/reftable/pq.h b/reftable/pq.h
index 707bd26767..83c062eeca 100644
--- a/reftable/pq.h
+++ b/reftable/pq.h
@@ -23,7 +23,7 @@ struct merged_iter_pqueue {
};
struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq);
-void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e);
+int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e);
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq);
int pq_less(struct pq_entry *a, struct pq_entry *b);
diff --git a/reftable/publicbasics.c b/reftable/publicbasics.c
deleted file mode 100644
index 44b84a125e..0000000000
--- a/reftable/publicbasics.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-Copyright 2020 Google LLC
-
-Use of this source code is governed by a BSD-style
-license that can be found in the LICENSE file or at
-https://developers.google.com/open-source/licenses/bsd
-*/
-
-#include "system.h"
-#include "reftable-malloc.h"
-
-#include "basics.h"
-
-static void *(*reftable_malloc_ptr)(size_t sz);
-static void *(*reftable_realloc_ptr)(void *, size_t);
-static void (*reftable_free_ptr)(void *);
-
-void *reftable_malloc(size_t sz)
-{
- if (reftable_malloc_ptr)
- return (*reftable_malloc_ptr)(sz);
- return malloc(sz);
-}
-
-void *reftable_realloc(void *p, size_t sz)
-{
- if (reftable_realloc_ptr)
- return (*reftable_realloc_ptr)(p, sz);
- return realloc(p, sz);
-}
-
-void reftable_free(void *p)
-{
- if (reftable_free_ptr)
- reftable_free_ptr(p);
- else
- free(p);
-}
-
-void *reftable_calloc(size_t nelem, size_t elsize)
-{
- size_t sz = st_mult(nelem, elsize);
- void *p = reftable_malloc(sz);
- memset(p, 0, sz);
- return p;
-}
-
-void reftable_set_alloc(void *(*malloc)(size_t),
- void *(*realloc)(void *, size_t), void (*free)(void *))
-{
- reftable_malloc_ptr = malloc;
- reftable_realloc_ptr = realloc;
- reftable_free_ptr = free;
-}
-
-int hash_size(uint32_t id)
-{
- switch (id) {
- case 0:
- case GIT_SHA1_FORMAT_ID:
- return GIT_SHA1_RAWSZ;
- case GIT_SHA256_FORMAT_ID:
- return GIT_SHA256_RAWSZ;
- }
- abort();
-}
diff --git a/reftable/reader.c b/reftable/reader.c
index 6494ce2e32..8d37253922 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -554,32 +554,37 @@ static void iterator_from_table_iter(struct reftable_iterator *it,
it->ops = &table_iter_vtable;
}
-void reader_init_iter(struct reftable_reader *r,
- struct reftable_iterator *it,
- uint8_t typ)
+int reader_init_iter(struct reftable_reader *r,
+ struct reftable_iterator *it,
+ uint8_t typ)
{
struct reftable_reader_offsets *offs = reader_offsets_for(r, typ);
if (offs->is_present) {
struct table_iter *ti;
REFTABLE_ALLOC_ARRAY(ti, 1);
+ if (!ti)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
table_iter_init(ti, r);
iterator_from_table_iter(it, ti);
} else {
iterator_set_empty(it);
}
+
+ return 0;
}
-void reftable_reader_init_ref_iterator(struct reftable_reader *r,
- struct reftable_iterator *it)
+int reftable_reader_init_ref_iterator(struct reftable_reader *r,
+ struct reftable_iterator *it)
{
- reader_init_iter(r, it, BLOCK_TYPE_REF);
+ return reader_init_iter(r, it, BLOCK_TYPE_REF);
}
-void reftable_reader_init_log_iterator(struct reftable_reader *r,
- struct reftable_iterator *it)
+int reftable_reader_init_log_iterator(struct reftable_reader *r,
+ struct reftable_iterator *it)
{
- reader_init_iter(r, it, BLOCK_TYPE_LOG);
+ return reader_init_iter(r, it, BLOCK_TYPE_LOG);
}
int reftable_reader_new(struct reftable_reader **out,
@@ -593,6 +598,10 @@ int reftable_reader_new(struct reftable_reader **out,
int err;
REFTABLE_CALLOC_ARRAY(r, 1);
+ if (!r) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
/*
* We need one extra byte to read the type of first block. We also
@@ -622,7 +631,11 @@ int reftable_reader_new(struct reftable_reader **out,
r->size = file_size - footer_size(r->version);
r->source = *source;
- r->name = xstrdup(name);
+ r->name = reftable_strdup(name);
+ if (!r->name) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
r->hash_id = 0;
r->refcount = 1;
@@ -665,7 +678,7 @@ void reftable_reader_decref(struct reftable_reader *r)
if (--r->refcount)
return;
block_source_close(&r->source);
- FREE_AND_NULL(r->name);
+ REFTABLE_FREE_AND_NULL(r->name);
reftable_free(r);
}
@@ -689,7 +702,10 @@ static int reftable_reader_refs_for_indexed(struct reftable_reader *r,
struct indexed_table_ref_iter *itr = NULL;
/* Look through the reverse index. */
- reader_init_iter(r, &oit, BLOCK_TYPE_OBJ);
+ err = reader_init_iter(r, &oit, BLOCK_TYPE_OBJ);
+ if (err < 0)
+ goto done;
+
err = iterator_seek(&oit, &want);
if (err != 0)
goto done;
@@ -707,7 +723,7 @@ static int reftable_reader_refs_for_indexed(struct reftable_reader *r,
goto done;
}
- err = new_indexed_table_ref_iter(&itr, r, oid, hash_size(r->hash_id),
+ err = indexed_table_ref_iter_new(&itr, r, oid, hash_size(r->hash_id),
got.u.obj.offsets,
got.u.obj.offset_len);
if (err < 0)
@@ -732,21 +748,37 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r,
int err;
REFTABLE_ALLOC_ARRAY(ti, 1);
+ if (!ti) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
+
table_iter_init(ti, r);
err = table_iter_seek_start(ti, BLOCK_TYPE_REF, 0);
- if (err < 0) {
- reftable_free(ti);
- return err;
- }
+ if (err < 0)
+ goto out;
- filter = reftable_malloc(sizeof(struct filtering_ref_iterator));
+ filter = reftable_malloc(sizeof(*filter));
+ if (!filter) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
*filter = empty;
strbuf_add(&filter->oid, oid, oid_len);
iterator_from_table_iter(&filter->it, ti);
iterator_from_filtering_ref_iterator(it, filter);
- return 0;
+
+ err = 0;
+
+out:
+ if (err < 0) {
+ if (ti)
+ table_iter_close(ti);
+ reftable_free(ti);
+ }
+ return err;
}
int reftable_reader_refs_for(struct reftable_reader *r,
diff --git a/reftable/reader.h b/reftable/reader.h
index 91377b9ce5..010fbfe851 100644
--- a/reftable/reader.h
+++ b/reftable/reader.h
@@ -56,9 +56,9 @@ struct reftable_reader {
const char *reader_name(struct reftable_reader *r);
-void reader_init_iter(struct reftable_reader *r,
- struct reftable_iterator *it,
- uint8_t typ);
+int reader_init_iter(struct reftable_reader *r,
+ struct reftable_iterator *it,
+ uint8_t typ);
/* initialize a block reader to read from `r` */
int reader_init_block_reader(struct reftable_reader *r, struct block_reader *br,
diff --git a/reftable/record.c b/reftable/record.c
index 6b5a075b92..30d563e16d 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -215,13 +215,14 @@ static void reftable_ref_record_key(const void *r, struct strbuf *dest)
strbuf_addstr(dest, rec->refname);
}
-static void reftable_ref_record_copy_from(void *rec, const void *src_rec,
- int hash_size)
+static int reftable_ref_record_copy_from(void *rec, const void *src_rec,
+ int hash_size)
{
struct reftable_ref_record *ref = rec;
const struct reftable_ref_record *src = src_rec;
char *refname = NULL;
size_t refname_cap = 0;
+ int err;
assert(hash_size > 0);
@@ -236,6 +237,11 @@ static void reftable_ref_record_copy_from(void *rec, const void *src_rec,
REFTABLE_ALLOC_GROW(ref->refname, refname_len + 1,
ref->refname_cap);
+ if (!ref->refname) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
+
memcpy(ref->refname, src->refname, refname_len);
ref->refname[refname_len] = 0;
}
@@ -254,9 +260,17 @@ static void reftable_ref_record_copy_from(void *rec, const void *src_rec,
src->value.val2.target_value, hash_size);
break;
case REFTABLE_REF_SYMREF:
- ref->value.symref = xstrdup(src->value.symref);
+ ref->value.symref = reftable_strdup(src->value.symref);
+ if (!ref->value.symref) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
break;
}
+
+ err = 0;
+out:
+ return err;
}
static void reftable_ref_record_release_void(void *rec)
@@ -345,7 +359,7 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
uint64_t update_index = 0;
const char *refname = NULL;
size_t refname_cap = 0;
- int n;
+ int n, err;
assert(hash_size > 0);
@@ -361,6 +375,10 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
SWAP(r->refname_cap, refname_cap);
REFTABLE_ALLOC_GROW(r->refname, key.len + 1, r->refname_cap);
+ if (!r->refname) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
memcpy(r->refname, key.buf, key.len);
r->refname[key.len] = 0;
@@ -369,7 +387,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
switch (val_type) {
case REFTABLE_REF_VAL1:
if (in.len < hash_size) {
- return -1;
+ err = REFTABLE_FORMAT_ERROR;
+ goto done;
}
memcpy(r->value.val1, in.buf, hash_size);
@@ -378,7 +397,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
case REFTABLE_REF_VAL2:
if (in.len < 2 * hash_size) {
- return -1;
+ err = REFTABLE_FORMAT_ERROR;
+ goto done;
}
memcpy(r->value.val2.value, in.buf, hash_size);
@@ -391,7 +411,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
case REFTABLE_REF_SYMREF: {
int n = decode_string(scratch, in);
if (n < 0) {
- return -1;
+ err = REFTABLE_FORMAT_ERROR;
+ goto done;
}
string_view_consume(&in, n);
r->value.symref = strbuf_detach(scratch, NULL);
@@ -405,6 +426,9 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
}
return start.len - in.len;
+
+done:
+ return err;
}
static int reftable_ref_record_is_deletion_void(const void *p)
@@ -452,28 +476,33 @@ static void reftable_obj_record_key(const void *r, struct strbuf *dest)
static void reftable_obj_record_release(void *rec)
{
struct reftable_obj_record *obj = rec;
- FREE_AND_NULL(obj->hash_prefix);
- FREE_AND_NULL(obj->offsets);
+ REFTABLE_FREE_AND_NULL(obj->hash_prefix);
+ REFTABLE_FREE_AND_NULL(obj->offsets);
memset(obj, 0, sizeof(struct reftable_obj_record));
}
-static void reftable_obj_record_copy_from(void *rec, const void *src_rec,
- int hash_size UNUSED)
+static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
+ int hash_size UNUSED)
{
struct reftable_obj_record *obj = rec;
- const struct reftable_obj_record *src =
- (const struct reftable_obj_record *)src_rec;
+ const struct reftable_obj_record *src = src_rec;
reftable_obj_record_release(obj);
REFTABLE_ALLOC_ARRAY(obj->hash_prefix, src->hash_prefix_len);
+ if (!obj->hash_prefix)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
obj->hash_prefix_len = src->hash_prefix_len;
if (src->hash_prefix_len)
memcpy(obj->hash_prefix, src->hash_prefix, obj->hash_prefix_len);
REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len);
+ if (!obj->offsets)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
obj->offset_len = src->offset_len;
COPY_ARRAY(obj->offsets, src->offsets, src->offset_len);
+
+ return 0;
}
static uint8_t reftable_obj_record_val_type(const void *rec)
@@ -533,6 +562,8 @@ static int reftable_obj_record_decode(void *rec, struct strbuf key,
reftable_obj_record_release(r);
REFTABLE_ALLOC_ARRAY(r->hash_prefix, key.len);
+ if (!r->hash_prefix)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
memcpy(r->hash_prefix, key.buf, key.len);
r->hash_prefix_len = key.len;
@@ -551,6 +582,8 @@ static int reftable_obj_record_decode(void *rec, struct strbuf key,
return start.len - in.len;
REFTABLE_ALLOC_ARRAY(r->offsets, count);
+ if (!r->offsets)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
r->offset_len = count;
n = get_var_int(&r->offsets[0], &in);
@@ -646,33 +679,44 @@ static void reftable_log_record_key(const void *r, struct strbuf *dest)
strbuf_add(dest, i64, sizeof(i64));
}
-static void reftable_log_record_copy_from(void *rec, const void *src_rec,
- int hash_size)
+static int reftable_log_record_copy_from(void *rec, const void *src_rec,
+ int hash_size)
{
struct reftable_log_record *dst = rec;
const struct reftable_log_record *src =
(const struct reftable_log_record *)src_rec;
+ int ret;
reftable_log_record_release(dst);
*dst = *src;
+
if (dst->refname) {
- dst->refname = xstrdup(dst->refname);
+ dst->refname = reftable_strdup(dst->refname);
+ if (!dst->refname) {
+ ret = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
}
+
switch (dst->value_type) {
case REFTABLE_LOG_DELETION:
break;
case REFTABLE_LOG_UPDATE:
- if (dst->value.update.email) {
+ if (dst->value.update.email)
dst->value.update.email =
- xstrdup(dst->value.update.email);
- }
- if (dst->value.update.name) {
+ reftable_strdup(dst->value.update.email);
+ if (dst->value.update.name)
dst->value.update.name =
- xstrdup(dst->value.update.name);
- }
- if (dst->value.update.message) {
+ reftable_strdup(dst->value.update.name);
+ if (dst->value.update.message)
dst->value.update.message =
- xstrdup(dst->value.update.message);
+ reftable_strdup(dst->value.update.message);
+
+ if (!dst->value.update.email ||
+ !dst->value.update.name ||
+ !dst->value.update.message) {
+ ret = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
}
memcpy(dst->value.update.new_hash,
@@ -681,6 +725,10 @@ static void reftable_log_record_copy_from(void *rec, const void *src_rec,
src->value.update.old_hash, hash_size);
break;
}
+
+ ret = 0;
+out:
+ return ret;
}
static void reftable_log_record_release_void(void *rec)
@@ -767,12 +815,17 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
struct reftable_log_record *r = rec;
uint64_t max = 0;
uint64_t ts = 0;
- int n;
+ int err, n;
if (key.len <= 9 || key.buf[key.len - 9] != 0)
return REFTABLE_FORMAT_ERROR;
REFTABLE_ALLOC_GROW(r->refname, key.len - 8, r->refname_cap);
+ if (!r->refname) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+
memcpy(r->refname, key.buf, key.len - 8);
ts = get_be64(key.buf + key.len - 8);
@@ -781,10 +834,10 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
if (val_type != r->value_type) {
switch (r->value_type) {
case REFTABLE_LOG_UPDATE:
- FREE_AND_NULL(r->value.update.message);
+ REFTABLE_FREE_AND_NULL(r->value.update.message);
r->value.update.message_cap = 0;
- FREE_AND_NULL(r->value.update.email);
- FREE_AND_NULL(r->value.update.name);
+ REFTABLE_FREE_AND_NULL(r->value.update.email);
+ REFTABLE_FREE_AND_NULL(r->value.update.name);
break;
case REFTABLE_LOG_DELETION:
break;
@@ -795,8 +848,10 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
if (val_type == REFTABLE_LOG_DELETION)
return 0;
- if (in.len < 2 * hash_size)
- return REFTABLE_FORMAT_ERROR;
+ if (in.len < 2 * hash_size) {
+ err = REFTABLE_FORMAT_ERROR;
+ goto done;
+ }
memcpy(r->value.update.old_hash, in.buf, hash_size);
memcpy(r->value.update.new_hash, in.buf + hash_size, hash_size);
@@ -804,8 +859,10 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
string_view_consume(&in, 2 * hash_size);
n = decode_string(scratch, in);
- if (n < 0)
+ if (n < 0) {
+ err = REFTABLE_FORMAT_ERROR;
goto done;
+ }
string_view_consume(&in, n);
/*
@@ -816,52 +873,75 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
*/
if (!r->value.update.name ||
strcmp(r->value.update.name, scratch->buf)) {
- r->value.update.name =
- reftable_realloc(r->value.update.name, scratch->len + 1);
+ char *name = reftable_realloc(r->value.update.name, scratch->len + 1);
+ if (!name) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+
+ r->value.update.name = name;
memcpy(r->value.update.name, scratch->buf, scratch->len);
r->value.update.name[scratch->len] = 0;
}
n = decode_string(scratch, in);
- if (n < 0)
+ if (n < 0) {
+ err = REFTABLE_FORMAT_ERROR;
goto done;
+ }
string_view_consume(&in, n);
/* Same as above, but for the reflog email. */
if (!r->value.update.email ||
strcmp(r->value.update.email, scratch->buf)) {
- r->value.update.email =
- reftable_realloc(r->value.update.email, scratch->len + 1);
+ char *email = reftable_realloc(r->value.update.email, scratch->len + 1);
+ if (!email) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+
+ r->value.update.email = email;
memcpy(r->value.update.email, scratch->buf, scratch->len);
r->value.update.email[scratch->len] = 0;
}
ts = 0;
n = get_var_int(&ts, &in);
- if (n < 0)
+ if (n < 0) {
+ err = REFTABLE_FORMAT_ERROR;
goto done;
+ }
string_view_consume(&in, n);
r->value.update.time = ts;
- if (in.len < 2)
+ if (in.len < 2) {
+ err = REFTABLE_FORMAT_ERROR;
goto done;
+ }
r->value.update.tz_offset = get_be16(in.buf);
string_view_consume(&in, 2);
n = decode_string(scratch, in);
- if (n < 0)
+ if (n < 0) {
+ err = REFTABLE_FORMAT_ERROR;
goto done;
+ }
string_view_consume(&in, n);
REFTABLE_ALLOC_GROW(r->value.update.message, scratch->len + 1,
r->value.update.message_cap);
+ if (!r->value.update.message) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+
memcpy(r->value.update.message, scratch->buf, scratch->len);
r->value.update.message[scratch->len] = 0;
return start.len - in.len;
done:
- return REFTABLE_FORMAT_ERROR;
+ return err;
}
static int null_streq(const char *a, const char *b)
@@ -954,8 +1034,8 @@ static void reftable_index_record_key(const void *r, struct strbuf *dest)
strbuf_addbuf(dest, &rec->last_key);
}
-static void reftable_index_record_copy_from(void *rec, const void *src_rec,
- int hash_size UNUSED)
+static int reftable_index_record_copy_from(void *rec, const void *src_rec,
+ int hash_size UNUSED)
{
struct reftable_index_record *dst = rec;
const struct reftable_index_record *src = src_rec;
@@ -963,6 +1043,8 @@ static void reftable_index_record_copy_from(void *rec, const void *src_rec,
strbuf_reset(&dst->last_key);
strbuf_addbuf(&dst->last_key, &src->last_key);
dst->offset = src->offset;
+
+ return 0;
}
static void reftable_index_record_release(void *rec)
@@ -1054,14 +1136,14 @@ int reftable_record_encode(struct reftable_record *rec, struct string_view dest,
dest, hash_size);
}
-void reftable_record_copy_from(struct reftable_record *rec,
+int reftable_record_copy_from(struct reftable_record *rec,
struct reftable_record *src, int hash_size)
{
assert(src->type == rec->type);
- reftable_record_vtable(rec)->copy_from(reftable_record_data(rec),
- reftable_record_data(src),
- hash_size);
+ return reftable_record_vtable(rec)->copy_from(reftable_record_data(rec),
+ reftable_record_data(src),
+ hash_size);
}
uint8_t reftable_record_val_type(struct reftable_record *rec)
diff --git a/reftable/record.h b/reftable/record.h
index 5003bacdb0..0f53ba5443 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -44,7 +44,7 @@ struct reftable_record_vtable {
/* The record type of ('r' for ref). */
uint8_t type;
- void (*copy_from)(void *dest, const void *src, int hash_size);
+ int (*copy_from)(void *dest, const void *src, int hash_size);
/* a value of [0..7], indicating record subvariants (eg. ref vs. symref
* vs ref deletion) */
@@ -137,8 +137,8 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ);
int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size);
void reftable_record_key(struct reftable_record *rec, struct strbuf *dest);
-void reftable_record_copy_from(struct reftable_record *rec,
- struct reftable_record *src, int hash_size);
+int reftable_record_copy_from(struct reftable_record *rec,
+ struct reftable_record *src, int hash_size);
uint8_t reftable_record_val_type(struct reftable_record *rec);
int reftable_record_encode(struct reftable_record *rec, struct string_view dest,
int hash_size);
diff --git a/reftable/reftable-basics.h b/reftable/reftable-basics.h
new file mode 100644
index 0000000000..6e8e636b71
--- /dev/null
+++ b/reftable/reftable-basics.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://developers.google.com/open-source/licenses/bsd
+*/
+
+#ifndef REFTABLE_BASICS_H
+#define REFTABLE_BASICS_H
+
+#include <stddef.h>
+
+/* Overrides the functions to use for memory management. */
+void reftable_set_alloc(void *(*malloc)(size_t),
+ void *(*realloc)(void *, size_t), void (*free)(void *));
+
+#endif
diff --git a/reftable/reftable-error.h b/reftable/reftable-error.h
index 6368cd9ed9..f404826562 100644
--- a/reftable/reftable-error.h
+++ b/reftable/reftable-error.h
@@ -57,6 +57,9 @@ enum reftable_error {
/* Trying to write out-of-date data. */
REFTABLE_OUTDATED_ERROR = -12,
+
+ /* An allocation has failed due to an out-of-memory situation. */
+ REFTABLE_OUT_OF_MEMORY_ERROR = -13,
};
/* convert the numeric error code to a string. The string should not be
diff --git a/reftable/reftable-malloc.h b/reftable/reftable-malloc.h
deleted file mode 100644
index 5f2185f1f3..0000000000
--- a/reftable/reftable-malloc.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-Copyright 2020 Google LLC
-
-Use of this source code is governed by a BSD-style
-license that can be found in the LICENSE file or at
-https://developers.google.com/open-source/licenses/bsd
-*/
-
-#ifndef REFTABLE_H
-#define REFTABLE_H
-
-#include <stddef.h>
-
-/* Overrides the functions to use for memory management. */
-void reftable_set_alloc(void *(*malloc)(size_t),
- void *(*realloc)(void *, size_t), void (*free)(void *));
-
-#endif
diff --git a/reftable/reftable-merged.h b/reftable/reftable-merged.h
index 16d19f8df2..a970d5dd89 100644
--- a/reftable/reftable-merged.h
+++ b/reftable/reftable-merged.h
@@ -37,12 +37,12 @@ int reftable_merged_table_new(struct reftable_merged_table **dest,
uint32_t hash_id);
/* Initialize a merged table iterator for reading refs. */
-void reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt,
- struct reftable_iterator *it);
+int reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt,
+ struct reftable_iterator *it);
/* Initialize a merged table iterator for reading logs. */
-void reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt,
- struct reftable_iterator *it);
+int reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt,
+ struct reftable_iterator *it);
/* returns the max update_index covered by this merged table. */
uint64_t
diff --git a/reftable/reftable-reader.h b/reftable/reftable-reader.h
index a600452b56..6a2d0b693f 100644
--- a/reftable/reftable-reader.h
+++ b/reftable/reftable-reader.h
@@ -46,12 +46,12 @@ void reftable_reader_incref(struct reftable_reader *reader);
void reftable_reader_decref(struct reftable_reader *reader);
/* Initialize a reftable iterator for reading refs. */
-void reftable_reader_init_ref_iterator(struct reftable_reader *r,
- struct reftable_iterator *it);
+int reftable_reader_init_ref_iterator(struct reftable_reader *r,
+ struct reftable_iterator *it);
/* Initialize a reftable iterator for reading logs. */
-void reftable_reader_init_log_iterator(struct reftable_reader *r,
- struct reftable_iterator *it);
+int reftable_reader_init_log_iterator(struct reftable_reader *r,
+ struct reftable_iterator *it);
/* returns the hash ID used in this table. */
uint32_t reftable_reader_hash_id(struct reftable_reader *r);
diff --git a/reftable/reftable-stack.h b/reftable/reftable-stack.h
index 6370fe45dd..54787f2ef5 100644
--- a/reftable/reftable-stack.h
+++ b/reftable/reftable-stack.h
@@ -82,16 +82,16 @@ struct reftable_iterator;
* be used to iterate through refs. The iterator is valid until the next reload
* or write.
*/
-void reftable_stack_init_ref_iterator(struct reftable_stack *st,
- struct reftable_iterator *it);
+int reftable_stack_init_ref_iterator(struct reftable_stack *st,
+ struct reftable_iterator *it);
/*
* Initialize an iterator for the merged tables contained in the stack that can
* be used to iterate through logs. The iterator is valid until the next reload
* or write.
*/
-void reftable_stack_init_log_iterator(struct reftable_stack *st,
- struct reftable_iterator *it);
+int reftable_stack_init_log_iterator(struct reftable_stack *st,
+ struct reftable_iterator *it);
/* returns the merged_table for seeking. This table is valid until the
* next write or reload, and should not be closed or deleted.
diff --git a/reftable/reftable-writer.h b/reftable/reftable-writer.h
index f5e25cfda1..e4fc953788 100644
--- a/reftable/reftable-writer.h
+++ b/reftable/reftable-writer.h
@@ -101,11 +101,13 @@ struct reftable_stats {
int object_id_len;
};
-/* reftable_new_writer creates a new writer */
-struct reftable_writer *
-reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t),
- int (*flush_func)(void *),
- void *writer_arg, const struct reftable_write_options *opts);
+struct reftable_writer;
+
+/* Create a new writer. */
+int reftable_writer_new(struct reftable_writer **out,
+ ssize_t (*writer_func)(void *, const void *, size_t),
+ int (*flush_func)(void *),
+ void *writer_arg, const struct reftable_write_options *opts);
/* Set the range of update indices for the records we will add. When writing a
table into a stack, the min should be at least
diff --git a/reftable/stack.c b/reftable/stack.c
index 84cf37a2ad..7e617c2591 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -56,10 +56,16 @@ static int reftable_fd_flush(void *arg)
int reftable_new_stack(struct reftable_stack **dest, const char *dir,
const struct reftable_write_options *_opts)
{
- struct reftable_stack *p = reftable_calloc(1, sizeof(*p));
struct strbuf list_file_name = STRBUF_INIT;
- struct reftable_write_options opts = {0};
- int err = 0;
+ struct reftable_write_options opts = { 0 };
+ struct reftable_stack *p;
+ int err;
+
+ p = reftable_calloc(1, sizeof(*p));
+ if (!p) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
if (_opts)
opts = *_opts;
@@ -74,15 +80,23 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
p->list_file = strbuf_detach(&list_file_name, NULL);
p->list_fd = -1;
- p->reftable_dir = xstrdup(dir);
p->opts = opts;
+ p->reftable_dir = reftable_strdup(dir);
+ if (!p->reftable_dir) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
err = reftable_stack_reload_maybe_reuse(p, 1);
- if (err < 0) {
+ if (err < 0)
+ goto out;
+
+ *dest = p;
+ err = 0;
+
+out:
+ if (err < 0)
reftable_stack_destroy(p);
- } else {
- *dest = p;
- }
return err;
}
@@ -102,13 +116,22 @@ static int fd_read_lines(int fd, char ***namesp)
}
REFTABLE_ALLOC_ARRAY(buf, size + 1);
+ if (!buf) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+
if (read_in_full(fd, buf, size) != size) {
err = REFTABLE_IO_ERROR;
goto done;
}
buf[size] = 0;
- parse_names(buf, size, namesp);
+ *namesp = parse_names(buf, size);
+ if (!*namesp) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
done:
reftable_free(buf);
@@ -122,6 +145,8 @@ int read_lines(const char *filename, char ***namesp)
if (fd < 0) {
if (errno == ENOENT) {
REFTABLE_CALLOC_ARRAY(*namesp, 1);
+ if (!*namesp)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
return 0;
}
@@ -132,18 +157,18 @@ int read_lines(const char *filename, char ***namesp)
return err;
}
-void reftable_stack_init_ref_iterator(struct reftable_stack *st,
+int reftable_stack_init_ref_iterator(struct reftable_stack *st,
struct reftable_iterator *it)
{
- merged_table_init_iter(reftable_stack_merged_table(st),
- it, BLOCK_TYPE_REF);
+ return merged_table_init_iter(reftable_stack_merged_table(st),
+ it, BLOCK_TYPE_REF);
}
-void reftable_stack_init_log_iterator(struct reftable_stack *st,
- struct reftable_iterator *it)
+int reftable_stack_init_log_iterator(struct reftable_stack *st,
+ struct reftable_iterator *it)
{
- merged_table_init_iter(reftable_stack_merged_table(st),
- it, BLOCK_TYPE_LOG);
+ return merged_table_init_iter(reftable_stack_merged_table(st),
+ it, BLOCK_TYPE_LOG);
}
struct reftable_merged_table *
@@ -167,6 +192,10 @@ void reftable_stack_destroy(struct reftable_stack *st)
{
char **names = NULL;
int err = 0;
+
+ if (!st)
+ return;
+
if (st->merged) {
reftable_merged_table_free(st->merged);
st->merged = NULL;
@@ -174,7 +203,7 @@ void reftable_stack_destroy(struct reftable_stack *st)
err = read_lines(st->list_file, &names);
if (err < 0) {
- FREE_AND_NULL(names);
+ REFTABLE_FREE_AND_NULL(names);
}
if (st->readers) {
@@ -195,7 +224,7 @@ void reftable_stack_destroy(struct reftable_stack *st)
}
strbuf_release(&filename);
st->readers_len = 0;
- FREE_AND_NULL(st->readers);
+ REFTABLE_FREE_AND_NULL(st->readers);
}
if (st->list_fd >= 0) {
@@ -203,20 +232,20 @@ void reftable_stack_destroy(struct reftable_stack *st)
st->list_fd = -1;
}
- FREE_AND_NULL(st->list_file);
- FREE_AND_NULL(st->reftable_dir);
+ REFTABLE_FREE_AND_NULL(st->list_file);
+ REFTABLE_FREE_AND_NULL(st->reftable_dir);
reftable_free(st);
free_names(names);
}
static struct reftable_reader **stack_copy_readers(struct reftable_stack *st,
- int cur_len)
+ size_t cur_len)
{
struct reftable_reader **cur = reftable_calloc(cur_len, sizeof(*cur));
- int i = 0;
- for (i = 0; i < cur_len; i++) {
+ if (!cur)
+ return NULL;
+ for (size_t i = 0; i < cur_len; i++)
cur[i] = st->readers[i];
- }
return cur;
}
@@ -225,18 +254,30 @@ static int reftable_stack_reload_once(struct reftable_stack *st,
int reuse_open)
{
size_t cur_len = !st->merged ? 0 : st->merged->readers_len;
- struct reftable_reader **cur = stack_copy_readers(st, cur_len);
+ struct reftable_reader **cur;
struct reftable_reader **reused = NULL;
- size_t reused_len = 0, reused_alloc = 0;
- size_t names_len = names_length(names);
- struct reftable_reader **new_readers =
- reftable_calloc(names_len, sizeof(*new_readers));
+ struct reftable_reader **new_readers;
+ size_t reused_len = 0, reused_alloc = 0, names_len;
size_t new_readers_len = 0;
struct reftable_merged_table *new_merged = NULL;
struct strbuf table_path = STRBUF_INIT;
int err = 0;
size_t i;
+ cur = stack_copy_readers(st, cur_len);
+ if (!cur) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+
+ names_len = names_length(names);
+
+ new_readers = reftable_calloc(names_len, sizeof(*new_readers));
+ if (!new_readers) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+
while (*names) {
struct reftable_reader *rd = NULL;
const char *name = *names++;
@@ -257,6 +298,10 @@ static int reftable_stack_reload_once(struct reftable_stack *st,
* do by bumping their refcount.
*/
REFTABLE_ALLOC_GROW(reused, reused_len + 1, reused_alloc);
+ if (!reused) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
reused[reused_len++] = rd;
reftable_reader_incref(rd);
break;
@@ -382,6 +427,10 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
}
REFTABLE_CALLOC_ARRAY(names, 1);
+ if (!names) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto out;
+ }
} else {
err = fd_read_lines(fd, &names);
if (err < 0)
@@ -749,7 +798,11 @@ int reftable_stack_new_addition(struct reftable_addition **dest,
{
int err = 0;
struct reftable_addition empty = REFTABLE_ADDITION_INIT;
+
REFTABLE_CALLOC_ARRAY(*dest, 1);
+ if (!*dest)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
**dest = empty;
err = reftable_stack_init_addition(*dest, st, flags);
if (err) {
@@ -812,8 +865,11 @@ int reftable_addition_add(struct reftable_addition *add,
}
tab_fd = get_tempfile_fd(tab_file);
- wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush, &tab_fd,
- &add->stack->opts);
+ err = reftable_writer_new(&wr, reftable_fd_write, reftable_fd_flush,
+ &tab_fd, &add->stack->opts);
+ if (err < 0)
+ goto done;
+
err = write_table(wr, arg);
if (err < 0)
goto done;
@@ -853,7 +909,12 @@ int reftable_addition_add(struct reftable_addition *add,
REFTABLE_ALLOC_GROW(add->new_tables, add->new_tables_len + 1,
add->new_tables_cap);
+ if (!add->new_tables) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
add->new_tables[add->new_tables_len++] = strbuf_detach(&next_name, NULL);
+
done:
delete_tempfile(&tab_file);
strbuf_release(&temp_tab_file_name);
@@ -902,8 +963,11 @@ static int stack_compact_locked(struct reftable_stack *st,
goto done;
}
- wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush,
- &tab_fd, &st->opts);
+ err = reftable_writer_new(&wr, reftable_fd_write, reftable_fd_flush,
+ &tab_fd, &st->opts);
+ if (err < 0)
+ goto done;
+
err = stack_write_compact(st, wr, first, last, config);
if (err < 0)
goto done;
@@ -950,7 +1014,10 @@ static int stack_write_compact(struct reftable_stack *st,
if (err < 0)
goto done;
- merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ if (err < 0)
+ goto done;
+
err = reftable_iterator_seek_ref(&it, "");
if (err < 0)
goto done;
@@ -975,7 +1042,10 @@ static int stack_write_compact(struct reftable_stack *st,
}
reftable_iterator_destroy(&it);
- merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ if (err < 0)
+ goto done;
+
err = reftable_iterator_seek_log(&it, "");
if (err < 0)
goto done;
@@ -1091,6 +1161,11 @@ static int stack_compact_range(struct reftable_stack *st,
* from the point of view of the newer process.
*/
REFTABLE_CALLOC_ARRAY(table_locks, last - first + 1);
+ if (!table_locks) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+
for (i = last + 1; i > first; i--) {
stack_filename(&table_name, st, reader_name(st->readers[i - 1]));
@@ -1274,8 +1349,18 @@ static int stack_compact_range(struct reftable_stack *st,
* thus have to allocate `readers_len + 1` many entries.
*/
REFTABLE_CALLOC_ARRAY(names, st->merged->readers_len + 1);
- for (size_t i = 0; i < st->merged->readers_len; i++)
- names[i] = xstrdup(st->readers[i]->name);
+ if (!names) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+
+ for (size_t i = 0; i < st->merged->readers_len; i++) {
+ names[i] = reftable_strdup(st->readers[i]->name);
+ if (!names[i]) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
+ }
first_to_replace = first;
last_to_replace = last;
}
@@ -1348,7 +1433,7 @@ static int stack_compact_range(struct reftable_stack *st,
struct lock_file *table_lock = &table_locks[i];
char *table_path = get_locked_file_path(table_lock);
unlink(table_path);
- free(table_path);
+ reftable_free(table_path);
}
done:
@@ -1465,6 +1550,8 @@ static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st)
uint64_t *sizes;
REFTABLE_CALLOC_ARRAY(sizes, st->merged->readers_len);
+ if (!sizes)
+ return NULL;
for (size_t i = 0; i < st->merged->readers_len; i++)
sizes[i] = st->readers[i]->size - overhead;
@@ -1474,11 +1561,17 @@ static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st)
int reftable_stack_auto_compact(struct reftable_stack *st)
{
- uint64_t *sizes = stack_table_sizes_for_compaction(st);
- struct segment seg =
- suggest_compaction_segment(sizes, st->merged->readers_len,
- st->opts.auto_compaction_factor);
+ struct segment seg;
+ uint64_t *sizes;
+
+ sizes = stack_table_sizes_for_compaction(st);
+ if (!sizes)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
+ seg = suggest_compaction_segment(sizes, st->merged->readers_len,
+ st->opts.auto_compaction_factor);
reftable_free(sizes);
+
if (segment_size(&seg) > 0)
return stack_compact_range(st, seg.start, seg.end - 1,
NULL, STACK_COMPACT_RANGE_BEST_EFFORT);
@@ -1498,7 +1591,10 @@ int reftable_stack_read_ref(struct reftable_stack *st, const char *refname,
struct reftable_iterator it = { 0 };
int ret;
- reftable_merged_table_init_ref_iterator(st->merged, &it);
+ ret = reftable_merged_table_init_ref_iterator(st->merged, &it);
+ if (ret)
+ goto out;
+
ret = reftable_iterator_seek_ref(&it, refname);
if (ret)
goto out;
@@ -1525,7 +1621,10 @@ int reftable_stack_read_log(struct reftable_stack *st, const char *refname,
struct reftable_iterator it = {0};
int err;
- reftable_stack_init_log_iterator(st, &it);
+ err = reftable_stack_init_log_iterator(st, &it);
+ if (err)
+ goto done;
+
err = reftable_iterator_seek_log(&it, refname);
if (err)
goto done;
diff --git a/reftable/tree.c b/reftable/tree.c
index 5ffb2e0d69..f4dbe72090 100644
--- a/reftable/tree.c
+++ b/reftable/tree.c
@@ -11,28 +11,44 @@ https://developers.google.com/open-source/licenses/bsd
#include "basics.h"
-struct tree_node *tree_search(void *key, struct tree_node **rootp,
- int (*compare)(const void *, const void *),
- int insert)
+struct tree_node *tree_search(struct tree_node *tree,
+ void *key,
+ int (*compare)(const void *, const void *))
{
int res;
+ if (!tree)
+ return NULL;
+ res = compare(key, tree->key);
+ if (res < 0)
+ return tree_search(tree->left, key, compare);
+ else if (res > 0)
+ return tree_search(tree->right, key, compare);
+ return tree;
+}
+
+struct tree_node *tree_insert(struct tree_node **rootp,
+ void *key,
+ int (*compare)(const void *, const void *))
+{
+ int res;
+
if (!*rootp) {
- if (!insert) {
+ struct tree_node *n;
+
+ REFTABLE_CALLOC_ARRAY(n, 1);
+ if (!n)
return NULL;
- } else {
- struct tree_node *n;
- REFTABLE_CALLOC_ARRAY(n, 1);
- n->key = key;
- *rootp = n;
- return *rootp;
- }
+
+ n->key = key;
+ *rootp = n;
+ return *rootp;
}
res = compare(key, (*rootp)->key);
if (res < 0)
- return tree_search(key, &(*rootp)->left, compare, insert);
+ return tree_insert(&(*rootp)->left, key, compare);
else if (res > 0)
- return tree_search(key, &(*rootp)->right, compare, insert);
+ return tree_insert(&(*rootp)->right, key, compare);
return *rootp;
}
diff --git a/reftable/tree.h b/reftable/tree.h
index fbdd002e23..9604453b6d 100644
--- a/reftable/tree.h
+++ b/reftable/tree.h
@@ -15,12 +15,23 @@ struct tree_node {
struct tree_node *left, *right;
};
-/* looks for `key` in `rootp` using `compare` as comparison function. If insert
- * is set, insert the key if it's not found. Else, return NULL.
+/*
+ * Search the tree for the node matching the given key using `compare` as
+ * comparison function. Returns the node whose key matches or `NULL` in case
+ * the key does not exist in the tree.
+ */
+struct tree_node *tree_search(struct tree_node *tree,
+ void *key,
+ int (*compare)(const void *, const void *));
+
+/*
+ * Insert a node into the tree. Returns the newly inserted node if the key does
+ * not yet exist. Otherwise it returns the preexisting node. Returns `NULL`
+ * when allocating the new node fails.
*/
-struct tree_node *tree_search(void *key, struct tree_node **rootp,
- int (*compare)(const void *, const void *),
- int insert);
+struct tree_node *tree_insert(struct tree_node **rootp,
+ void *key,
+ int (*compare)(const void *, const void *));
/* performs an infix walk of the tree. */
void infix_walk(struct tree_node *t, void (*action)(void *arg, void *key),
diff --git a/reftable/writer.c b/reftable/writer.c
index 9d5e6072bc..b032a47dec 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -49,8 +49,14 @@ static int padded_write(struct reftable_writer *w, uint8_t *data, size_t len,
{
int n = 0;
if (w->pending_padding > 0) {
- uint8_t *zeroed = reftable_calloc(w->pending_padding, sizeof(*zeroed));
- int n = w->write(w->write_arg, zeroed, w->pending_padding);
+ uint8_t *zeroed;
+ int n;
+
+ zeroed = reftable_calloc(w->pending_padding, sizeof(*zeroed));
+ if (!zeroed)
+ return -1;
+
+ n = w->write(w->write_arg, zeroed, w->pending_padding);
if (n < 0)
return n;
@@ -102,28 +108,37 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
return header_size(writer_version(w));
}
-static void writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)
+static int writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)
{
- int block_start = 0;
- if (w->next == 0) {
+ int block_start = 0, ret;
+
+ if (w->next == 0)
block_start = header_size(writer_version(w));
- }
strbuf_reset(&w->last_key);
- block_writer_init(&w->block_writer_data, typ, w->block,
- w->opts.block_size, block_start,
- hash_size(w->opts.hash_id));
+ ret = block_writer_init(&w->block_writer_data, typ, w->block,
+ w->opts.block_size, block_start,
+ hash_size(w->opts.hash_id));
+ if (ret < 0)
+ return ret;
+
w->block_writer = &w->block_writer_data;
w->block_writer->restart_interval = w->opts.restart_interval;
+
+ return 0;
}
-struct reftable_writer *
-reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t),
- int (*flush_func)(void *),
- void *writer_arg, const struct reftable_write_options *_opts)
+int reftable_writer_new(struct reftable_writer **out,
+ ssize_t (*writer_func)(void *, const void *, size_t),
+ int (*flush_func)(void *),
+ void *writer_arg, const struct reftable_write_options *_opts)
{
- struct reftable_writer *wp = reftable_calloc(1, sizeof(*wp));
struct reftable_write_options opts = {0};
+ struct reftable_writer *wp;
+
+ wp = reftable_calloc(1, sizeof(*wp));
+ if (!wp)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
if (_opts)
opts = *_opts;
@@ -134,13 +149,19 @@ reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t),
strbuf_init(&wp->block_writer_data.last_key, 0);
strbuf_init(&wp->last_key, 0);
REFTABLE_CALLOC_ARRAY(wp->block, opts.block_size);
+ if (!wp->block) {
+ reftable_free(wp);
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+ }
wp->write = writer_func;
wp->write_arg = writer_arg;
wp->opts = opts;
wp->flush = flush_func;
writer_reinit_block_writer(wp, BLOCK_TYPE_REF);
- return wp;
+ *out = wp;
+
+ return 0;
}
void reftable_writer_set_limits(struct reftable_writer *w, uint64_t min,
@@ -186,34 +207,40 @@ static int obj_index_tree_node_compare(const void *a, const void *b)
&((const struct obj_index_tree_node *)b)->hash);
}
-static void writer_index_hash(struct reftable_writer *w, struct strbuf *hash)
+static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)
{
uint64_t off = w->next;
-
struct obj_index_tree_node want = { .hash = *hash };
+ struct obj_index_tree_node *key;
+ struct tree_node *node;
- struct tree_node *node = tree_search(&want, &w->obj_index_tree,
- &obj_index_tree_node_compare, 0);
- struct obj_index_tree_node *key = NULL;
+ node = tree_search(w->obj_index_tree, &want, &obj_index_tree_node_compare);
if (!node) {
struct obj_index_tree_node empty = OBJ_INDEX_TREE_NODE_INIT;
- key = reftable_malloc(sizeof(struct obj_index_tree_node));
+
+ key = reftable_malloc(sizeof(*key));
+ if (!key)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
*key = empty;
strbuf_reset(&key->hash);
strbuf_addbuf(&key->hash, hash);
- tree_search((void *)key, &w->obj_index_tree,
- &obj_index_tree_node_compare, 1);
+ tree_insert(&w->obj_index_tree, key,
+ &obj_index_tree_node_compare);
} else {
key = node->key;
}
- if (key->offset_len > 0 && key->offsets[key->offset_len - 1] == off) {
- return;
- }
+ if (key->offset_len > 0 && key->offsets[key->offset_len - 1] == off)
+ return 0;
REFTABLE_ALLOC_GROW(key->offsets, key->offset_len + 1, key->offset_cap);
+ if (!key->offsets)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
key->offsets[key->offset_len++] = off;
+
+ return 0;
}
static int writer_add_record(struct reftable_writer *w,
@@ -230,8 +257,11 @@ static int writer_add_record(struct reftable_writer *w,
strbuf_reset(&w->last_key);
strbuf_addbuf(&w->last_key, &key);
- if (!w->block_writer)
- writer_reinit_block_writer(w, reftable_record_type(rec));
+ if (!w->block_writer) {
+ err = writer_reinit_block_writer(w, reftable_record_type(rec));
+ if (err < 0)
+ goto done;
+ }
if (block_writer_type(w->block_writer) != reftable_record_type(rec))
BUG("record of type %d added to writer of type %d",
@@ -254,7 +284,9 @@ static int writer_add_record(struct reftable_writer *w,
err = writer_flush_block(w);
if (err < 0)
goto done;
- writer_reinit_block_writer(w, reftable_record_type(rec));
+ err = writer_reinit_block_writer(w, reftable_record_type(rec));
+ if (err < 0)
+ goto done;
/*
* Try to add the record to the writer again. If this still fails then
@@ -284,11 +316,11 @@ int reftable_writer_add_ref(struct reftable_writer *w,
.ref = *ref
},
};
- int err = 0;
+ struct strbuf buf = STRBUF_INIT;
+ int err;
- if (!ref->refname)
- return REFTABLE_API_ERROR;
- if (ref->update_index < w->min_update_index ||
+ if (!ref->refname ||
+ ref->update_index < w->min_update_index ||
ref->update_index > w->max_update_index)
return REFTABLE_API_ERROR;
@@ -296,24 +328,32 @@ int reftable_writer_add_ref(struct reftable_writer *w,
err = writer_add_record(w, &rec);
if (err < 0)
- return err;
+ goto out;
if (!w->opts.skip_index_objects && reftable_ref_record_val1(ref)) {
- struct strbuf h = STRBUF_INIT;
- strbuf_add(&h, (char *)reftable_ref_record_val1(ref),
+ strbuf_add(&buf, (char *)reftable_ref_record_val1(ref),
hash_size(w->opts.hash_id));
- writer_index_hash(w, &h);
- strbuf_release(&h);
+
+ err = writer_index_hash(w, &buf);
+ if (err < 0)
+ goto out;
}
if (!w->opts.skip_index_objects && reftable_ref_record_val2(ref)) {
- struct strbuf h = STRBUF_INIT;
- strbuf_add(&h, reftable_ref_record_val2(ref),
+ strbuf_reset(&buf);
+ strbuf_add(&buf, reftable_ref_record_val2(ref),
hash_size(w->opts.hash_id));
- writer_index_hash(w, &h);
- strbuf_release(&h);
+
+ err = writer_index_hash(w, &buf);
+ if (err < 0)
+ goto out;
}
- return 0;
+
+ err = 0;
+
+out:
+ strbuf_release(&buf);
+ return err;
}
int reftable_writer_add_refs(struct reftable_writer *w,
@@ -436,7 +476,9 @@ static int writer_finish_section(struct reftable_writer *w)
max_level++;
index_start = w->next;
- writer_reinit_block_writer(w, BLOCK_TYPE_INDEX);
+ err = writer_reinit_block_writer(w, BLOCK_TYPE_INDEX);
+ if (err < 0)
+ return err;
idx = w->index;
idx_len = w->index_len;
@@ -530,7 +572,10 @@ static void write_object_record(void *void_arg, void *key)
if (arg->err < 0)
goto done;
- writer_reinit_block_writer(arg->w, BLOCK_TYPE_OBJ);
+ arg->err = writer_reinit_block_writer(arg->w, BLOCK_TYPE_OBJ);
+ if (arg->err < 0)
+ goto done;
+
arg->err = block_writer_add(arg->w->block_writer, &rec);
if (arg->err == 0)
goto done;
@@ -548,7 +593,7 @@ static void object_record_free(void *void_arg UNUSED, void *key)
{
struct obj_index_tree_node *entry = key;
- FREE_AND_NULL(entry->offsets);
+ REFTABLE_FREE_AND_NULL(entry->offsets);
strbuf_release(&entry->hash);
reftable_free(entry);
}
@@ -559,16 +604,18 @@ static int writer_dump_object_index(struct reftable_writer *w)
struct common_prefix_arg common = {
.max = 1, /* obj_id_len should be >= 2. */
};
- if (w->obj_index_tree) {
+ int err;
+
+ if (w->obj_index_tree)
infix_walk(w->obj_index_tree, &update_common, &common);
- }
w->stats.object_id_len = common.max + 1;
- writer_reinit_block_writer(w, BLOCK_TYPE_OBJ);
+ err = writer_reinit_block_writer(w, BLOCK_TYPE_OBJ);
+ if (err < 0)
+ return err;
- if (w->obj_index_tree) {
+ if (w->obj_index_tree)
infix_walk(w->obj_index_tree, &write_object_record, &closure);
- }
if (closure.err < 0)
return closure.err;
@@ -662,7 +709,7 @@ static void writer_clear_index(struct reftable_writer *w)
{
for (size_t i = 0; w->index && i < w->index_len; i++)
strbuf_release(&w->index[i].last_key);
- FREE_AND_NULL(w->index);
+ REFTABLE_FREE_AND_NULL(w->index);
w->index_len = 0;
w->index_cap = 0;
}
@@ -726,6 +773,9 @@ static int writer_flush_nonempty_block(struct reftable_writer *w)
* case we will end up with a multi-level index.
*/
REFTABLE_ALLOC_GROW(w->index, w->index_len + 1, w->index_cap);
+ if (!w->index)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
index_record.offset = w->next;
strbuf_reset(&index_record.last_key);
strbuf_addbuf(&index_record.last_key, &w->block_writer->last_key);
diff --git a/remote.c b/remote.c
index e291e8ff5c..cd2091ac0c 100644
--- a/remote.c
+++ b/remote.c
@@ -868,6 +868,20 @@ struct strvec *push_url_of_remote(struct remote *remote)
return remote->pushurl.nr ? &remote->pushurl : &remote->url;
}
+void ref_push_report_free(struct ref_push_report *report)
+{
+ while (report) {
+ struct ref_push_report *next = report->next;
+
+ free(report->ref_name);
+ free(report->old_oid);
+ free(report->new_oid);
+ free(report);
+
+ report = next;
+ }
+}
+
static int match_name_with_pattern(const char *key, const char *name,
const char *value, char **result)
{
@@ -1122,6 +1136,7 @@ void free_one_ref(struct ref *ref)
if (!ref)
return;
free_one_ref(ref->peer_ref);
+ ref_push_report_free(ref->report);
free(ref->remote_status);
free(ref->tracking_ref);
free(ref->symref);
diff --git a/remote.h b/remote.h
index ad4513f639..c5e79eb40e 100644
--- a/remote.h
+++ b/remote.h
@@ -126,13 +126,15 @@ int remote_has_url(struct remote *remote, const char *url);
struct strvec *push_url_of_remote(struct remote *remote);
struct ref_push_report {
- const char *ref_name;
+ char *ref_name;
struct object_id *old_oid;
struct object_id *new_oid;
unsigned int forced_update:1;
struct ref_push_report *next;
};
+void ref_push_report_free(struct ref_push_report *);
+
struct ref {
struct ref *next;
struct object_id old_oid;
diff --git a/revision.c b/revision.c
index e79f39e555..f5f5b84f2b 100644
--- a/revision.c
+++ b/revision.c
@@ -3250,6 +3250,7 @@ static int remove_duplicate_parents(struct rev_info *revs, struct commit *commit
struct commit *parent = p->item;
if (parent->object.flags & TMP_MARK) {
*pp = p->next;
+ free(p);
if (ts)
compact_treesame(revs, commit, surviving_parents);
continue;
@@ -4005,6 +4006,7 @@ int rewrite_parents(struct rev_info *revs, struct commit *commit,
break;
case rewrite_one_noparents:
*pp = parent->next;
+ free(parent);
continue;
case rewrite_one_error:
return -1;
@@ -4205,10 +4207,18 @@ static void save_parents(struct rev_info *revs, struct commit *commit)
*pp = EMPTY_PARENT_LIST;
}
+static void free_saved_parent(struct commit_list **parents)
+{
+ if (*parents != EMPTY_PARENT_LIST)
+ free_commit_list(*parents);
+}
+
static void free_saved_parents(struct rev_info *revs)
{
- if (revs->saved_parents_slab)
- clear_saved_parents(revs->saved_parents_slab);
+ if (!revs->saved_parents_slab)
+ return;
+ deep_clear_saved_parents(revs->saved_parents_slab, free_saved_parent);
+ FREE_AND_NULL(revs->saved_parents_slab);
}
struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit)
diff --git a/scalar.c b/scalar.c
index 73b79a5d4c..ac0cb579d3 100644
--- a/scalar.c
+++ b/scalar.c
@@ -732,6 +732,7 @@ static int cmd_reconfigure(int argc, const char **argv)
succeeded = 1;
the_repository = old_repo;
+ repo_clear(&r);
if (toggle_maintenance(1) >= 0)
succeeded = 1;
diff --git a/shell.c b/shell.c
index 2ece8b16e2..76333c8068 100644
--- a/shell.c
+++ b/shell.c
@@ -143,6 +143,7 @@ static void run_shell(void)
}
free(argv);
+ free(split_args);
free(rawargs);
} while (!done);
}
@@ -216,9 +217,8 @@ int cmd_main(int argc, const char **argv)
count = split_cmdline(prog, &user_argv);
if (count >= 0) {
if (is_valid_cmd_name(user_argv[0])) {
- prog = make_cmd(user_argv[0]);
- user_argv[0] = prog;
- execv(user_argv[0], (char *const *) user_argv);
+ char *cmd = make_cmd(user_argv[0]);
+ execv(cmd, (char *const *) user_argv);
}
free(prog);
free(user_argv);
diff --git a/submodule-config.c b/submodule-config.c
index 471637a725..9c8c37b259 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -901,8 +901,9 @@ static void traverse_tree_submodules(struct repository *r,
struct submodule_tree_entry *st_entry;
struct name_entry name_entry;
char *tree_path = NULL;
+ char *tree_buf;
- fill_tree_descriptor(r, &tree, treeish_name);
+ tree_buf = fill_tree_descriptor(r, &tree, treeish_name);
while (tree_entry(&tree, &name_entry)) {
if (prefix)
tree_path =
@@ -930,6 +931,8 @@ static void traverse_tree_submodules(struct repository *r,
&name_entry.oid, out);
free(tree_path);
}
+
+ free(tree_buf);
}
void submodules_of_tree(struct repository *r,
@@ -943,6 +946,16 @@ void submodules_of_tree(struct repository *r,
traverse_tree_submodules(r, treeish_name, NULL, treeish_name, out);
}
+void submodule_entry_list_release(struct submodule_entry_list *list)
+{
+ for (size_t i = 0; i < list->entry_nr; i++) {
+ free(list->entries[i].name_entry);
+ repo_clear(list->entries[i].repo);
+ free(list->entries[i].repo);
+ }
+ free(list->entries);
+}
+
void submodule_free(struct repository *r)
{
if (r->submodule_cache)
diff --git a/submodule-config.h b/submodule-config.h
index b6133af71b..f55d4e3b61 100644
--- a/submodule-config.h
+++ b/submodule-config.h
@@ -136,4 +136,7 @@ struct submodule_entry_list {
void submodules_of_tree(struct repository *r,
const struct object_id *treeish_name,
struct submodule_entry_list *ret);
+
+void submodule_entry_list_release(struct submodule_entry_list *list);
+
#endif /* SUBMODULE_CONFIG_H */
diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c
index 0ead529167..a1af9710c3 100644
--- a/t/helper/test-partial-clone.c
+++ b/t/helper/test-partial-clone.c
@@ -26,6 +26,8 @@ static void object_info(const char *gitdir, const char *oid_hex)
if (oid_object_info_extended(&r, &oid, &oi, 0))
die("could not obtain object info");
printf("%d\n", (int) size);
+
+ repo_clear(&r);
}
int cmd__partial_clone(int argc, const char **argv)
diff --git a/t/helper/test-proc-receive.c b/t/helper/test-proc-receive.c
index 29361c7aab..3703f734f3 100644
--- a/t/helper/test-proc-receive.c
+++ b/t/helper/test-proc-receive.c
@@ -196,5 +196,12 @@ int cmd__proc_receive(int argc, const char **argv)
packet_flush(1);
sigchain_pop(SIGPIPE);
+ while (commands) {
+ struct command *next = commands->next;
+ free(commands);
+ commands = next;
+ }
+ string_list_clear(&push_options, 0);
+
return 0;
}
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index 29d4e9a755..5c8849d115 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -28,7 +28,10 @@ static int dump_table(struct reftable_merged_table *mt)
const struct git_hash_algo *algop;
int err;
- reftable_merged_table_init_ref_iterator(mt, &it);
+ err = reftable_merged_table_init_ref_iterator(mt, &it);
+ if (err < 0)
+ return err;
+
err = reftable_iterator_seek_ref(&it, "");
if (err < 0)
return err;
@@ -63,7 +66,10 @@ static int dump_table(struct reftable_merged_table *mt)
reftable_iterator_destroy(&it);
reftable_ref_record_release(&ref);
- reftable_merged_table_init_log_iterator(mt, &it);
+ err = reftable_merged_table_init_log_iterator(mt, &it);
+ if (err < 0)
+ return err;
+
err = reftable_iterator_seek_log(&it, "");
if (err < 0)
return err;
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index 34bdb3ab1f..818700fbec 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -2,6 +2,7 @@
test_description='partial clone'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
diff --git a/t/t0450-txt-doc-vs-help.sh b/t/t0450-txt-doc-vs-help.sh
index 69917d7b84..f99a69ae1b 100755
--- a/t/t0450-txt-doc-vs-help.sh
+++ b/t/t0450-txt-doc-vs-help.sh
@@ -56,14 +56,11 @@ txt_to_synopsis () {
fi &&
b2t="$(builtin_to_txt "$builtin")" &&
sed -n \
- -e '/^\[verse\]$/,/^$/ {
+ -E '/^\[(verse|synopsis)\]$/,/^$/ {
/^$/d;
- /^\[verse\]$/d;
- s/_//g;
- s/++//g;
- s/`//g;
- s/{litdd}/--/g;
- s/'\''\(git[ a-z-]*\)'\''/\1/g;
+ /^\[(verse|synopsis)\]$/d;
+ s/\{litdd\}/--/g;
+ s/'\''(git[ a-z-]*)'\''/\1/g;
p;
}' \
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 6e230b5487..3d44bd7643 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -5,6 +5,7 @@ test_description='compare full workdir to sparse workdir'
GIT_TEST_SPLIT_INDEX=0
GIT_TEST_SPARSE_INDEX=
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t3207-branch-submodule.sh b/t/t3207-branch-submodule.sh
index fe72b24716..904eea7df5 100755
--- a/t/t3207-branch-submodule.sh
+++ b/t/t3207-branch-submodule.sh
@@ -5,6 +5,7 @@ test_description='git branch submodule tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh
index 1b3e97c875..5e9046e3df 100755
--- a/t/t3427-rebase-subtree.sh
+++ b/t/t3427-rebase-subtree.sh
@@ -7,6 +7,7 @@ This test runs git rebase and tests the subtree strategy.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3514-cherry-pick-revert-gpg.sh b/t/t3514-cherry-pick-revert-gpg.sh
index 5b2e250eaa..133dc07217 100755
--- a/t/t3514-cherry-pick-revert-gpg.sh
+++ b/t/t3514-cherry-pick-revert-gpg.sh
@@ -5,6 +5,7 @@
test_description='test {cherry-pick,revert} --[no-]gpg-sign'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t3909-stash-pathspec-file.sh b/t/t3909-stash-pathspec-file.sh
index 73f2dbdeb0..83269d0eb4 100755
--- a/t/t3909-stash-pathspec-file.sh
+++ b/t/t3909-stash-pathspec-file.sh
@@ -2,6 +2,7 @@
test_description='stash --pathspec-from-file'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_tick
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index 02d76dca28..950451cf6a 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -337,4 +337,32 @@ test_expect_success 'zero-width regex .* matches any function name' '
test_cmp expect actual
'
+test_expect_success 'show line-log with graph' '
+ qz_to_tab_space >expect <<-EOF &&
+ * $head_oid Modify func2() in file.c
+ |Z
+ | diff --git a/file.c b/file.c
+ | --- a/file.c
+ | +++ b/file.c
+ | @@ -6,4 +6,4 @@
+ | int func2()
+ | {
+ | - return F2;
+ | + return F2 + 2;
+ | }
+ * $root_oid Add func1() and func2() in file.c
+ ZZ
+ diff --git a/file.c b/file.c
+ --- /dev/null
+ +++ b/file.c
+ @@ -0,0 +6,4 @@
+ +int func2()
+ +{
+ + return F2;
+ +}
+ EOF
+ git log --graph --oneline -L:func2:file.c >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5323-pack-redundant.sh b/t/t5323-pack-redundant.sh
index 8dbbcc5e51..4e18f5490a 100755
--- a/t/t5323-pack-redundant.sh
+++ b/t/t5323-pack-redundant.sh
@@ -34,6 +34,7 @@ relationship between packs and objects is as follows:
Px2 | s s s x x x
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
main_repo=main.git
diff --git a/t/t5327-multi-pack-bitmaps-rev.sh b/t/t5327-multi-pack-bitmaps-rev.sh
index 9cac03a94b..994a8e6be4 100755
--- a/t/t5327-multi-pack-bitmaps-rev.sh
+++ b/t/t5327-multi-pack-bitmaps-rev.sh
@@ -2,6 +2,7 @@
test_description='exercise basic multi-pack bitmap functionality (.rev files)'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "${TEST_DIRECTORY}/lib-bitmap.sh"
diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh
index 1dd6284756..eca4a1eb8c 100755
--- a/t/t5333-pseudo-merge-bitmaps.sh
+++ b/t/t5333-pseudo-merge-bitmaps.sh
@@ -4,6 +4,7 @@ test_description='pseudo-merge bitmaps'
GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_pseudo_merges () {
diff --git a/t/t5334-incremental-multi-pack-index.sh b/t/t5334-incremental-multi-pack-index.sh
index c3b08acc73..471994c4bc 100755
--- a/t/t5334-incremental-multi-pack-index.sh
+++ b/t/t5334-incremental-multi-pack-index.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='incremental multi-pack-index'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-midx.sh
diff --git a/t/t5411-proc-receive-hook.sh b/t/t5411-proc-receive-hook.sh
index 92cf52c6d4..13d2d310a9 100755
--- a/t/t5411-proc-receive-hook.sh
+++ b/t/t5411-proc-receive-hook.sh
@@ -8,6 +8,7 @@ test_description='Test proc-receive hook'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/t5411/common-functions.sh
diff --git a/t/t5545-push-options.sh b/t/t5545-push-options.sh
index fb13549da7..64ce56d3aa 100755
--- a/t/t5545-push-options.sh
+++ b/t/t5545-push-options.sh
@@ -8,6 +8,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
mk_repo_pair () {
diff --git a/t/t5730-protocol-v2-bundle-uri-file.sh b/t/t5730-protocol-v2-bundle-uri-file.sh
index 37bdb725bc..38396df95b 100755
--- a/t/t5730-protocol-v2-bundle-uri-file.sh
+++ b/t/t5730-protocol-v2-bundle-uri-file.sh
@@ -7,6 +7,7 @@ TEST_NO_CREATE_REPO=1
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Test protocol v2 with 'file://' transport
diff --git a/t/t5731-protocol-v2-bundle-uri-git.sh b/t/t5731-protocol-v2-bundle-uri-git.sh
index 8add1b37ab..c199e955fe 100755
--- a/t/t5731-protocol-v2-bundle-uri-git.sh
+++ b/t/t5731-protocol-v2-bundle-uri-git.sh
@@ -7,6 +7,7 @@ TEST_NO_CREATE_REPO=1
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Test protocol v2 with 'git://' transport
diff --git a/t/t5732-protocol-v2-bundle-uri-http.sh b/t/t5732-protocol-v2-bundle-uri-http.sh
index 129daa0226..a9403e94c6 100755
--- a/t/t5732-protocol-v2-bundle-uri-http.sh
+++ b/t/t5732-protocol-v2-bundle-uri-http.sh
@@ -7,6 +7,7 @@ TEST_NO_CREATE_REPO=1
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Test protocol v2 with 'http://' transport
diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh
index de1e87f162..8ed1a215da 100755
--- a/t/t6012-rev-list-simplify.sh
+++ b/t/t6012-rev-list-simplify.sh
@@ -5,6 +5,7 @@ test_description='merge simplification'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
note () {
diff --git a/t/t6016-rev-list-graph-simplify-history.sh b/t/t6016-rev-list-graph-simplify-history.sh
index 54b0a6f5f8..2656d6a6bc 100755
--- a/t/t6016-rev-list-graph-simplify-history.sh
+++ b/t/t6016-rev-list-graph-simplify-history.sh
@@ -10,6 +10,7 @@ test_description='--graph and simplified history'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-log-graph.sh
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index 5ab4d41ee7..bf3e3f0b67 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -4,6 +4,7 @@ test_description='git filter-branch'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh
index d7167f5539..d434698919 100755
--- a/t/t8001-annotate.sh
+++ b/t/t8001-annotate.sh
@@ -5,6 +5,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
PROG='git annotate'
diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh
index 027235d61a..a30b2c9f70 100755
--- a/t/t9210-scalar.sh
+++ b/t/t9210-scalar.sh
@@ -2,6 +2,7 @@
test_description='test the `scalar` command'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
GIT_TEST_MAINT_SCHEDULER="crontab:test-tool crontab cron.txt,launchctl:true,schtasks:true"
diff --git a/t/t9211-scalar-clone.sh b/t/t9211-scalar-clone.sh
index 7869f45ee6..c16ea67c1d 100755
--- a/t/t9211-scalar-clone.sh
+++ b/t/t9211-scalar-clone.sh
@@ -2,6 +2,7 @@
test_description='test the `scalar clone` subcommand'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "${TEST_DIRECTORY}/lib-terminal.sh"
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 1eb035ee4c..2bdc02b459 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -7,6 +7,7 @@ test_description='git fast-export'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index e499c7f955..6da7440e73 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -11,6 +11,7 @@ cvs CLI client via git-cvsserver server'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
if ! test_have_prereq PERL; then
diff --git a/t/t9402-git-cvsserver-refs.sh b/t/t9402-git-cvsserver-refs.sh
index 2ee41f9443..c847120d52 100755
--- a/t/t9402-git-cvsserver-refs.sh
+++ b/t/t9402-git-cvsserver-refs.sh
@@ -8,6 +8,7 @@ tags, branches and other git refspecs'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
#########
diff --git a/t/t9850-shell.sh b/t/t9850-shell.sh
index cfc71c3bd4..f503f16d1b 100755
--- a/t/t9850-shell.sh
+++ b/t/t9850-shell.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git shell tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'shell allows upload-pack' '
diff --git a/t/unit-tests/lib-reftable.c b/t/unit-tests/lib-reftable.c
index ab1fa44a28..54c26c43e7 100644
--- a/t/unit-tests/lib-reftable.c
+++ b/t/unit-tests/lib-reftable.c
@@ -22,9 +22,11 @@ static int strbuf_writer_flush(void *arg UNUSED)
struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,
struct reftable_write_options *opts)
{
- return reftable_new_writer(&strbuf_writer_write,
- &strbuf_writer_flush,
- buf, opts);
+ struct reftable_writer *writer;
+ int ret = reftable_writer_new(&writer, &strbuf_writer_write, &strbuf_writer_flush,
+ buf, opts);
+ check(!ret);
+ return writer;
}
void t_reftable_write_to_buf(struct strbuf *buf,
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c
index e5556ebf52..1fa77b6faf 100644
--- a/t/unit-tests/t-reftable-basics.c
+++ b/t/unit-tests/t-reftable-basics.c
@@ -72,13 +72,14 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
if_test ("parse_names works for basic input") {
char in1[] = "line\n";
char in2[] = "a\nb\nc";
- char **out = NULL;
- parse_names(in1, strlen(in1), &out);
+ char **out = parse_names(in1, strlen(in1));
+ check(out != NULL);
check_str(out[0], "line");
check(!out[1]);
free_names(out);
- parse_names(in2, strlen(in2), &out);
+ out = parse_names(in2, strlen(in2));
+ check(out != NULL);
check_str(out[0], "a");
check_str(out[1], "b");
check_str(out[2], "c");
@@ -88,8 +89,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
if_test ("parse_names drops empty string") {
char in[] = "a\n\nb\n";
- char **out = NULL;
- parse_names(in, strlen(in), &out);
+ char **out = parse_names(in, strlen(in));
+ check(out != NULL);
check_str(out[0], "a");
/* simply '\n' should be dropped as empty string */
check_str(out[1], "b");
diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c
index f1a49485e2..d470060e8b 100644
--- a/t/unit-tests/t-reftable-block.c
+++ b/t/unit-tests/t-reftable-block.c
@@ -32,10 +32,12 @@ static void t_ref_block_read_write(void)
struct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;
REFTABLE_CALLOC_ARRAY(block.data, block_size);
+ check(block.data != NULL);
block.len = block_size;
block_source_from_strbuf(&block.source ,&buf);
- block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size,
- header_off, hash_size(GIT_SHA1_FORMAT_ID));
+ ret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size,
+ header_off, hash_size(GIT_SHA1_FORMAT_ID));
+ check(!ret);
rec.u.ref.refname = (char *) "";
rec.u.ref.value_type = REFTABLE_REF_DELETION;
@@ -124,10 +126,12 @@ static void t_log_block_read_write(void)
struct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;
REFTABLE_CALLOC_ARRAY(block.data, block_size);
+ check(block.data != NULL);
block.len = block_size;
block_source_from_strbuf(&block.source ,&buf);
- block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size,
- header_off, hash_size(GIT_SHA1_FORMAT_ID));
+ ret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size,
+ header_off, hash_size(GIT_SHA1_FORMAT_ID));
+ check(!ret);
for (i = 0; i < N; i++) {
rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i);
@@ -212,10 +216,12 @@ static void t_obj_block_read_write(void)
struct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;
REFTABLE_CALLOC_ARRAY(block.data, block_size);
+ check(block.data != NULL);
block.len = block_size;
block_source_from_strbuf(&block.source, &buf);
- block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size,
- header_off, hash_size(GIT_SHA1_FORMAT_ID));
+ ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size,
+ header_off, hash_size(GIT_SHA1_FORMAT_ID));
+ check(!ret);
for (i = 0; i < N; i++) {
uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated;
@@ -294,10 +300,12 @@ static void t_index_block_read_write(void)
struct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;
REFTABLE_CALLOC_ARRAY(block.data, block_size);
+ check(block.data != NULL);
block.len = block_size;
block_source_from_strbuf(&block.source, &buf);
- block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size,
- header_off, hash_size(GIT_SHA1_FORMAT_ID));
+ ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size,
+ header_off, hash_size(GIT_SHA1_FORMAT_ID));
+ check(!ret);
for (i = 0; i < N; i++) {
strbuf_init(&recs[i].u.idx.last_key, 9);
diff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c
index 19e54bdfb8..3c84363e98 100644
--- a/t/unit-tests/t-reftable-merged.c
+++ b/t/unit-tests/t-reftable-merged.c
@@ -29,7 +29,9 @@ merged_table_from_records(struct reftable_ref_record **refs,
int err;
REFTABLE_CALLOC_ARRAY(*readers, n);
+ check(*readers != NULL);
REFTABLE_CALLOC_ARRAY(*source, n);
+ check(*source != NULL);
for (size_t i = 0; i < n; i++) {
t_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts);
@@ -82,7 +84,8 @@ static void t_merged_single_record(void)
struct reftable_iterator it = { 0 };
int err;
- merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ check(!err);
err = reftable_iterator_seek_ref(&it, "a");
check(!err);
@@ -161,7 +164,8 @@ static void t_merged_refs(void)
size_t cap = 0;
size_t i;
- merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ check(!err);
err = reftable_iterator_seek_ref(&it, "a");
check(!err);
check_int(reftable_merged_table_hash_id(mt), ==, GIT_SHA1_FORMAT_ID);
@@ -283,7 +287,9 @@ merged_table_from_log_records(struct reftable_log_record **logs,
int err;
REFTABLE_CALLOC_ARRAY(*readers, n);
+ check(*readers != NULL);
REFTABLE_CALLOC_ARRAY(*source, n);
+ check(*source != NULL);
for (size_t i = 0; i < n; i++) {
t_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts);
@@ -367,7 +373,8 @@ static void t_merged_logs(void)
size_t cap = 0;
size_t i;
- merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ check(!err);
err = reftable_iterator_seek_log(&it, "a");
check(!err);
check_int(reftable_merged_table_hash_id(mt), ==, GIT_SHA1_FORMAT_ID);
@@ -390,7 +397,8 @@ static void t_merged_logs(void)
check(reftable_log_record_equal(want[i], &out[i],
GIT_SHA1_RAWSZ));
- merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ check(!err);
err = reftable_iterator_seek_log_at(&it, "a", 2);
check(!err);
reftable_log_record_release(&out[0]);
diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c
index e1b235a5f1..27ce84445e 100644
--- a/t/unit-tests/t-reftable-readwrite.c
+++ b/t/unit-tests/t-reftable-readwrite.c
@@ -52,8 +52,11 @@ static void write_table(char ***names, struct strbuf *buf, int N,
int i;
REFTABLE_CALLOC_ARRAY(*names, N + 1);
+ check(*names != NULL);
REFTABLE_CALLOC_ARRAY(refs, N);
+ check(refs != NULL);
REFTABLE_CALLOC_ARRAY(logs, N);
+ check(logs != NULL);
for (i = 0; i < N; i++) {
refs[i].refname = (*names)[i] = xstrfmt("refs/heads/branch%02d", i);
@@ -73,8 +76,8 @@ static void write_table(char ***names, struct strbuf *buf, int N,
t_reftable_write_to_buf(buf, refs, N, logs, N, &opts);
- free(refs);
- free(logs);
+ reftable_free(refs);
+ reftable_free(logs);
}
static void t_log_buffer_size(void)
@@ -150,23 +153,25 @@ static void t_log_overflow(void)
static void t_log_write_read(void)
{
- int N = 2;
- char **names = reftable_calloc(N + 1, sizeof(*names));
- int err;
struct reftable_write_options opts = {
.block_size = 256,
};
struct reftable_ref_record ref = { 0 };
- int i = 0;
struct reftable_log_record log = { 0 };
- int n;
struct reftable_iterator it = { 0 };
struct reftable_reader *reader;
struct reftable_block_source source = { 0 };
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
const struct reftable_stats *stats = NULL;
+ int N = 2, err, i, n;
+ char **names;
+
+ names = reftable_calloc(N + 1, sizeof(*names));
+ check(names != NULL);
+
reftable_writer_set_limits(w, 0, N);
+
for (i = 0; i < N; i++) {
char name[256];
struct reftable_ref_record ref = { 0 };
@@ -178,6 +183,7 @@ static void t_log_write_read(void)
err = reftable_writer_add_ref(w, &ref);
check(!err);
}
+
for (i = 0; i < N; i++) {
struct reftable_log_record log = { 0 };
@@ -206,7 +212,8 @@ static void t_log_write_read(void)
err = reftable_reader_new(&reader, &source, "file.log");
check(!err);
- reftable_reader_init_ref_iterator(reader, &it);
+ err = reftable_reader_init_ref_iterator(reader, &it);
+ check(!err);
err = reftable_iterator_seek_ref(&it, names[N - 1]);
check(!err);
@@ -221,8 +228,8 @@ static void t_log_write_read(void)
reftable_iterator_destroy(&it);
reftable_ref_record_release(&ref);
- reftable_reader_init_log_iterator(reader, &it);
-
+ err = reftable_reader_init_log_iterator(reader, &it);
+ check(!err);
err = reftable_iterator_seek_log(&it, "");
check(!err);
@@ -296,7 +303,8 @@ static void t_log_zlib_corruption(void)
err = reftable_reader_new(&reader, &source, "file.log");
check(!err);
- reftable_reader_init_log_iterator(reader, &it);
+ err = reftable_reader_init_log_iterator(reader, &it);
+ check(!err);
err = reftable_iterator_seek_log(&it, "refname");
check_int(err, ==, REFTABLE_ZLIB_ERROR);
@@ -325,7 +333,8 @@ static void t_table_read_write_sequential(void)
err = reftable_reader_new(&reader, &source, "file.ref");
check(!err);
- reftable_reader_init_ref_iterator(reader, &it);
+ err = reftable_reader_init_ref_iterator(reader, &it);
+ check(!err);
err = reftable_iterator_seek_ref(&it, "");
check(!err);
@@ -376,7 +385,8 @@ static void t_table_read_api(void)
err = reftable_reader_new(&reader, &source, "file.ref");
check(!err);
- reftable_reader_init_ref_iterator(reader, &it);
+ err = reftable_reader_init_ref_iterator(reader, &it);
+ check(!err);
err = reftable_iterator_seek_ref(&it, names[0]);
check(!err);
@@ -419,7 +429,8 @@ static void t_table_read_write_seek(int index, int hash_id)
}
for (i = 1; i < N; i++) {
- reftable_reader_init_ref_iterator(reader, &it);
+ err = reftable_reader_init_ref_iterator(reader, &it);
+ check(!err);
err = reftable_iterator_seek_ref(&it, names[i]);
check(!err);
err = reftable_iterator_next_ref(&it, &ref);
@@ -435,7 +446,8 @@ static void t_table_read_write_seek(int index, int hash_id)
strbuf_addstr(&pastLast, names[N - 1]);
strbuf_addstr(&pastLast, "/");
- reftable_reader_init_ref_iterator(reader, &it);
+ err = reftable_reader_init_ref_iterator(reader, &it);
+ check(!err);
err = reftable_iterator_seek_ref(&it, pastLast.buf);
if (err == 0) {
struct reftable_ref_record ref = { 0 };
@@ -470,8 +482,7 @@ static void t_table_read_write_seek_index(void)
static void t_table_refs_for(int indexed)
{
- int N = 50;
- char **want_names = reftable_calloc(N + 1, sizeof(*want_names));
+ char **want_names;
int want_names_len = 0;
uint8_t want_hash[GIT_SHA1_RAWSZ];
@@ -479,15 +490,15 @@ static void t_table_refs_for(int indexed)
.block_size = 256,
};
struct reftable_ref_record ref = { 0 };
- int i = 0;
- int n;
- int err;
struct reftable_reader *reader;
struct reftable_block_source source = { 0 };
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_iterator it = { 0 };
- int j;
+ int N = 50, n, j, err, i;
+
+ want_names = reftable_calloc(N + 1, sizeof(*want_names));
+ check(want_names != NULL);
t_reftable_set_hash(want_hash, 4, GIT_SHA1_FORMAT_ID);
@@ -534,7 +545,8 @@ static void t_table_refs_for(int indexed)
if (!indexed)
reader->obj_offsets.is_present = 0;
- reftable_reader_init_ref_iterator(reader, &it);
+ err = reftable_reader_init_ref_iterator(reader, &it);
+ check(!err);
err = reftable_iterator_seek_ref(&it, "");
check(!err);
reftable_iterator_destroy(&it);
@@ -593,7 +605,8 @@ static void t_write_empty_table(void)
err = reftable_reader_new(&rd, &source, "filename");
check(!err);
- reftable_reader_init_ref_iterator(rd, &it);
+ err = reftable_reader_init_ref_iterator(rd, &it);
+ check(!err);
err = reftable_iterator_seek_ref(&it, "");
check(!err);
@@ -802,7 +815,8 @@ static void t_write_multiple_indices(void)
* Seeking the log uses the log index now. In case there is any
* confusion regarding indices we would notice here.
*/
- reftable_reader_init_log_iterator(reader, &it);
+ err = reftable_reader_init_log_iterator(reader, &it);
+ check(!err);
err = reftable_iterator_seek_log(&it, "");
check(!err);
@@ -858,7 +872,8 @@ static void t_write_multi_level_index(void)
/*
* Seeking the last ref should work as expected.
*/
- reftable_reader_init_ref_iterator(reader, &it);
+ err = reftable_reader_init_ref_iterator(reader, &it);
+ check(!err);
err = reftable_iterator_seek_ref(&it, "refs/heads/199");
check(!err);
diff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c
index 31d563d992..874095b9ee 100644
--- a/t/unit-tests/t-reftable-stack.c
+++ b/t/unit-tests/t-reftable-stack.c
@@ -661,7 +661,9 @@ static void t_reftable_stack_iterator(void)
reftable_iterator_destroy(&it);
- reftable_stack_init_log_iterator(st, &it);
+ err = reftable_stack_init_log_iterator(st, &it);
+ check(!err);
+
reftable_iterator_seek_log(&it, logs[0].refname);
for (i = 0; ; i++) {
struct reftable_log_record log = { 0 };
@@ -1209,7 +1211,7 @@ static void unclean_stack_close(struct reftable_stack *st)
for (size_t i = 0; i < st->readers_len; i++)
reftable_reader_decref(st->readers[i]);
st->readers_len = 0;
- FREE_AND_NULL(st->readers);
+ REFTABLE_FREE_AND_NULL(st->readers);
}
static void t_reftable_stack_compaction_concurrent_clean(void)
diff --git a/t/unit-tests/t-reftable-tree.c b/t/unit-tests/t-reftable-tree.c
index 700479d34b..79b175a45a 100644
--- a/t/unit-tests/t-reftable-tree.c
+++ b/t/unit-tests/t-reftable-tree.c
@@ -37,16 +37,17 @@ static void t_tree_search(void)
* values[1] and values[10] (inclusive) in the tree.
*/
do {
- nodes[i] = tree_search(&values[i], &root, &t_compare, 1);
+ nodes[i] = tree_insert(&root, &values[i], &t_compare);
+ check(nodes[i] != NULL);
i = (i * 7) % 11;
} while (i != 1);
for (i = 1; i < ARRAY_SIZE(nodes); i++) {
check_pointer_eq(&values[i], nodes[i]->key);
- check_pointer_eq(nodes[i], tree_search(&values[i], &root, &t_compare, 0));
+ check_pointer_eq(nodes[i], tree_search(root, &values[i], &t_compare));
}
- check(!tree_search(values, &root, t_compare, 0));
+ check(!tree_search(root, values, t_compare));
tree_free(root);
}
@@ -62,7 +63,8 @@ static void t_infix_walk(void)
size_t count = 0;
do {
- tree_search(&values[i], &root, t_compare, 1);
+ struct tree_node *node = tree_insert(&root, &values[i], t_compare);
+ check(node != NULL);
i = (i * 7) % 11;
count++;
} while (i != 1);
diff --git a/wt-status.c b/wt-status.c
index 6a6397ca8f..6a8c05d1cf 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -717,6 +717,7 @@ static int add_file_to_list(const struct object_id *oid,
static void wt_status_collect_changes_initial(struct wt_status *s)
{
struct index_state *istate = s->repo->index;
+ struct strbuf base = STRBUF_INIT;
int i;
for (i = 0; i < istate->cache_nr; i++) {
@@ -735,7 +736,6 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
* expanding the trees to find the elements that are new in this
* tree and marking them with DIFF_STATUS_ADDED.
*/
- struct strbuf base = STRBUF_INIT;
struct pathspec ps = { 0 };
struct tree *tree = lookup_tree(istate->repo, &ce->oid);
@@ -743,9 +743,11 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
ps.has_wildcard = 1;
ps.max_depth = -1;
+ strbuf_reset(&base);
strbuf_add(&base, ce->name, ce->ce_namelen);
read_tree_at(istate->repo, tree, &base, 0, &ps,
add_file_to_list, s);
+
continue;
}
@@ -772,6 +774,8 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
s->committable = 1;
}
}
+
+ strbuf_release(&base);
}
static void wt_status_collect_untracked(struct wt_status *s)