Code clean-up.
* jk/misc-null-check-fixes:
fetch_bundle_uri(): drop pointless NULL check
notes: clean up confusing NULL checks in init_notes()
man7dir = $(mandir)/man7
# DESTDIR =
+GIT_DATE := $(shell git show --quiet --pretty='%as')
+
ASCIIDOC = asciidoc
ASCIIDOC_EXTRA =
ASCIIDOC_HTML = xhtml11
ASCIIDOC_DOCBOOK = docbook
ASCIIDOC_CONF = -f asciidoc.conf
ASCIIDOC_COMMON = $(ASCIIDOC) $(ASCIIDOC_EXTRA) $(ASCIIDOC_CONF) \
- -amanmanual='Git Manual' -amansource='Git $(GIT_VERSION)'
+ -amanmanual='Git Manual' -amansource='Git $(GIT_VERSION)' \
+ -arevdate='$(GIT_DATE)'
ASCIIDOC_DEPS = asciidoc.conf GIT-ASCIIDOCFLAGS
TXT_TO_HTML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_HTML)
TXT_TO_XML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_DOCBOOK)
--- /dev/null
+Git v2.30.9 Release Notes
+=========================
+
+This release addresses the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007.
+
+
+Fixes since v2.30.8
+-------------------
+
+ * CVE-2023-25652:
+
+ By feeding specially crafted input to `git apply --reject`, a
+ path outside the working tree can be overwritten with partially
+ controlled contents (corresponding to the rejected hunk(s) from
+ the given patch).
+
+ * CVE-2023-25815:
+
+ When Git is compiled with runtime prefix support and runs without
+ translated messages, it still used the gettext machinery to
+ display messages, which subsequently potentially looked for
+ translated messages in unexpected places. This allowed for
+ malicious placement of crafted messages.
+
+ * CVE-2023-29007:
+
+ When renaming or deleting a section from a configuration file,
+ certain malicious configuration values may be misinterpreted as
+ the beginning of a new configuration section, leading to arbitrary
+ configuration injection.
+
+Credit for finding CVE-2023-25652 goes to Ry0taK, and the fix was
+developed by Taylor Blau, Junio C Hamano and Johannes Schindelin,
+with the help of Linus Torvalds.
+
+Credit for finding CVE-2023-25815 goes to Maxime Escourbiac and
+Yassine BENGANA of Michelin, and the fix was developed by Johannes
+Schindelin.
+
+Credit for finding CVE-2023-29007 goes to André Baptista and VÃtor Pinho
+of Ethiack, and the fix was developed by Taylor Blau, and Johannes
+Schindelin, with help from Jeff King, and Patrick Steinhardt.
--- /dev/null
+Git v2.31.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9 to address the
+security issues CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007;
+see the release notes for that version for details.
--- /dev/null
+Git v2.32.7 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9 and v2.31.8 to
+address the security issues CVE-2023-25652, CVE-2023-25815, and
+CVE-2023-29007; see the release notes for these versions for
+details.
--- /dev/null
+Git v2.33.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8 and
+v2.32.7 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
--- /dev/null
+Git v2.34.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7 and v2.33.8 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
--- /dev/null
+Git v2.35.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8 and v2.34.8 to address the security issues
+CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007; see the release
+notes for these versions for details.
--- /dev/null
+Git v2.36.6 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8 and v2.35.8 to address the security issues
+CVE-2023-25652, CVS-2023-25815, and CVE-2023-29007; see the release
+notes for these versions for details.
--- /dev/null
+Git v2.37.7 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8 and v2.36.6 to address the
+security issues CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007;
+see the release notes for these versions for details.
--- /dev/null
+Git v2.38.5 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6 and v2.37.7 to address
+the security issues CVE-2023-25652, CVE-2023-25815, and
+CVE-2023-29007; see the release notes for these versions for
+details.
Git v2.39.3 Release Notes
=========================
-This release is primarily to merge fixes accumulated on the 'master'
-front to prepare for 2.40 release that are still relevant to 2.39.x
-maintenance track.
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6, v2.37.7 and v2.38.5 to
+address the security issues CVE-2023-25652, CVE-2023-25815, and
+CVE-2023-29007; see the release notes for these versions for
+details.
+
+This release also merges fixes that have accumulated on the 'master'
+front to prepare for the 2.40 release that are still relevant to
+2.39.x maintenance track.
Fixes since v2.39.2
-------------------
--- /dev/null
+Git v2.40.1 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6, v2.37.7, v2.38.5
+and v2.39.3 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
learns "--omit-empty" to hide refs that whose formatting result
becomes an empty string from the output.
+ * The sendemail-validate validate hook learned to pass the total
+ number of input files and where in the sequence each invocation is
+ via environment variables.
+
+ * When "gc" needs to retain unreachable objects, packing them into
+ cruft packs (instead of exploding them into loose object files) has
+ been offered as a more efficient option for some time. Now the use
+ of cruft packs has been made the default and no longer considered
+ an experimental feature.
+
Performance, Internal Implementation, Development Support etc.
* "git write-tree" learns to work better with sparse-index.
+ * The on-disk reverse index that allows mapping from the pack offset
+ to the object name for the object stored at the offset has been
+ enabled by default.
+
+ * "git fsck" learned to validate the on-disk pack reverse index files.
Fixes since v2.40
paths outside the current directory.
(merge 92b1dd1b9e rs/archive-from-subdirectory-fixes later to maint).
+ * The code to parse capability list for v0 on-wire protocol fell into
+ an infinite loop when a capability appears multiple times, which
+ has been corrected.
+
+ * Geometric repacking ("git repack --geometric=<n>") in a repository
+ that borrows from an alternate object database had various corner
+ case bugs, which have been corrected.
+ (merge d85cd18777 ps/fix-geom-repack-with-alternates later to maint).
+
+ * The "%GT" placeholder for the "--format" option of "git log" and
+ friends caused BUG() to trigger on a commit signed with an unknown
+ key, which has been corrected.
+ (merge 7891e46585 jk/gpg-trust-level-fix later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge f7111175df as/doc-markup-fix later to maint).
(merge 90ff7c9898 fc/test-aggregation-clean-up later to maint).
+
* `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by
skipping more commits at a time, reducing the number of round trips.
-+
-* `gc.cruftPacks=true` reduces disk space used by unreachable objects during
-garbage collection, preventing loose object explosions.
feature.manyFiles::
Enable config options that optimize for repos with many files in the
if the system supports it. Default is true.
gc.bigPackThreshold::
- If non-zero, all packs larger than this limit are kept when
- `git gc` is run. This is very similar to `--keep-largest-pack`
- except that all packs that meet the threshold are kept, not
- just the largest pack. Defaults to zero. Common unit suffixes of
- 'k', 'm', or 'g' are supported.
+ If non-zero, all non-cruft packs larger than this limit are kept
+ when `git gc` is run. This is very similar to
+ `--keep-largest-pack` except that all non-cruft packs that meet
+ the threshold are kept, not just the largest pack. Defaults to
+ zero. Common unit suffixes of 'k', 'm', or 'g' are supported.
+
Note that if the number of kept packs is more than gc.autoPackLimit,
this configuration variable is ignored, all packs except the base pack
gc.cruftPacks::
Store unreachable objects in a cruft pack (see
linkgit:git-repack[1]) instead of as loose objects. The default
- is `false`.
+ is `true`.
gc.pruneExpire::
When 'git gc' is run, it will call 'prune --expire 2.weeks.ago'
beneficial in repositories that have relatively large bitmap
indexes. Defaults to false.
+pack.readReverseIndex::
+ When true, git will read any .rev file(s) that may be available
+ (see: linkgit:gitformat-pack[5]). When false, the reverse index
+ will be generated from scratch and stored in memory. Defaults to
+ true.
+
pack.writeReverseIndex::
When true, git will write a corresponding .rev file (see:
linkgit:gitformat-pack[5])
for each new packfile that it writes in all places except for
linkgit:git-fast-import[1] and in the bulk checkin mechanism.
- Defaults to false.
+ Defaults to true.
$ git branch foo <2>
$ git tag foo <3>
------------
-
<1> creates a new branch `foo`, which refers to commit `f`, and then
updates `HEAD` to refer to branch `foo`. In other words, we'll no longer
be in detached `HEAD` state after this command.
-
<2> similarly creates a new branch `foo`, which refers to commit `f`,
but leaves `HEAD` detached.
-
<3> creates a new tag `foo`, which refers to commit `f`,
leaving `HEAD` detached.
EXAMPLES
--------
-. The following sequence checks out the `master` branch, reverts
- the `Makefile` to two revisions back, deletes `hello.c` by
- mistake, and gets it back from the index.
-+
+=== 1. Paths
+
+The following sequence checks out the `master` branch, reverts
+the `Makefile` to two revisions back, deletes `hello.c` by
+mistake, and gets it back from the index.
+
------------
$ git checkout master <1>
$ git checkout master~2 Makefile <2>
$ rm -f hello.c
$ git checkout hello.c <3>
------------
-+
<1> switch branch
<2> take a file out of another commit
<3> restore `hello.c` from the index
-+
+
If you want to check out _all_ C source files out of the index,
you can say
-+
+
------------
$ git checkout -- '*.c'
------------
-+
+
Note the quotes around `*.c`. The file `hello.c` will also be
checked out, even though it is no longer in the working tree,
because the file globbing is used to match entries in the index
(not in the working tree by the shell).
-+
+
If you have an unfortunate branch that is named `hello.c`, this
step would be confused as an instruction to switch to that branch.
You should instead write:
-+
+
------------
$ git checkout -- hello.c
------------
-. After working in the wrong branch, switching to the correct
- branch would be done using:
-+
+=== 2. Merge
+
+After working in the wrong branch, switching to the correct
+branch would be done using:
+
------------
$ git checkout mytopic
------------
-+
+
However, your "wrong" branch and correct `mytopic` branch may
differ in files that you have modified locally, in which case
the above checkout would fail like this:
-+
+
------------
$ git checkout mytopic
error: You have local changes to 'frotz'; not switching branches.
------------
-+
+
You can give the `-m` flag to the command, which would try a
three-way merge:
-+
+
------------
$ git checkout -m mytopic
Auto-merging frotz
------------
-+
+
After this three-way merge, the local modifications are _not_
registered in your index file, so `git diff` would show you what
changes you made since the tip of the new branch.
-. When a merge conflict happens during switching branches with
- the `-m` option, you would see something like this:
-+
+=== 3. Merge conflict
+
+When a merge conflict happens during switching branches with
+the `-m` option, you would see something like this:
+
------------
$ git checkout -m mytopic
Auto-merging frotz
ERROR: Merge conflict in frotz
fatal: merge program failed
------------
-+
+
At this point, `git diff` shows the changes cleanly merged as in
the previous example, as well as the changes in the conflicted
files. Edit and resolve the conflict and mark it resolved with
`git add` as usual:
-+
+
------------
$ edit frotz
$ git add frotz
be performed as well.
---cruft::
+--[no-]cruft::
When expiring unreachable objects, pack them separately into a
- cruft pack instead of storing them as loose objects.
+ cruft pack instead of storing them as loose objects. `--cruft`
+ is on by default.
--prune=<date>::
Prune loose objects older than date (default is 2 weeks ago,
instance running on this repository.
--keep-largest-pack::
- All packs except the largest pack and those marked with a
- `.keep` files are consolidated into a single pack. When this
- option is used, `gc.bigPackThreshold` is ignored.
+ All packs except the largest non-cruft pack, any packs marked
+ with a `.keep` file, and any cruft pack(s) are consolidated into
+ a single pack. When this option is used, `gc.bigPackThreshold`
+ is ignored.
AGGRESSIVE
----------
If you are GC-ing repositories in a mixed version environment, consider omitting
the `--cruft` option when using linkgit:git-repack[1] and linkgit:git-gc[1], and
-leaving the `gc.cruftPacks` configuration unset until all writers understand
-cruft packs.
+setting the `gc.cruftPacks` configuration to "false" until all writers
+understand cruft packs.
=== Alternatives
non-zero status causes `git send-email` to abort before sending any
e-mails.
+The following environment variables are set when executing the hook.
+
+`GIT_SENDEMAIL_FILE_COUNTER`::
+ A 1-based counter incremented by one for every file holding an e-mail
+ to be sent (excluding any FIFOs). This counter does not follow the
+ patch series counter scheme. It will always start at 1 and will end at
+ GIT_SENDEMAIL_FILE_TOTAL.
+
+`GIT_SENDEMAIL_FILE_TOTAL`::
+ The total number of files that will be sent (excluding any FIFOs). This
+ counter does not follow the patch series counter scheme. It will always
+ be equal to the number of files being sent, whether there is a cover
+ letter or not.
+
+These variables may for instance be used to validate patch series.
+
+The sample `sendemail-validate` hook that comes with Git checks that all sent
+patches (excluding the cover letter) can be applied on top of the upstream
+repository default branch without conflicts. Some placeholders are left for
+additional validation steps to be performed after all patches of a given series
+have been applied.
+
fsmonitor-watchman
~~~~~~~~~~~~~~~~~~
LIB_OBJS += fsmonitor-ipc.o
LIB_OBJS += fsmonitor-settings.o
LIB_OBJS += gettext.o
+LIB_OBJS += git-zlib.o
LIB_OBJS += gpg-interface.o
LIB_OBJS += graph.o
LIB_OBJS += grep.o
LIB_OBJS += ws.o
LIB_OBJS += wt-status.o
LIB_OBJS += xdiff-interface.o
-LIB_OBJS += zlib.o
BUILTIN_OBJS += builtin/add.o
BUILTIN_OBJS += builtin/am.o
#include "cache.h"
#include "add-interactive.h"
+#include "advice.h"
#include "alloc.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
+#include "object-name.h"
#include "strbuf.h"
#include "run-command.h"
#include "strvec.h"
#include "xdiff-interface.h"
#include "ll-merge.h"
#include "lockfile.h"
+#include "object-name.h"
+#include "object-file.h"
#include "parse-options.h"
#include "quote.h"
#include "rerere.h"
FILE *rej;
char namebuf[PATH_MAX];
struct fragment *frag;
- int cnt = 0;
+ int fd, cnt = 0;
struct strbuf sb = STRBUF_INIT;
for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) {
memcpy(namebuf, patch->new_name, cnt);
memcpy(namebuf + cnt, ".rej", 5);
- rej = fopen(namebuf, "w");
+ fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
+ if (fd < 0) {
+ if (errno != EEXIST)
+ return error_errno(_("cannot open %s"), namebuf);
+ if (unlink(namebuf))
+ return error_errno(_("cannot unlink '%s'"), namebuf);
+ fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
+ if (fd < 0)
+ return error_errno(_("cannot open %s"), namebuf);
+ }
+ rej = fdopen(fd, "w");
if (!rej)
return error_errno(_("cannot open %s"), namebuf);
#include "alloc.h"
#include "config.h"
#include "gettext.h"
+#include "git-zlib.h"
#include "hex.h"
#include "tar.h"
#include "archive.h"
#include "config.h"
#include "archive.h"
#include "gettext.h"
+#include "git-zlib.h"
#include "hex.h"
#include "streaming.h"
#include "utf8.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
+#include "convert.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#ifndef ARCHIVE_H
#define ARCHIVE_H
-#include "cache.h"
+#include "object-name.h"
#include "pathspec.h"
+#include "string-list.h"
struct repository;
struct pretty_print_context;
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "commit.h"
#include "diff.h"
#include "strvec.h"
#include "commit-slab.h"
#include "commit-reach.h"
+#include "object-name.h"
#include "object-store.h"
#include "dir.h"
#include "object-store.h"
#include "cache-tree.h"
#include "mergesort.h"
+#include "convert.h"
#include "diff.h"
#include "diffcore.h"
#include "gettext.h"
#include "hex.h"
#include "setup.h"
#include "tag.h"
+#include "trace2.h"
#include "blame.h"
#include "alloc.h"
#include "commit-slab.h"
#include "git-compat-util.h"
-#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "branch.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "refs.h"
#include "refspec.h"
#include "remote.h"
*/
#define USE_THE_INDEX_VARIABLE
#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "builtin.h"
#include "lockfile.h"
+#include "editor.h"
#include "dir.h"
#include "gettext.h"
#include "pathspec.h"
#define USE_THE_INDEX_VARIABLE
#include "cache.h"
#include "abspath.h"
+#include "advice.h"
#include "config.h"
#include "builtin.h"
+#include "editor.h"
#include "environment.h"
#include "exec-cmd.h"
#include "gettext.h"
#include "diffcore.h"
#include "unpack-trees.h"
#include "branch.h"
+#include "object-name.h"
#include "sequencer.h"
#include "revision.h"
#include "merge-recursive.h"
#include "apply.h"
#include "string-list.h"
#include "packfile.h"
+#include "pager.h"
#include "repository.h"
#include "pretty.h"
#include "wrapper.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "bisect.h"
#include "refs.h"
#include "dir.h"
#include "strvec.h"
#include "run-command.h"
+#include "oid-array.h"
#include "prompt.h"
#include "quote.h"
#include "revision.h"
#include "line-log.h"
#include "dir.h"
#include "progress.h"
+#include "object-name.h"
#include "object-store.h"
+#include "pager.h"
#include "blame.h"
#include "refs.h"
#include "setup.h"
#include "cache.h"
#include "config.h"
#include "color.h"
+#include "editor.h"
#include "environment.h"
#include "refs.h"
#include "commit.h"
#include "builtin.h"
#include "gettext.h"
+#include "object-name.h"
#include "remote.h"
#include "parse-options.h"
#include "branch.h"
#include "builtin.h"
#include "abspath.h"
+#include "editor.h"
#include "gettext.h"
#include "parse-options.h"
#include "strbuf.h"
#include "hook.h"
#include "hook-list.h"
#include "diagnose.h"
+#include "object-file.h"
#include "setup.h"
#include "wrapper.h"
#include "cache.h"
#include "alloc.h"
#include "config.h"
+#include "convert.h"
#include "builtin.h"
#include "diff.h"
#include "environment.h"
#include "tree-walk.h"
#include "oid-array.h"
#include "packfile.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "replace-object.h"
#include "promisor-remote.h"
#include "attr.h"
#include "environment.h"
#include "gettext.h"
+#include "object-name.h"
#include "quote.h"
#include "setup.h"
#include "parse-options.h"
#include "hook.h"
#include "ll-merge.h"
#include "lockfile.h"
+#include "mem-pool.h"
#include "merge-recursive.h"
+#include "object-name.h"
#include "object-store.h"
#include "parse-options.h"
#include "refs.h"
#include "setup.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "trace2.h"
#include "tree.h"
#include "tree-walk.h"
#include "unpack-trees.h"
#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "abspath.h"
+#include "advice.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
#include "fetch-pack.h"
#include "refs.h"
#include "refspec.h"
+#include "object-file.h"
#include "object-store.h"
#include "tree.h"
#include "tree-walk.h"
#include "hook.h"
#include "bundle.h"
#include "bundle-uri.h"
+#include "wrapper.h"
/*
* Overall FIXMEs:
#include "progress.h"
#include "replace-object.h"
#include "tag.h"
+#include "trace2.h"
#define BUILTIN_COMMIT_GRAPH_VERIFY_USAGE \
N_("git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]")
#include "config.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "commit.h"
#define USE_THE_INDEX_VARIABLE
#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "lockfile.h"
#include "cache-tree.h"
#include "color.h"
#include "dir.h"
+#include "editor.h"
#include "environment.h"
#include "builtin.h"
#include "diff.h"
#include "log-tree.h"
#include "strbuf.h"
#include "utf8.h"
+#include "object-name.h"
#include "parse-options.h"
#include "string-list.h"
#include "rerere.h"
#include "alloc.h"
#include "config.h"
#include "color.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
#include "ident.h"
#include "abspath.h"
#include "alloc.h"
#include "gettext.h"
+#include "object-file.h"
#include "parse-options.h"
#ifndef NO_UNIX_SOCKETS
#include "refs.h"
#include "builtin.h"
#include "exec-cmd.h"
+#include "object-name.h"
#include "parse-options.h"
#include "revision.h"
#include "diff.h"
#include "builtin.h"
#include "abspath.h"
#include "gettext.h"
+#include "object-file.h"
#include "parse-options.h"
#include "diagnose.h"
#include "strvec.h"
#include "strbuf.h"
#include "lockfile.h"
+#include "object-file.h"
#include "object-store.h"
#include "dir.h"
#include "entry.h"
#include "hex.h"
#include "refs.h"
#include "refspec.h"
+#include "object-file.h"
#include "object-store.h"
#include "commit.h"
#include "object.h"
#include "dir.h"
#include "run-command.h"
#include "packfile.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "mem-pool.h"
#include "commit-reach.h"
#include "alloc.h"
#include "gettext.h"
#include "hex.h"
+#include "object-file.h"
#include "pkt-line.h"
#include "fetch-pack.h"
#include "remote.h"
* "git fetch"
*/
#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "gettext.h"
#include "environment.h"
#include "repository.h"
#include "refs.h"
#include "refspec.h"
+#include "object-name.h"
#include "object-store.h"
#include "oidset.h"
+#include "oid-array.h"
#include "commit.h"
#include "builtin.h"
#include "string-list.h"
#include "strvec.h"
#include "utf8.h"
#include "packfile.h"
+#include "pager.h"
#include "list-objects-filter-options.h"
#include "commit-reach.h"
#include "branch.h"
#include "promisor-remote.h"
#include "commit-graph.h"
#include "shallow.h"
+#include "trace.h"
+#include "trace2.h"
#include "worktree.h"
#include "bundle-uri.h"
#include "streaming.h"
#include "decorate.h"
#include "packfile.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "replace-object.h"
#include "resolve-undo.h"
#include "run-command.h"
#include "worktree.h"
+#include "pack-revindex.h"
#define REACHABLE 0x0001
#define SEEN 0x0002
#define ERROR_REFS 010
#define ERROR_COMMIT_GRAPH 020
#define ERROR_MULTI_PACK_INDEX 040
+#define ERROR_PACK_REV_INDEX 0100
static const char *describe_object(const struct object_id *oid)
{
return 0;
}
+static int check_pack_rev_indexes(struct repository *r, int show_progress)
+{
+ struct progress *progress = NULL;
+ uint32_t pack_count = 0;
+ int res = 0;
+
+ if (show_progress) {
+ for (struct packed_git *p = get_all_packs(the_repository); p; p = p->next)
+ pack_count++;
+ progress = start_delayed_progress("Verifying reverse pack-indexes", pack_count);
+ pack_count = 0;
+ }
+
+ for (struct packed_git *p = get_all_packs(the_repository); p; p = p->next) {
+ int load_error = load_pack_revindex_from_disk(p);
+
+ if (load_error < 0) {
+ error(_("unable to load rev-index for pack '%s'"), p->pack_name);
+ res = ERROR_PACK_REV_INDEX;
+ } else if (!load_error &&
+ !load_pack_revindex(the_repository, p) &&
+ verify_pack_revindex(p)) {
+ error(_("invalid rev-index for pack '%s'"), p->pack_name);
+ res = ERROR_PACK_REV_INDEX;
+ }
+ display_progress(progress, ++pack_count);
+ }
+ stop_progress(&progress);
+
+ return res;
+}
+
static char const * const fsck_usage[] = {
N_("git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
" [--[no-]full] [--strict] [--verbose] [--lost-found]\n"
free_worktrees(worktrees);
}
+ errors_found |= check_pack_rev_indexes(the_repository, show_progress);
+
check_connectivity();
if (the_repository->settings.core_commit_graph) {
#include "simple-ipc.h"
#include "khash.h"
#include "pkt-line.h"
+#include "trace2.h"
static const char * const builtin_fsmonitor__daemon_usage[] = {
N_("git fsmonitor--daemon start [<options>]"),
#include "commit.h"
#include "commit-graph.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
#include "pack.h"
#include "pack-objects.h"
#include "gettext.h"
#include "hook.h"
#include "setup.h"
+#include "trace2.h"
#include "wrapper.h"
#define FAILED_RUN "failed to run %s"
static int pack_refs = 1;
static int prune_reflogs = 1;
-static int cruft_packs = -1;
+static int cruft_packs = 1;
static int aggressive_depth = 50;
static int aggressive_window = 250;
static int gc_auto_threshold = 6700;
struct packed_git *p, *base = NULL;
for (p = get_all_packs(the_repository); p; p = p->next) {
- if (!p->pack_local)
+ if (!p->pack_local || p->is_cruft)
continue;
if (limit) {
if (p->pack_size >= limit)
if (prune_expire && parse_expiry_date(prune_expire, &dummy))
die(_("failed to parse prune expiry value %s"), prune_expire);
- prepare_repo_settings(the_repository);
- if (cruft_packs < 0)
- cruft_packs = the_repository->settings.gc_cruft_packs;
-
if (aggressive) {
strvec_push(&repack, "-f");
if (aggressive_depth > 0)
#include "setup.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "packfile.h"
+#include "pager.h"
#include "write-or-die.h"
static const char *grep_prefix;
#include "config.h"
#include "gettext.h"
#include "hex.h"
+#include "object-file.h"
#include "object-store.h"
#include "blob.h"
#include "quote.h"
#include "builtin.h"
#include "exec-cmd.h"
#include "gettext.h"
+#include "pager.h"
#include "parse-options.h"
#include "run-command.h"
#include "config-list.h"
#include "streaming.h"
#include "thread-utils.h"
#include "packfile.h"
+#include "pack-revindex.h"
+#include "object-file.h"
#include "object-store.h"
+#include "oid-array.h"
#include "replace-object.h"
#include "promisor-remote.h"
#include "setup.h"
fsck_options.walk = mark_link;
reset_pack_idx_option(&opts);
+ opts.flags |= WRITE_REV;
git_config(git_index_pack_config, &opts);
if (prefix && chdir(prefix))
die(_("Cannot come back to cwd"));
- if (git_env_bool(GIT_TEST_WRITE_REV_INDEX, 0))
- rev_index = 1;
+ if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0))
+ rev_index = 0;
else
rev_index = !!(opts.flags & (WRITE_REV_VERIFY | WRITE_REV));
#include "refs.h"
#include "builtin.h"
#include "exec-cmd.h"
+#include "object-file.h"
#include "parse-options.h"
#include "setup.h"
#include "worktree.h"
#include "gettext.h"
#include "hex.h"
#include "refs.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
+#include "pager.h"
#include "color.h"
#include "commit.h"
#include "diff.h"
#include "revision.h"
#include "log-tree.h"
#include "builtin.h"
+#include "oid-array.h"
#include "tag.h"
#include "reflog-walk.h"
#include "patch-ids.h"
#include "cache.h"
#include "repository.h"
#include "config.h"
+#include "convert.h"
#include "quote.h"
#include "dir.h"
#include "builtin.h"
#include "gettext.h"
+#include "object-name.h"
#include "strbuf.h"
#include "tree.h"
#include "cache-tree.h"
#include "config.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "object-store.h"
#include "blob.h"
#include "tree.h"
#include "refs.h"
#include "diff.h"
#include "revision.h"
+#include "object-name.h"
#include "parse-options.h"
#include "repository.h"
#include "commit-reach.h"
#include "cache.h"
#include "builtin.h"
+#include "advice.h"
#include "commit.h"
#include "gettext.h"
#include "tag.h"
#include "merge-recursive.h"
+#include "object-name.h"
#include "xdiff-interface.h"
static const char builtin_merge_recursive_usage[] =
#include "commit.h"
#include "commit-reach.h"
#include "merge-ort.h"
+#include "object-name.h"
#include "object-store.h"
#include "parse-options.h"
#include "repository.h"
#define USE_THE_INDEX_VARIABLE
#include "cache.h"
#include "abspath.h"
+#include "advice.h"
#include "alloc.h"
#include "config.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "builtin.h"
#include "lockfile.h"
#include "parse-options.h"
#include "tag.h"
#include "replace-object.h"
+#include "object-file.h"
#include "object-store.h"
#include "fsck.h"
#include "config.h"
#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "abspath.h"
+#include "advice.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
+#include "object-file.h"
#include "pathspec.h"
#include "lockfile.h"
#include "dir.h"
#include "commit.h"
#include "tag.h"
#include "refs.h"
+#include "object-name.h"
+#include "pager.h"
#include "parse-options.h"
#include "prio-queue.h"
#include "hash-lookup.h"
#include "cache.h"
#include "config.h"
#include "builtin.h"
+#include "editor.h"
#include "gettext.h"
#include "hex.h"
#include "notes.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "blob.h"
#include "strvec.h"
#include "list.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
#include "replace-object.h"
#include "dir.h"
}
string_list_sort(&include_packs);
+ string_list_remove_duplicates(&include_packs, 0);
string_list_sort(&exclude_packs);
+ string_list_remove_duplicates(&exclude_packs, 0);
for (p = get_all_packs(the_repository); p; p = p->next) {
const char *pack_name = pack_basename(p);
- item = string_list_lookup(&include_packs, pack_name);
- if (!item)
- item = string_list_lookup(&exclude_packs, pack_name);
-
- if (item)
+ if ((item = string_list_lookup(&include_packs, pack_name)))
+ item->util = p;
+ if ((item = string_list_lookup(&exclude_packs, pack_name)))
item->util = p;
}
}
reset_pack_idx_option(&pack_idx_opts);
+ pack_idx_opts.flags |= WRITE_REV;
git_config(git_pack_config, NULL);
- if (git_env_bool(GIT_TEST_WRITE_REV_INDEX, 0))
- pack_idx_opts.flags |= WRITE_REV;
+ if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0))
+ pack_idx_opts.flags &= ~WRITE_REV;
progress = isatty(2);
argc = parse_options(argc, argv, prefix, pack_objects_options,
#include "progress.h"
#include "prune-packed.h"
#include "replace-object.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "shallow.h"
*/
#define USE_THE_INDEX_VARIABLE
#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "builtin.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "exec-cmd.h"
#include "run-command.h"
* "git push"
*/
#include "cache.h"
+#include "advice.h"
#include "branch.h"
#include "config.h"
#include "environment.h"
#include "submodule.h"
#include "submodule-config.h"
#include "send-pack.h"
+#include "trace2.h"
#include "color.h"
static const char * const push_usage[] = {
#include "cache.h"
#include "builtin.h"
#include "gettext.h"
+#include "object-name.h"
#include "parse-options.h"
#include "range-diff.h"
#include "config.h"
#include "hex.h"
#include "lockfile.h"
#include "object.h"
+#include "object-name.h"
#include "tree.h"
#include "tree-walk.h"
#include "cache-tree.h"
#include "cache-tree.h"
#include "unpack-trees.h"
#include "lockfile.h"
+#include "object-file.h"
+#include "object-name.h"
#include "parse-options.h"
#include "commit.h"
#include "diff.h"
#include "sequencer.h"
#include "rebase-interactive.h"
#include "reset.h"
+#include "trace2.h"
#include "hook.h"
#include "wrapper.h"
#include "tmp-objdir.h"
#include "oidset.h"
#include "packfile.h"
+#include "object-name.h"
#include "object-store.h"
#include "protocol.h"
#include "commit-reach.h"
+#include "trace.h"
+#include "trace2.h"
#include "worktree.h"
#include "shallow.h"
#include "parse-options.h"
const char *feature_list = reader->line + linelen + 1;
const char *hash = NULL;
const char *client_sid;
- int len = 0;
+ size_t len = 0;
if (parse_feature_request(feature_list, "report-status"))
report_status = 1;
if (parse_feature_request(feature_list, "report-status-v2"))
}
static void init_pack_geometry(struct pack_geometry **geometry_p,
- struct string_list *existing_kept_packs)
+ struct string_list *existing_kept_packs,
+ const struct pack_objects_args *args)
{
struct packed_git *p;
struct pack_geometry *geometry;
geometry = *geometry_p;
for (p = get_all_packs(the_repository); p; p = p->next) {
+ if (args->local && !p->pack_local)
+ /*
+ * When asked to only repack local packfiles we skip
+ * over any packfiles that are borrowed from alternate
+ * object directories.
+ */
+ continue;
+
if (!pack_kept_objects) {
/*
* Any pack that has its pack_keep bit set will appear
geometry->split = split;
}
-static struct packed_git *get_largest_active_pack(struct pack_geometry *geometry)
+static struct packed_git *get_preferred_pack(struct pack_geometry *geometry)
{
+ uint32_t i;
+
if (!geometry) {
/*
* No geometry means either an all-into-one repack (in which
}
if (geometry->split == geometry->pack_nr)
return NULL;
- return geometry->pack[geometry->pack_nr - 1];
+
+ /*
+ * The preferred pack is the largest pack above the split line. In
+ * other words, it is the largest pack that does not get rolled up in
+ * the geometric repack.
+ */
+ for (i = geometry->pack_nr; i > geometry->split; i--)
+ /*
+ * A pack that is not local would never be included in a
+ * multi-pack index. We thus skip over any non-local packs.
+ */
+ if (geometry->pack[i - 1]->pack_local)
+ return geometry->pack[i - 1];
+
+ return NULL;
}
static void clear_pack_geometry(struct pack_geometry *geometry)
for (i = geometry->split; i < geometry->pack_nr; i++) {
struct packed_git *p = geometry->pack[i];
+ /*
+ * The multi-pack index never refers to packfiles part
+ * of an alternate object database, so we skip these.
+ * While git-multi-pack-index(1) would silently ignore
+ * them anyway, this allows us to skip executing the
+ * command completely when we have only non-local
+ * packfiles.
+ */
+ if (!p->pack_local)
+ continue;
+
strbuf_addstr(&buf, pack_basename(p));
strbuf_strip_suffix(&buf, ".pack");
strbuf_addstr(&buf, ".idx");
{
struct child_process cmd = CHILD_PROCESS_INIT;
struct string_list_item *item;
- struct packed_git *largest = get_largest_active_pack(geometry);
+ struct packed_git *preferred = get_preferred_pack(geometry);
FILE *in;
int ret;
if (write_bitmaps)
strvec_push(&cmd.args, "--bitmap");
- if (largest)
+ if (preferred)
strvec_pushf(&cmd.args, "--preferred-pack=%s",
- pack_basename(largest));
+ pack_basename(preferred));
if (refs_snapshot)
strvec_pushf(&cmd.args, "--refs-snapshot=%s", refs_snapshot);
N_("same as -a, pack unreachable cruft objects separately"),
PACK_CRUFT),
OPT_STRING(0, "cruft-expiration", &cruft_expiration, N_("approxidate"),
- N_("with -C, expire objects older than this")),
+ N_("with --cruft, expire objects older than this")),
OPT_BOOL('d', NULL, &delete_redundant,
N_("remove redundant packs, and run git-prune-packed")),
OPT_BOOL('f', NULL, &po_args.no_reuse_delta,
if (write_bitmaps && !(pack_everything & ALL_INTO_ONE) && !write_midx)
die(_(incremental_bitmap_conflict_error));
+ if (write_bitmaps && po_args.local && has_alt_odb(the_repository)) {
+ /*
+ * When asked to do a local repack, but we have
+ * packfiles that are inherited from an alternate, then
+ * we cannot guarantee that the multi-pack-index would
+ * have full coverage of all objects. We thus disable
+ * writing bitmaps in that case.
+ */
+ warning(_("disabling bitmap writing, as some objects are not being packed"));
+ write_bitmaps = 0;
+ }
+
if (write_midx && write_bitmaps) {
struct strbuf path = STRBUF_INIT;
if (geometric_factor) {
if (pack_everything)
die(_("options '%s' and '%s' cannot be used together"), "--geometric", "-A/-a");
- init_pack_geometry(&geometry, &existing_kept_packs);
+ init_pack_geometry(&geometry, &existing_kept_packs, &po_args);
split_pack_geometry(geometry, geometric_factor);
}
#include "cache.h"
#include "config.h"
#include "builtin.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "refs.h"
#include "parse-options.h"
#include "run-command.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "replace-object.h"
#include "repository.h"
*/
#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
+#include "advice.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
#include "diffcore.h"
#include "tree.h"
#include "branch.h"
+#include "object-name.h"
#include "parse-options.h"
#include "unpack-trees.h"
#include "cache-tree.h"
#include "setup.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "trace.h"
+#include "trace2.h"
#include "dir.h"
#include "add-interactive.h"
#include "list-objects-filter.h"
#include "list-objects-filter-options.h"
#include "object.h"
+#include "object-name.h"
+#include "object-file.h"
#include "object-store.h"
#include "pack.h"
#include "pack-bitmap.h"
#include "refs.h"
#include "quote.h"
#include "builtin.h"
+#include "object-name.h"
#include "parse-options.h"
#include "diff.h"
#include "revision.h"
#include "cache-tree.h"
#include "gettext.h"
#include "tree-walk.h"
+#include "object-name.h"
#include "parse-options.h"
#include "string-list.h"
#include "setup.h"
#include "builtin.h"
#include "color.h"
#include "strvec.h"
+#include "object-name.h"
#include "parse-options.h"
#include "dir.h"
#include "commit-slab.h"
#include "gettext.h"
#include "hex.h"
#include "refs.h"
+#include "object-name.h"
#include "object-store.h"
#include "object.h"
#include "tag.h"
#include "dir.h"
#include "environment.h"
#include "gettext.h"
+#include "object-file.h"
+#include "object-name.h"
#include "parse-options.h"
#include "pathspec.h"
#include "repository.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "refs.h"
#include "lockfile.h"
#include "revision.h"
#include "diffcore.h"
#include "diff.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "advice.h"
#include "branch.h"
*/
#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "builtin.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "refs.h"
+#include "object-name.h"
#include "object-store.h"
#include "tag.h"
#include "run-command.h"
#include "builtin.h"
#include "config.h"
#include "hex.h"
+#include "object-name.h"
#include "object-store.h"
#include "wrapper.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
+#include "git-zlib.h"
#include "hex.h"
#include "object-store.h"
#include "object.h"
#include "cache-tree.h"
#include "tree-walk.h"
#include "builtin.h"
+#include "object-file.h"
#include "refs.h"
#include "resolve-undo.h"
#include "parse-options.h"
#include "gettext.h"
#include "refs.h"
#include "builtin.h"
+#include "object-name.h"
#include "parse-options.h"
#include "quote.h"
#include "strvec.h"
*/
#include "builtin.h"
#include "config.h"
+#include "editor.h"
#include "ident.h"
+#include "pager.h"
#include "refs.h"
static const char var_usage[] = "git var (-l | <variable>)";
#include "config.h"
#include "builtin.h"
#include "gettext.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "commit.h"
#include "gettext.h"
#include "tag.h"
#include "run-command.h"
+#include "object-name.h"
#include "parse-options.h"
#include "gpg-interface.h"
#include "ref-filter.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-file.h"
+#include "object-name.h"
#include "parse-options.h"
#include "strvec.h"
#include "branch.h"
/*
* Copyright (c) 2011, Google Inc.
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "bulk-checkin.h"
#include "environment.h"
#include "string-list.h"
#include "tmp-objdir.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
+#include "wrapper.h"
static int odb_transaction_nesting;
-#include "cache.h"
+#include "git-compat-util.h"
#include "lockfile.h"
#include "bundle.h"
#include "environment.h"
#include "tree-walk.h"
#include "cache-tree.h"
#include "bulk-checkin.h"
+#include "object-file.h"
#include "object-store.h"
#include "replace-object.h"
#include "promisor-remote.h"
#include "sparse-index.h"
+#include "trace.h"
+#include "trace2.h"
#ifndef DEBUG_CACHE_TREE
#define DEBUG_CACHE_TREE 0
#include "git-compat-util.h"
#include "strbuf.h"
#include "hashmap.h"
-#include "list.h"
-#include "advice.h"
#include "gettext.h"
-#include "convert.h"
-#include "trace.h"
-#include "trace2.h"
#include "string-list.h"
-#include "pack-revindex.h"
-#include "hash.h"
-#include "path.h"
#include "pathspec.h"
#include "object.h"
-#include "oid-array.h"
-#include "repository.h"
#include "statinfo.h"
-#include "mem-pool.h"
-
-typedef struct git_zstream {
- z_stream z;
- unsigned long avail_in;
- unsigned long avail_out;
- unsigned long total_in;
- unsigned long total_out;
- unsigned char *next_in;
- unsigned char *next_out;
-} git_zstream;
-
-void git_inflate_init(git_zstream *);
-void git_inflate_init_gzip_only(git_zstream *);
-void git_inflate_end(git_zstream *);
-int git_inflate(git_zstream *, int flush);
-
-void git_deflate_init(git_zstream *, int level);
-void git_deflate_init_gzip(git_zstream *, int level);
-void git_deflate_init_raw(git_zstream *, int level);
-void git_deflate_end(git_zstream *);
-int git_deflate_abort(git_zstream *);
-int git_deflate_end_gently(git_zstream *);
-int git_deflate(git_zstream *, int flush);
-unsigned long git_deflate_bound(git_zstream *, unsigned long);
#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
#define DTYPE(de) ((de)->d_type)
#define DTYPE(de) DT_UNKNOWN
#endif
-/* unknown mode (impossible combination S_IFIFO|S_IFCHR) */
-#define S_IFINVALID 0030000
-
-/*
- * A "directory link" is a link to another git directory.
- *
- * The value 0160000 is not normally a valid mode, and
- * also just happens to be S_IFDIR + S_IFLNK
- */
-#define S_IFGITLINK 0160000
-#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
-
/*
* Some mode bits are also used internally for computations.
*
#define S_DIFFTREE_IFXMIN_NEQ 0x80000000
-/*
- * Intensive research over the course of many years has shown that
- * port 9418 is totally unused by anything else. Or
- *
- * Your search - "port 9418" - did not match any documents.
- *
- * as www.google.com puts it.
- *
- * This port has been properly assigned for git use by IANA:
- * git (Assigned-9418) [I06-050728-0001].
- *
- * git 9418/tcp git pack transfer service
- * git 9418/udp git pack transfer service
- *
- * with Linus Torvalds <torvalds@osdl.org> as the point of
- * contact. September 2005.
- *
- * See http://www.iana.org/assignments/port-numbers
- */
-#define DEFAULT_GIT_PORT 9418
-
/*
* Basic data structures for the directory cache
*/
#error "CE_EXTENDED_FLAGS out of range"
#endif
-#define S_ISSPARSEDIR(m) ((m) == S_IFDIR)
-
/* Forward structure decls */
struct pathspec;
-struct child_process;
struct tree;
/*
#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
#define ce_intent_to_add(ce) ((ce)->ce_flags & CE_INTENT_TO_ADD)
-#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
-static inline unsigned int create_ce_mode(unsigned int mode)
-{
- if (S_ISLNK(mode))
- return S_IFLNK;
- if (S_ISSPARSEDIR(mode))
- return S_IFDIR;
- if (S_ISDIR(mode) || S_ISGITLINK(mode))
- return S_IFGITLINK;
- return S_IFREG | ce_permissions(mode);
-}
static inline unsigned int ce_mode_from_stat(const struct cache_entry *ce,
unsigned int mode)
{
else
return DT_UNKNOWN;
}
-static inline unsigned int canon_mode(unsigned int mode)
-{
- if (S_ISREG(mode))
- return S_IFREG | ce_permissions(mode);
- if (S_ISLNK(mode))
- return S_IFLNK;
- if (S_ISDIR(mode))
- return S_IFDIR;
- return S_IFGITLINK;
-}
static inline int ce_path_match(struct index_state *istate,
const struct cache_entry *ce,
extern struct index_state the_index;
#endif
-static inline enum object_type object_type(unsigned int mode)
-{
- return S_ISDIR(mode) ? OBJ_TREE :
- S_ISGITLINK(mode) ? OBJ_COMMIT :
- OBJ_BLOB;
-}
-
#define INIT_DB_QUIET 0x0001
#define INIT_DB_EXIST_OK 0x0002
int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
-#define HASH_WRITE_OBJECT 1
-#define HASH_FORMAT_CHECK 2
-#define HASH_RENORMALIZE 4
-#define HASH_SILENT 8
-int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
-int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
-
/*
* Record to sd the data from st that we use to check whether a file
* might have changed.
extern int verify_index_checksum;
extern int verify_ce_order;
-extern int quote_path_fully;
-
#define MTIME_CHANGED 0x0001
#define CTIME_CHANGED 0x0002
#define OWNER_CHANGED 0x0004
#define DATA_CHANGED 0x0020
#define TYPE_CHANGED 0x0040
-/*
- * Return an abbreviated sha1 unique within this repository's object database.
- * The result will be at least `len` characters long, and will be NUL
- * terminated.
- *
- * The non-`_r` version returns a static buffer which remains valid until 4
- * more calls to repo_find_unique_abbrev are made.
- *
- * The `_r` variant writes to a buffer supplied by the caller, which must be at
- * least `GIT_MAX_HEXSZ + 1` bytes. The return value is the number of bytes
- * written (excluding the NUL terminator).
- *
- * Note that while this version avoids the static buffer, it is not fully
- * reentrant, as it calls into other non-reentrant git code.
- */
-const char *repo_find_unique_abbrev(struct repository *r, const struct object_id *oid, int len);
-int repo_find_unique_abbrev_r(struct repository *r, char *hex, const struct object_id *oid, int len);
-
-/*
- * Create the directory containing the named path, using care to be
- * somewhat safe against races. Return one of the scld_error values to
- * indicate success/failure. On error, set errno to describe the
- * problem.
- *
- * SCLD_VANISHED indicates that one of the ancestor directories of the
- * path existed at one point during the function call and then
- * suddenly vanished, probably because another process pruned the
- * directory while we were working. To be robust against this kind of
- * race, callers might want to try invoking the function again when it
- * returns SCLD_VANISHED.
- *
- * safe_create_leading_directories() temporarily changes path while it
- * is working but restores it before returning.
- * safe_create_leading_directories_const() doesn't modify path, even
- * temporarily. Both these variants adjust the permissions of the
- * created directories to honor core.sharedRepository, so they are best
- * suited for files inside the git dir. For working tree files, use
- * safe_create_leading_directories_no_share() instead, as it ignores
- * the core.sharedRepository setting.
- */
-enum scld_error {
- SCLD_OK = 0,
- SCLD_FAILED = -1,
- SCLD_PERMS = -2,
- SCLD_EXISTS = -3,
- SCLD_VANISHED = -4
-};
-enum scld_error safe_create_leading_directories(char *path);
-enum scld_error safe_create_leading_directories_const(const char *path);
-enum scld_error safe_create_leading_directories_no_share(char *path);
-
-int mkdir_in_gitdir(const char *path);
-
-int git_open_cloexec(const char *name, int flags);
-#define git_open(name) git_open_cloexec(name, O_RDONLY)
-
-/**
- * unpack_loose_header() initializes the data stream needed to unpack
- * a loose object header.
- *
- * Returns:
- *
- * - ULHR_OK on success
- * - ULHR_BAD on error
- * - ULHR_TOO_LONG if the header was too long
- *
- * It will only parse up to MAX_HEADER_LEN bytes unless an optional
- * "hdrbuf" argument is non-NULL. This is intended for use with
- * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error)
- * reporting. The full header will be extracted to "hdrbuf" for use
- * with parse_loose_header(), ULHR_TOO_LONG will still be returned
- * from this function to indicate that the header was too long.
- */
-enum unpack_loose_header_result {
- ULHR_OK,
- ULHR_BAD,
- ULHR_TOO_LONG,
-};
-enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
- unsigned char *map,
- unsigned long mapsize,
- void *buffer,
- unsigned long bufsiz,
- struct strbuf *hdrbuf);
-
-/**
- * parse_loose_header() parses the starting "<type> <len>\0" of an
- * object. If it doesn't follow that format -1 is returned. To check
- * the validity of the <type> populate the "typep" in the "struct
- * object_info". It will be OBJ_BAD if the object type is unknown. The
- * parsed <len> can be retrieved via "oi->sizep", and from there
- * passed to unpack_loose_rest().
- */
-struct object_info;
-int parse_loose_header(const char *hdr, struct object_info *oi);
-
-/**
- * With in-core object data in "buf", rehash it to make sure the
- * object name actually matches "oid" to detect object corruption.
- *
- * A negative value indicates an error, usually that the OID is not
- * what we expected, but it might also indicate another error.
- */
-int check_object_signature(struct repository *r, const struct object_id *oid,
- void *map, unsigned long size,
- enum object_type type);
-
-/**
- * A streaming version of check_object_signature().
- * Try reading the object named with "oid" using
- * the streaming interface and rehash it to do the same.
- */
-int stream_object_signature(struct repository *r, const struct object_id *oid);
-
-int finalize_object_file(const char *tmpfile, const char *filename);
-
-/* Helper to check and "touch" a file */
-int check_and_freshen_file(const char *fn, int freshen);
-
-/* Convert to/from hex/sha1 representation */
-#define MINIMUM_ABBREV minimum_abbrev
-#define DEFAULT_ABBREV default_abbrev
-
-/* used when the code does not know or care what the default abbrev is */
-#define FALLBACK_DEFAULT_ABBREV 7
-
-struct object_context {
- unsigned short mode;
- /*
- * symlink_path is only used by get_tree_entry_follow_symlinks,
- * and only for symlinks that point outside the repository.
- */
- struct strbuf symlink_path;
- /*
- * If GET_OID_RECORD_PATH is set, this will record path (if any)
- * found when resolving the name. The caller is responsible for
- * releasing the memory.
- */
- char *path;
-};
-
-int repo_get_oid(struct repository *r, const char *str, struct object_id *oid);
-__attribute__((format (printf, 2, 3)))
-int get_oidf(struct object_id *oid, const char *fmt, ...);
-int repo_get_oid_commit(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_committish(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_tree(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_treeish(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_blob(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_mb(struct repository *r, const char *str, struct object_id *oid);
-void maybe_die_on_misspelt_object_name(struct repository *repo,
- const char *name,
- const char *prefix);
-enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
- unsigned flags, struct object_id *oid,
- struct object_context *oc);
-
-typedef int each_abbrev_fn(const struct object_id *oid, void *);
-int repo_for_each_abbrev(struct repository *r, const char *prefix, each_abbrev_fn, void *);
-
-int set_disambiguate_hint_config(const char *var, const char *value);
-
-/*
- * This reads short-hand syntax that not only evaluates to a commit
- * object name, but also can act as if the end user spelled the name
- * of the branch from the command line.
- *
- * - "@{-N}" finds the name of the Nth previous branch we were on, and
- * places the name of the branch in the given buf and returns the
- * number of characters parsed if successful.
- *
- * - "<branch>@{upstream}" finds the name of the other ref that
- * <branch> is configured to merge with (missing <branch> defaults
- * to the current branch), and places the name of the branch in the
- * given buf and returns the number of characters parsed if
- * successful.
- *
- * If the input is not of the accepted format, it returns a negative
- * number to signal an error.
- *
- * If the input was ok but there are not N branch switches in the
- * reflog, it returns 0.
- */
-#define INTERPRET_BRANCH_LOCAL (1<<0)
-#define INTERPRET_BRANCH_REMOTE (1<<1)
-#define INTERPRET_BRANCH_HEAD (1<<2)
-struct interpret_branch_name_options {
- /*
- * If "allowed" is non-zero, it is a treated as a bitfield of allowable
- * expansions: local branches ("refs/heads/"), remote branches
- * ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
- * allowed, even ones to refs outside of those namespaces.
- */
- unsigned allowed;
-
- /*
- * If ^{upstream} or ^{push} (or equivalent) is requested, and the
- * branch in question does not have such a reference, return -1 instead
- * of die()-ing.
- */
- unsigned nonfatal_dangling_mark : 1;
-};
-int repo_interpret_branch_name(struct repository *r,
- const char *str, int len,
- struct strbuf *buf,
- const struct interpret_branch_name_options *options);
-
int base_name_compare(const char *name1, size_t len1, int mode1,
const char *name2, size_t len2, int mode2);
int df_name_compare(const char *name1, size_t len1, int mode1,
int name_compare(const char *name1, size_t len1, const char *name2, size_t len2);
int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2);
-void *read_object_with_reference(struct repository *r,
- const struct object_id *oid,
- enum object_type required_type,
- unsigned long *size,
- struct object_id *oid_ret);
-
-struct object *repo_peel_to_type(struct repository *r,
- const char *name, int namelen,
- struct object *o, enum object_type);
-
-const char *git_editor(void);
-const char *git_sequence_editor(void);
-const char *git_pager(int stdout_is_tty);
-int is_terminal_dumb(void);
-
struct cache_def {
struct strbuf path;
int flags;
struct packed_git *p;
};
-/*
- * Set this to 0 to prevent oid_object_info_extended() from fetching missing
- * blobs. This has a difference only if extensions.partialClone is set.
- *
- * Its default value is 1.
- */
-extern int fetch_if_missing;
-
/* Dumb servers support */
int update_server_info(int);
-extern const char *git_mailmap_file;
-extern const char *git_mailmap_blob;
-
#define COPY_READ_ERROR (-2)
#define COPY_WRITE_ERROR (-3)
int copy_fd(int ifd, int ofd);
int copy_file(const char *dst, const char *src, int mode);
int copy_file_with_time(const char *dst, const char *src, int mode);
-/* pager.c */
-void setup_pager(void);
-int pager_in_use(void);
-extern int pager_use_color;
-int term_columns(void);
-void term_clear_line(void);
-int decimal_width(uintmax_t);
-int check_pager_config(const char *cmd);
-void prepare_pager_args(struct child_process *, const char *pager);
-
/* base85 */
int decode_85(char *dst, const char *line, int linelen);
void encode_85(char *buf, const unsigned char *data, int bytes);
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "chdir-notify.h"
#include "list.h"
+#include "path.h"
#include "strbuf.h"
+#include "trace.h"
struct chdir_notify_entry {
const char *name;
-#include "cache.h"
+#include "git-compat-util.h"
+#include "object-name.h"
#include "remote.h"
#include "refspec.h"
#include "checkout.h"
#include "config.h"
+#include "strbuf.h"
struct tracking_name_data {
/* const */ char *src_ref;
export GIT_TEST_MULTI_PACK_INDEX=1
export GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=1
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
- export GIT_TEST_WRITE_REV_INDEX=1
+ export GIT_TEST_NO_WRITE_REV_INDEX=1
export GIT_TEST_CHECKOUT_WORKERS=2
;;
linux-clang)
#include "cache.h"
#include "config.h"
#include "color.h"
+#include "editor.h"
#include "gettext.h"
#include "hex.h"
+#include "pager.h"
static int git_use_color_default = GIT_COLOR_AUTO;
int color_stdout_is_tty = -1;
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "column.h"
#include "string-list.h"
+#include "pager.h"
#include "parse-options.h"
#include "run-command.h"
#include "utf8.h"
#include "cache.h"
#include "object-store.h"
#include "commit.h"
+#include "convert.h"
#include "blob.h"
#include "diff.h"
#include "diffcore.h"
#include "environment.h"
#include "hex.h"
+#include "object-name.h"
#include "quote.h"
#include "xdiff-interface.h"
#include "xdiff/xmacros.h"
#include "userdiff.h"
#include "oid-array.h"
#include "revision.h"
+#include "wrapper.h"
static int compare_paths(const struct combine_diff_path *one,
const struct diff_filespec *two)
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "gettext.h"
#include "hex.h"
#include "revision.h"
#include "hash-lookup.h"
#include "commit-graph.h"
+#include "object-file.h"
#include "object-store.h"
+#include "oid-array.h"
#include "alloc.h"
#include "hashmap.h"
#include "replace-object.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "tag.h"
#include "commit.h"
#include "commit-graph.h"
#include "gettext.h"
#include "hex.h"
#include "repository.h"
+#include "object-name.h"
#include "object-store.h"
#include "pkt-line.h"
#include "utf8.h"
#include "gettext.h"
#include "attr.h"
#include "setup.h"
+#include "trace2.h"
/*
* Many parts of Git have subprograms communicate via pipe, expect the
#include "fsm-listen.h"
#include "fsmonitor--daemon.h"
#include "gettext.h"
+#include "trace2.h"
/*
* The documentation of ReadDirectoryChangesW() states that the maximum
#include "win32/lazyload.h"
#include "../config.h"
#include "../environment.h"
+#include "../trace2.h"
#include "../wrapper.h"
#include "dir.h"
#include "gettext.h"
#include "../git-compat-util.h"
+#include "../wrapper.h"
ssize_t git_pread(int fd, void *buf, size_t count, off_t offset)
{
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "simple-ipc.h"
#include "strbuf.h"
#include "pkt-line.h"
#include "thread-utils.h"
+#include "trace2.h"
#include "unix-socket.h"
#include "unix-stream-server.h"
#include "strbuf.h"
#include "pkt-line.h"
#include "thread-utils.h"
+#include "trace.h"
+#include "trace2.h"
#include "accctrl.h"
#include "aclapi.h"
#include "../../cache.h"
#include "../../json-writer.h"
+#include "../../trace2.h"
#include "lazyload.h"
#include <Psapi.h>
#include <tlHelp32.h>
*/
#include "cache.h"
#include "abspath.h"
+#include "advice.h"
#include "alloc.h"
#include "date.h"
#include "branch.h"
#include "config.h"
+#include "convert.h"
#include "environment.h"
#include "gettext.h"
#include "ident.h"
#include "repository.h"
#include "lockfile.h"
+#include "mailmap.h"
#include "exec-cmd.h"
#include "strbuf.h"
#include "quote.h"
#include "hashmap.h"
#include "string-list.h"
+#include "object-name.h"
#include "object-store.h"
+#include "pager.h"
#include "utf8.h"
#include "dir.h"
#include "color.h"
#include "replace-object.h"
#include "refs.h"
#include "setup.h"
+#include "trace2.h"
#include "worktree.h"
#include "wrapper.h"
#include "write-or-die.h"
flags);
}
-static int section_name_match (const char *buf, const char *name)
+static size_t section_name_match (const char *buf, const char *name)
{
- int i = 0, j = 0, dot = 0;
+ size_t i = 0, j = 0;
+ int dot = 0;
if (buf[i] != '[')
return 0;
for (i = 1; buf[i] && buf[i] != ']'; i++) {
return 1;
}
+#define GIT_CONFIG_MAX_LINE_LEN (512 * 1024)
+
/* if new_name == NULL, the section is removed instead */
static int git_config_copy_or_rename_section_in_file(const char *config_filename,
const char *old_name,
char *filename_buf = NULL;
struct lock_file lock = LOCK_INIT;
int out_fd;
- char buf[1024];
+ struct strbuf buf = STRBUF_INIT;
FILE *config_file = NULL;
struct stat st;
struct strbuf copystr = STRBUF_INIT;
struct config_store_data store;
+ uint32_t line_nr = 0;
memset(&store, 0, sizeof(store));
goto out;
}
- while (fgets(buf, sizeof(buf), config_file)) {
- unsigned i;
- int length;
+ while (!strbuf_getwholeline(&buf, config_file, '\n')) {
+ size_t i, length;
int is_section = 0;
- char *output = buf;
- for (i = 0; buf[i] && isspace(buf[i]); i++)
+ char *output = buf.buf;
+
+ line_nr++;
+
+ if (buf.len >= GIT_CONFIG_MAX_LINE_LEN) {
+ ret = error(_("refusing to work with overly long line "
+ "in '%s' on line %"PRIuMAX),
+ config_filename, (uintmax_t)line_nr);
+ goto out;
+ }
+
+ for (i = 0; buf.buf[i] && isspace(buf.buf[i]); i++)
; /* do nothing */
- if (buf[i] == '[') {
+ if (buf.buf[i] == '[') {
/* it's a section */
- int offset;
+ size_t offset;
is_section = 1;
/*
strbuf_reset(©str);
}
- offset = section_name_match(&buf[i], old_name);
+ offset = section_name_match(&buf.buf[i], old_name);
if (offset > 0) {
ret++;
if (!new_name) {
out_no_rollback:
free(filename_buf);
config_store_data_clear(&store);
+ strbuf_release(&buf);
return ret;
}
#include "git-compat-util.h"
-#include "cache.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
#include "string-list.h"
#include "oid-array.h"
#include "transport.h"
+#include "trace2.h"
#include "strbuf.h"
#include "version.h"
#include "protocol.h"
static char *server_capabilities_v1;
static struct strvec server_capabilities_v2 = STRVEC_INIT;
-static const char *next_server_feature_value(const char *feature, int *len, int *offset);
+static const char *next_server_feature_value(const char *feature, size_t *len, size_t *offset);
static int check_ref(const char *name, unsigned int flags)
{
static void annotate_refs_with_symref_info(struct ref *ref)
{
struct string_list symref = STRING_LIST_INIT_DUP;
- int offset = 0;
+ size_t offset = 0;
while (1) {
- int len;
+ size_t len;
const char *val;
val = next_server_feature_value("symref", &len, &offset);
static void process_capabilities(struct packet_reader *reader, int *linelen)
{
const char *feat_val;
- int feat_len;
+ size_t feat_len;
const char *line = reader->line;
int nul_location = strlen(line);
if (nul_location == *linelen)
return 0;
name++;
- return oideq(null_oid(), &oid) && !strcmp(name, "capabilities^{}");
+ return oideq(reader->hash_algo->null_oid, &oid) &&
+ !strcmp(name, "capabilities^{}");
}
static void check_no_capabilities(const char *line, int len)
return list;
}
-const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset)
+const char *parse_feature_value(const char *feature_list, const char *feature, size_t *lenp, size_t *offset)
{
- int len;
+ const char *orig_start = feature_list;
+ size_t len;
if (!feature_list)
return NULL;
if (lenp)
*lenp = 0;
if (offset)
- *offset = found + len - feature_list;
+ *offset = found + len - orig_start;
return value;
}
/* feature with a value (e.g., "agent=git/1.2.3") */
else if (*value == '=') {
- int end;
+ size_t end;
value++;
end = strcspn(value, " \t\n");
if (lenp)
*lenp = end;
if (offset)
- *offset = value + end - feature_list;
+ *offset = value + end - orig_start;
return value;
}
/*
int server_supports_hash(const char *desired, int *feature_supported)
{
- int offset = 0;
- int len;
+ size_t offset = 0;
+ size_t len;
const char *hash;
hash = next_server_feature_value("object-format", &len, &offset);
return !!parse_feature_value(feature_list, feature, NULL, NULL);
}
-static const char *next_server_feature_value(const char *feature, int *len, int *offset)
+static const char *next_server_feature_value(const char *feature, size_t *len, size_t *offset)
{
return parse_feature_value(server_capabilities_v1, feature, len, offset);
}
-const char *server_feature_value(const char *feature, int *len)
+const char *server_feature_value(const char *feature, size_t *len)
{
return parse_feature_value(server_capabilities_v1, feature, len, NULL);
}
int git_connection_is_socket(struct child_process *conn);
int server_supports(const char *feature);
int parse_feature_request(const char *features, const char *feature);
-const char *server_feature_value(const char *feature, int *len_ret);
+const char *server_feature_value(const char *feature, size_t *len_ret);
int url_is_local_not_ssh(const char *url);
struct packet_reader;
enum protocol_version discover_version(struct packet_reader *reader);
int server_supports_hash(const char *desired, int *feature_supported);
-const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset);
+const char *parse_feature_value(const char *feature_list, const char *feature, size_t *lenp, size_t *offset);
int server_supports_v2(const char *c);
void ensure_server_supports_v2(const char *c);
int server_feature_v2(const char *c, const char **v);
# variable, in that order.
__git_eread ()
{
- test -r "$1" && IFS=$'\r\n' read "$2" <"$1"
+ test -r "$1" && IFS=$'\r\n' read -r "$2" <"$1"
}
# see if a cherry-pick or revert is in progress, if the user has committed a
#include "cache.h"
+#include "advice.h"
#include "config.h"
+#include "convert.h"
#include "gettext.h"
#include "hex.h"
#include "object-store.h"
#include "sigchain.h"
#include "pkt-line.h"
#include "sub-process.h"
+#include "trace.h"
#include "utf8.h"
#include "ll-merge.h"
#include "wrapper.h"
#include "config.h"
#include "environment.h"
#include "pkt-line.h"
+#include "protocol.h"
#include "run-command.h"
#include "setup.h"
#include "strbuf.h"
#include "cache.h"
#include "date.h"
#include "gettext.h"
+#include "pager.h"
/*
* This is like mktime, but without normalization of tm_wday and tm_yday.
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "attr.h"
#include "object.h"
#include "diffcore.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "revision.h"
#include "cache-tree.h"
#include "unpack-trees.h"
#include "refs.h"
#include "submodule.h"
+#include "trace.h"
#include "dir.h"
#include "fsmonitor.h"
#include "commit-reach.h"
* Copyright (c) 2008 by Junio C Hamano
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "color.h"
#include "commit.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
+#include "convert.h"
#include "environment.h"
#include "gettext.h"
#include "tempfile.h"
#include "string-list.h"
#include "strvec.h"
#include "graph.h"
+#include "oid-array.h"
#include "packfile.h"
+#include "pager.h"
#include "parse-options.h"
#include "help.h"
#include "promisor-remote.h"
#include "dir.h"
+#include "object-file.h"
+#include "object-name.h"
#include "setup.h"
#include "strmap.h"
#include "wrapper.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
+#include "convert.h"
#include "dir.h"
#include "environment.h"
#include "gettext.h"
+#include "object-file.h"
#include "object-store.h"
#include "attr.h"
#include "refs.h"
#include "fsmonitor.h"
#include "setup.h"
#include "submodule-config.h"
+#include "trace2.h"
#include "wrapper.h"
/*
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
+#include "advice.h"
#include "config.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
+#include "pager.h"
#include "strbuf.h"
#include "strvec.h"
#include "run-command.h"
#include "sigchain.h"
+#include "wrapper.h"
#ifndef DEFAULT_EDITOR
#define DEFAULT_EDITOR "vi"
{
return launch_specified_editor(git_sequence_editor(), path, buffer, env);
}
+
+int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
+ const char *const *env)
+{
+ char *path2 = NULL;
+ int fd, res = 0;
+
+ if (!is_absolute_path(path))
+ path = path2 = xstrdup(git_path("%s", path));
+
+ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0)
+ res = error_errno(_("could not open '%s' for writing"), path);
+ else if (write_in_full(fd, buffer->buf, buffer->len) < 0) {
+ res = error_errno(_("could not write to '%s'"), path);
+ close(fd);
+ } else if (close(fd) < 0)
+ res = error_errno(_("could not close '%s'"), path);
+ else {
+ strbuf_reset(buffer);
+ if (launch_editor(path, buffer, env) < 0)
+ res = error_errno(_("could not edit '%s'"), path);
+ unlink(path);
+ }
+
+ free(path2);
+ return res;
+}
--- /dev/null
+#ifndef EDITOR_H
+#define EDITOR_H
+
+struct strbuf;
+
+const char *git_editor(void);
+const char *git_sequence_editor(void);
+int is_terminal_dumb(void);
+
+/**
+ * Launch the user preferred editor to edit a file and fill the buffer
+ * with the file's contents upon the user completing their editing. The
+ * third argument can be used to set the environment which the editor is
+ * run in. If the buffer is NULL the editor is launched as usual but the
+ * file's contents are not read into the buffer upon completion.
+ */
+int launch_editor(const char *path, struct strbuf *buffer,
+ const char *const *env);
+
+int launch_sequence_editor(const char *path, struct strbuf *buffer,
+ const char *const *env);
+
+/*
+ * In contrast to `launch_editor()`, this function writes out the contents
+ * of the specified file first, then clears the `buffer`, then launches
+ * the editor and reads back in the file contents into the `buffer`.
+ * Finally, it deletes the temporary file.
+ *
+ * If `path` is relative, it refers to a file in the `.git` directory.
+ */
+int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
+ const char *const *env);
+
+#endif
#include "cache.h"
#include "abspath.h"
#include "branch.h"
+#include "convert.h"
#include "environment.h"
#include "gettext.h"
#include "repository.h"
#include "fmt-merge-msg.h"
#include "commit.h"
#include "strvec.h"
+#include "object-file.h"
#include "object-store.h"
#include "replace-object.h"
#include "tmp-objdir.h"
#include "chdir-notify.h"
#include "setup.h"
#include "shallow.h"
+#include "trace.h"
#include "wrapper.h"
#include "write-or-die.h"
size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
size_t delta_base_cache_limit = 96 * 1024 * 1024;
unsigned long big_file_threshold = 512 * 1024 * 1024;
-int pager_use_color = 1;
const char *editor_program;
const char *askpass_program;
const char *excludes_file;
#include "gettext.h"
#include "quote.h"
#include "strvec.h"
+#include "trace.h"
+#include "trace2.h"
#if defined(RUNTIME_PREFIX)
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "repository.h"
#include "config.h"
#include "remote.h"
#include "run-command.h"
#include "connect.h"
+#include "trace2.h"
#include "transport.h"
#include "version.h"
#include "oid-array.h"
struct ref *ref = copy_ref_list(orig_ref);
struct object_id oid;
const char *agent_feature;
- int agent_len;
+ size_t agent_len;
struct fetch_negotiator negotiator_alloc;
struct fetch_negotiator *negotiator;
agent_supported = 1;
if (agent_len)
print_verbose(args, _("Server version is %.*s"),
- agent_len, agent_feature);
+ (int)agent_len, agent_feature);
}
if (!server_supports("session-id"))
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
#include "refs.h"
+#include "object-name.h"
#include "object-store.h"
#include "diff.h"
#include "diff-merges.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "hex.h"
#include "object-store.h"
#include "fsmonitor-ipc.h"
#include "run-command.h"
#include "strbuf.h"
+#include "trace2.h"
#define INDEX_EXTENSION_VERSION1 (1)
#define INDEX_EXTENSION_VERSION2 (2)
#include "cache.h"
#include "dir.h"
#include "fsmonitor-settings.h"
+#include "trace.h"
extern struct trace_key trace_fsmonitor;
setlocale(LC_CTYPE, "C");
}
+int git_gettext_enabled = 0;
+
void git_setup_gettext(void)
{
const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT);
init_gettext_charset("git");
textdomain("git");
+ git_gettext_enabled = 1;
+
free(p);
}
#define FORMAT_PRESERVING(n) __attribute__((format_arg(n)))
#ifndef NO_GETTEXT
+extern int git_gettext_enabled;
void git_setup_gettext(void);
int gettext_width(const char *s);
#else
+#define git_gettext_enabled (0)
static inline void git_setup_gettext(void)
{
}
{
if (!*msgid)
return "";
+ if (!git_gettext_enabled)
+ return msgid;
return gettext(msgid);
}
static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2)
const char *Q_(const char *msgid, const char *plu, unsigned long n)
{
+ if (!git_gettext_enabled)
+ return n == 1 ? msgid : plu;
return ngettext(msgid, plu, n);
}
#define pread git_pread
ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
#endif
-/*
- * Forward decl that will remind us if its twin in cache.h changes.
- * This function is used in compat/pread.c. But we can't include
- * cache.h there.
- */
-ssize_t read_in_full(int fd, void *buf, size_t count);
#ifdef NO_SETENV
#define setenv gitsetenv
@files = handle_backup_files(@files);
if ($validate) {
+ # FIFOs can only be read once, exclude them from validation.
+ my @real_files = ();
foreach my $f (@files) {
unless (-p $f) {
- validate_patch($f, $target_xfer_encoding);
+ push(@real_files, $f);
}
}
+
+ # Run the loop once again to avoid gaps in the counter due to FIFO
+ # arguments provided by the user.
+ my $num = 1;
+ my $num_files = scalar @real_files;
+ $ENV{GIT_SENDEMAIL_FILE_TOTAL} = "$num_files";
+ foreach my $r (@real_files) {
+ $ENV{GIT_SENDEMAIL_FILE_COUNTER} = "$num";
+ validate_patch($r, $target_xfer_encoding);
+ $num += 1;
+ }
+ delete $ENV{GIT_SENDEMAIL_FILE_COUNTER};
+ delete $ENV{GIT_SENDEMAIL_FILE_TOTAL};
}
if (@files) {
* zlib wrappers to make sure we don't silently miss errors
* at init time.
*/
-#include "cache.h"
+#include "git-compat-util.h"
+#include "git-zlib.h"
static const char *zerr_to_string(int status)
{
--- /dev/null
+#ifndef GIT_ZLIB_H
+#define GIT_ZLIB_H
+
+typedef struct git_zstream {
+ z_stream z;
+ unsigned long avail_in;
+ unsigned long avail_out;
+ unsigned long total_in;
+ unsigned long total_out;
+ unsigned char *next_in;
+ unsigned char *next_out;
+} git_zstream;
+
+void git_inflate_init(git_zstream *);
+void git_inflate_init_gzip_only(git_zstream *);
+void git_inflate_end(git_zstream *);
+int git_inflate(git_zstream *, int flush);
+
+void git_deflate_init(git_zstream *, int level);
+void git_deflate_init_gzip(git_zstream *, int level);
+void git_deflate_init_raw(git_zstream *, int level);
+void git_deflate_end(git_zstream *);
+int git_deflate_abort(git_zstream *);
+int git_deflate_end_gently(git_zstream *);
+int git_deflate(git_zstream *, int flush);
+unsigned long git_deflate_bound(git_zstream *, unsigned long);
+
+#endif /* GIT_ZLIB_H */
#include "exec-cmd.h"
#include "gettext.h"
#include "help.h"
+#include "pager.h"
#include "run-command.h"
#include "alias.h"
#include "replace-object.h"
#include "setup.h"
#include "shallow.h"
+#include "trace.h"
+#include "trace2.h"
#define RUN_SETUP (1<<0)
#define RUN_SETUP_GENTLY (1<<1)
gpg_interface_lazy_init();
sigc->result = 'N';
- sigc->trust_level = -1;
+ sigc->trust_level = TRUST_UNDEFINED;
fmt = get_format_by_sig(signature);
if (!fmt)
#include "commit.h"
#include "quote.h"
#include "help.h"
+#include "wrapper.h"
static int grep_source_load(struct grep_source *gs);
static int grep_source_is_binary(struct grep_source *gs,
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
+#include "git-zlib.h"
#include "hex.h"
#include "repository.h"
#include "refs.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "exec-cmd.h"
#include "gettext.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "hex.h"
#include "repository.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "repository.h"
#include "commit.h"
#include "hex.h"
#include "version.h"
#include "pkt-line.h"
#include "gettext.h"
+#include "trace.h"
#include "transport.h"
#include "packfile.h"
#include "protocol.h"
#include "string-list.h"
+#include "object-file.h"
#include "object-store.h"
static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
#ifndef HTTP_H
#define HTTP_H
-#include "cache.h"
+struct packed_git;
+
+#include "git-zlib.h"
#include <curl/curl.h>
#include <curl/easy.h>
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "dir.h"
#include "gettext.h"
#include "list-objects-filter-options.h"
#include "oidmap.h"
#include "oidset.h"
+#include "object-name.h"
#include "object-store.h"
/* Remember to update object flag allocation in object.h */
-#include "cache.h"
+#include "git-compat-util.h"
#include "tag.h"
#include "commit.h"
#include "gettext.h"
#include "cache.h"
#include "config.h"
+#include "convert.h"
#include "attr.h"
#include "xdiff-interface.h"
#include "run-command.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "commit-reach.h"
#include "config.h"
#include "diff.h"
#include "environment.h"
#include "hex.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "tmp-objdir.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "string-list.h"
#include "mailmap.h"
+#include "object-name.h"
#include "object-store.h"
#include "setup.h"
struct string_list;
+extern const char *git_mailmap_file;
+extern const char *git_mailmap_blob;
+
int read_mailmap(struct string_list *map);
void clear_mailmap(struct string_list *map);
#include "hex.h"
#include "entry.h"
#include "ll-merge.h"
+#include "mem-pool.h"
+#include "object-name.h"
#include "object-store.h"
+#include "oid-array.h"
#include "promisor-remote.h"
#include "revision.h"
#include "strmap.h"
#include "submodule-config.h"
#include "submodule.h"
+#include "trace2.h"
#include "tree.h"
#include "unpack-trees.h"
#include "xdiff-interface.h"
void merge_finalize(struct merge_options *opt,
struct merge_result *result)
{
- struct merge_options_internal *opti = result->priv;
-
if (opt->renormalize)
git_attr_set_direction(GIT_ATTR_CHECKIN);
assert(opt->priv == NULL);
- clear_or_reinit_internal_opts(opti, 0);
- FREE_AND_NULL(opti);
+ if (result->priv) {
+ clear_or_reinit_internal_opts(result->priv, 0);
+ FREE_AND_NULL(result->priv);
+ }
}
/*** Function Grouping: helper functions for merge_incore_*() ***/
#include "hex.h"
#include "ll-merge.h"
#include "lockfile.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "revision.h"
#include "hex.h"
#include "lockfile.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
#include "hash-lookup.h"
#include "midx.h"
}
if (preferred_pack_name) {
- int found = 0;
+ ctx.preferred_pack_idx = -1;
+
for (i = 0; i < ctx.nr; i++) {
if (!cmp_idx_or_pack_name(preferred_pack_name,
ctx.info[i].pack_name)) {
ctx.preferred_pack_idx = i;
- found = 1;
break;
}
}
- if (!found)
+ if (ctx.preferred_pack_idx == -1)
warning(_("unknown preferred pack: '%s'"),
preferred_pack_name);
} else if (ctx.nr &&
#include "environment.h"
#include "gettext.h"
#include "thread-utils.h"
+#include "trace.h"
#include "trace2.h"
#include "sparse-index.h"
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
#include "commit.h"
#include "gettext.h"
#include "refs.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "diff.h"
#include "notes.h"
#include "notes-merge.h"
#include "strbuf.h"
+#include "trace.h"
#include "notes-utils.h"
#include "commit-reach.h"
#include "wrapper.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "environment.h"
#include "hex.h"
#include "notes.h"
+#include "object-name.h"
#include "object-store.h"
#include "blob.h"
#include "tree.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
+#include "convert.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "mergesort.h"
#include "quote.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
#include "promisor-remote.h"
#include "setup.h"
r->objects->loaded_alternates = 1;
}
+int has_alt_odb(struct repository *r)
+{
+ prepare_alt_odb(r);
+ return !!r->objects->odb->next;
+}
+
/* Returns 1 if we have successfully freshened the file, 0 otherwise. */
static int freshen_file(const char *fn)
{
--- /dev/null
+#ifndef OBJECT_FILE_H
+#define OBJECT_FILE_H
+
+#include "git-zlib.h"
+#include "object.h"
+
+/*
+ * Set this to 0 to prevent oid_object_info_extended() from fetching missing
+ * blobs. This has a difference only if extensions.partialClone is set.
+ *
+ * Its default value is 1.
+ */
+extern int fetch_if_missing;
+
+#define HASH_WRITE_OBJECT 1
+#define HASH_FORMAT_CHECK 2
+#define HASH_RENORMALIZE 4
+#define HASH_SILENT 8
+int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
+int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
+
+/*
+ * Create the directory containing the named path, using care to be
+ * somewhat safe against races. Return one of the scld_error values to
+ * indicate success/failure. On error, set errno to describe the
+ * problem.
+ *
+ * SCLD_VANISHED indicates that one of the ancestor directories of the
+ * path existed at one point during the function call and then
+ * suddenly vanished, probably because another process pruned the
+ * directory while we were working. To be robust against this kind of
+ * race, callers might want to try invoking the function again when it
+ * returns SCLD_VANISHED.
+ *
+ * safe_create_leading_directories() temporarily changes path while it
+ * is working but restores it before returning.
+ * safe_create_leading_directories_const() doesn't modify path, even
+ * temporarily. Both these variants adjust the permissions of the
+ * created directories to honor core.sharedRepository, so they are best
+ * suited for files inside the git dir. For working tree files, use
+ * safe_create_leading_directories_no_share() instead, as it ignores
+ * the core.sharedRepository setting.
+ */
+enum scld_error {
+ SCLD_OK = 0,
+ SCLD_FAILED = -1,
+ SCLD_PERMS = -2,
+ SCLD_EXISTS = -3,
+ SCLD_VANISHED = -4
+};
+enum scld_error safe_create_leading_directories(char *path);
+enum scld_error safe_create_leading_directories_const(const char *path);
+enum scld_error safe_create_leading_directories_no_share(char *path);
+
+int mkdir_in_gitdir(const char *path);
+
+int git_open_cloexec(const char *name, int flags);
+#define git_open(name) git_open_cloexec(name, O_RDONLY)
+
+/**
+ * unpack_loose_header() initializes the data stream needed to unpack
+ * a loose object header.
+ *
+ * Returns:
+ *
+ * - ULHR_OK on success
+ * - ULHR_BAD on error
+ * - ULHR_TOO_LONG if the header was too long
+ *
+ * It will only parse up to MAX_HEADER_LEN bytes unless an optional
+ * "hdrbuf" argument is non-NULL. This is intended for use with
+ * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error)
+ * reporting. The full header will be extracted to "hdrbuf" for use
+ * with parse_loose_header(), ULHR_TOO_LONG will still be returned
+ * from this function to indicate that the header was too long.
+ */
+enum unpack_loose_header_result {
+ ULHR_OK,
+ ULHR_BAD,
+ ULHR_TOO_LONG,
+};
+enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
+ unsigned char *map,
+ unsigned long mapsize,
+ void *buffer,
+ unsigned long bufsiz,
+ struct strbuf *hdrbuf);
+
+/**
+ * parse_loose_header() parses the starting "<type> <len>\0" of an
+ * object. If it doesn't follow that format -1 is returned. To check
+ * the validity of the <type> populate the "typep" in the "struct
+ * object_info". It will be OBJ_BAD if the object type is unknown. The
+ * parsed <len> can be retrieved via "oi->sizep", and from there
+ * passed to unpack_loose_rest().
+ */
+struct object_info;
+int parse_loose_header(const char *hdr, struct object_info *oi);
+
+/**
+ * With in-core object data in "buf", rehash it to make sure the
+ * object name actually matches "oid" to detect object corruption.
+ *
+ * A negative value indicates an error, usually that the OID is not
+ * what we expected, but it might also indicate another error.
+ */
+int check_object_signature(struct repository *r, const struct object_id *oid,
+ void *map, unsigned long size,
+ enum object_type type);
+
+/**
+ * A streaming version of check_object_signature().
+ * Try reading the object named with "oid" using
+ * the streaming interface and rehash it to do the same.
+ */
+int stream_object_signature(struct repository *r, const struct object_id *oid);
+
+int finalize_object_file(const char *tmpfile, const char *filename);
+
+/* Helper to check and "touch" a file */
+int check_and_freshen_file(const char *fn, int freshen);
+
+void *read_object_with_reference(struct repository *r,
+ const struct object_id *oid,
+ enum object_type required_type,
+ unsigned long *size,
+ struct object_id *oid_ret);
+
+#endif /* OBJECT_FILE_H */
#include "cache.h"
+#include "object-name.h"
+#include "advice.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
--- /dev/null
+#ifndef OBJECT_NAME_H
+#define OBJECT_NAME_H
+
+#include "object.h"
+#include "strbuf.h"
+
+struct object_id;
+struct repository;
+
+struct object_context {
+ unsigned short mode;
+ /*
+ * symlink_path is only used by get_tree_entry_follow_symlinks,
+ * and only for symlinks that point outside the repository.
+ */
+ struct strbuf symlink_path;
+ /*
+ * If GET_OID_RECORD_PATH is set, this will record path (if any)
+ * found when resolving the name. The caller is responsible for
+ * releasing the memory.
+ */
+ char *path;
+};
+
+/*
+ * Return an abbreviated sha1 unique within this repository's object database.
+ * The result will be at least `len` characters long, and will be NUL
+ * terminated.
+ *
+ * The non-`_r` version returns a static buffer which remains valid until 4
+ * more calls to repo_find_unique_abbrev are made.
+ *
+ * The `_r` variant writes to a buffer supplied by the caller, which must be at
+ * least `GIT_MAX_HEXSZ + 1` bytes. The return value is the number of bytes
+ * written (excluding the NUL terminator).
+ *
+ * Note that while this version avoids the static buffer, it is not fully
+ * reentrant, as it calls into other non-reentrant git code.
+ */
+const char *repo_find_unique_abbrev(struct repository *r, const struct object_id *oid, int len);
+int repo_find_unique_abbrev_r(struct repository *r, char *hex, const struct object_id *oid, int len);
+
+int repo_get_oid(struct repository *r, const char *str, struct object_id *oid);
+__attribute__((format (printf, 2, 3)))
+int get_oidf(struct object_id *oid, const char *fmt, ...);
+int repo_get_oid_commit(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_committish(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_tree(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_treeish(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_blob(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_mb(struct repository *r, const char *str, struct object_id *oid);
+void maybe_die_on_misspelt_object_name(struct repository *repo,
+ const char *name,
+ const char *prefix);
+enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
+ unsigned flags, struct object_id *oid,
+ struct object_context *oc);
+
+
+typedef int each_abbrev_fn(const struct object_id *oid, void *);
+int repo_for_each_abbrev(struct repository *r, const char *prefix, each_abbrev_fn, void *);
+
+int set_disambiguate_hint_config(const char *var, const char *value);
+
+/*
+ * This reads short-hand syntax that not only evaluates to a commit
+ * object name, but also can act as if the end user spelled the name
+ * of the branch from the command line.
+ *
+ * - "@{-N}" finds the name of the Nth previous branch we were on, and
+ * places the name of the branch in the given buf and returns the
+ * number of characters parsed if successful.
+ *
+ * - "<branch>@{upstream}" finds the name of the other ref that
+ * <branch> is configured to merge with (missing <branch> defaults
+ * to the current branch), and places the name of the branch in the
+ * given buf and returns the number of characters parsed if
+ * successful.
+ *
+ * If the input is not of the accepted format, it returns a negative
+ * number to signal an error.
+ *
+ * If the input was ok but there are not N branch switches in the
+ * reflog, it returns 0.
+ */
+#define INTERPRET_BRANCH_LOCAL (1<<0)
+#define INTERPRET_BRANCH_REMOTE (1<<1)
+#define INTERPRET_BRANCH_HEAD (1<<2)
+struct interpret_branch_name_options {
+ /*
+ * If "allowed" is non-zero, it is a treated as a bitfield of allowable
+ * expansions: local branches ("refs/heads/"), remote branches
+ * ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
+ * allowed, even ones to refs outside of those namespaces.
+ */
+ unsigned allowed;
+
+ /*
+ * If ^{upstream} or ^{push} (or equivalent) is requested, and the
+ * branch in question does not have such a reference, return -1 instead
+ * of die()-ing.
+ */
+ unsigned nonfatal_dangling_mark : 1;
+};
+int repo_interpret_branch_name(struct repository *r,
+ const char *str, int len,
+ struct strbuf *buf,
+ const struct interpret_branch_name_options *options);
+
+struct object *repo_peel_to_type(struct repository *r,
+ const char *name, int namelen,
+ struct object *o, enum object_type);
+
+/* Convert to/from hex/sha1 representation */
+#define MINIMUM_ABBREV minimum_abbrev
+#define DEFAULT_ABBREV default_abbrev
+
+/* used when the code does not know or care what the default abbrev is */
+#define FALLBACK_DEFAULT_ABBREV 7
+
+#endif /* OBJECT_NAME_H */
struct object_directory *, 1, fspathhash, fspatheq)
void prepare_alt_odb(struct repository *r);
+int has_alt_odb(struct repository *r);
char *compute_alternate_path(const char *path, struct strbuf *err);
struct object_directory *find_odb(struct repository *r, const char *obj_dir);
typedef int alt_odb_fn(struct object_directory *, void *);
#include "hex.h"
#include "object.h"
#include "replace-object.h"
+#include "object-file.h"
#include "object-store.h"
#include "blob.h"
#include "tree.h"
OBJ_MAX
};
+/* unknown mode (impossible combination S_IFIFO|S_IFCHR) */
+#define S_IFINVALID 0030000
+
+/*
+ * A "directory link" is a link to another git directory.
+ *
+ * The value 0160000 is not normally a valid mode, and
+ * also just happens to be S_IFDIR + S_IFLNK
+ */
+#define S_IFGITLINK 0160000
+#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
+
+#define S_ISSPARSEDIR(m) ((m) == S_IFDIR)
+
+static inline enum object_type object_type(unsigned int mode)
+{
+ return S_ISDIR(mode) ? OBJ_TREE :
+ S_ISGITLINK(mode) ? OBJ_COMMIT :
+ OBJ_BLOB;
+}
+
+#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
+static inline unsigned int create_ce_mode(unsigned int mode)
+{
+ if (S_ISLNK(mode))
+ return S_IFLNK;
+ if (S_ISSPARSEDIR(mode))
+ return S_IFDIR;
+ if (S_ISDIR(mode) || S_ISGITLINK(mode))
+ return S_IFGITLINK;
+ return S_IFREG | ce_permissions(mode);
+}
+
+static inline unsigned int canon_mode(unsigned int mode)
+{
+ if (S_ISREG(mode))
+ return S_IFREG | ce_permissions(mode);
+ if (S_ISLNK(mode))
+ return S_IFLNK;
+ if (S_ISDIR(mode))
+ return S_IFDIR;
+ return S_IFGITLINK;
+}
+
/*
* The object type is stored in 3 bits.
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "environment.h"
#include "gettext.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "commit.h"
#include "gettext.h"
#include "pack-objects.h"
#include "packfile.h"
#include "repository.h"
+#include "trace2.h"
+#include "object-file.h"
#include "object-store.h"
#include "list-objects-filter-options.h"
#include "midx.h"
goto cleanup;
}
- if (load_midx_revindex(bitmap_git->midx) < 0) {
+ if (load_midx_revindex(bitmap_git->midx)) {
warning(_("multi-pack bitmap is missing required reverse index"));
goto cleanup;
}
return 0;
}
-static int load_reverse_index(struct bitmap_index *bitmap_git)
+static int load_reverse_index(struct repository *r, struct bitmap_index *bitmap_git)
{
if (bitmap_is_midx(bitmap_git)) {
uint32_t i;
* since we will need to make use of them in pack-objects.
*/
for (i = 0; i < bitmap_git->midx->num_packs; i++) {
- ret = load_pack_revindex(bitmap_git->midx->packs[i]);
+ ret = load_pack_revindex(r, bitmap_git->midx->packs[i]);
if (ret)
return ret;
}
return 0;
}
- return load_pack_revindex(bitmap_git->pack);
+ return load_pack_revindex(r, bitmap_git->pack);
}
-static int load_bitmap(struct bitmap_index *bitmap_git)
+static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git)
{
assert(bitmap_git->map);
bitmap_git->bitmaps = kh_init_oid_map();
bitmap_git->ext_index.positions = kh_init_oid_pos();
- if (load_reverse_index(bitmap_git))
+ if (load_reverse_index(r, bitmap_git))
goto failed;
if (!(bitmap_git->commits = read_bitmap_1(bitmap_git)) ||
{
struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
- if (!open_bitmap(r, bitmap_git) && !load_bitmap(bitmap_git))
+ if (!open_bitmap(r, bitmap_git) && !load_bitmap(r, bitmap_git))
return bitmap_git;
free_bitmap_index(bitmap_git);
struct bitmap_index *prepare_midx_bitmap_git(struct multi_pack_index *midx)
{
+ struct repository *r = the_repository;
struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
- if (!open_midx_bitmap_1(bitmap_git, midx) && !load_bitmap(bitmap_git))
+ if (!open_midx_bitmap_1(bitmap_git, midx) && !load_bitmap(r, bitmap_git))
return bitmap_git;
free_bitmap_index(bitmap_git);
* from disk. this is the point of no return; after this the rev_list
* becomes invalidated and we must perform the revwalk through bitmaps
*/
- if (load_bitmap(bitmap_git) < 0)
+ if (load_bitmap(revs->repo, bitmap_git) < 0)
goto cleanup;
object_array_clear(&revs->pending);
uint32_t *entries,
struct bitmap **reuse_out)
{
+ struct repository *r = the_repository;
struct packed_git *pack;
struct bitmap *result = bitmap_git->result;
struct bitmap *reuse;
assert(result);
- load_reverse_index(bitmap_git);
+ load_reverse_index(r, bitmap_git);
if (bitmap_is_midx(bitmap_git))
pack = bitmap_git->midx->packs[midx_preferred_pack(bitmap_git)];
uint32_t *create_bitmap_mapping(struct bitmap_index *bitmap_git,
struct packing_data *mapping)
{
+ struct repository *r = the_repository;
uint32_t i, num_objects;
uint32_t *reposition;
if (!bitmap_is_midx(bitmap_git))
- load_reverse_index(bitmap_git);
- else if (load_midx_revindex(bitmap_git->midx) < 0)
+ load_reverse_index(r, bitmap_git);
+ else if (load_midx_revindex(bitmap_git->midx))
BUG("rebuild_existing_bitmaps: missing required rev-cache "
"extension");
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "hex.h"
#include "repository.h"
#include "pack-revindex.h"
#include "progress.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
struct idx_entry {
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "pack-mtimes.h"
+#include "object-file.h"
#include "object-store.h"
#include "packfile.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "pack-revindex.h"
+#include "object-file.h"
#include "object-store.h"
#include "packfile.h"
+#include "trace2.h"
#include "config.h"
#include "midx.h"
+#include "csum-file.h"
struct revindex_entry {
off_t offset;
size_t revindex_size;
struct revindex_header *hdr;
+ if (git_env_bool(GIT_TEST_REV_INDEX_DIE_ON_DISK, 0))
+ die("dying as requested by '%s'", GIT_TEST_REV_INDEX_DIE_ON_DISK);
+
fd = git_open(revindex_name);
if (fd < 0) {
- ret = -1;
+ /* "No file" means return 1. */
+ ret = 1;
goto cleanup;
}
if (fstat(fd, &st)) {
return ret;
}
-static int load_pack_revindex_from_disk(struct packed_git *p)
+int load_pack_revindex_from_disk(struct packed_git *p)
{
char *revindex_name;
int ret;
return ret;
}
-int load_pack_revindex(struct packed_git *p)
+int load_pack_revindex(struct repository *r, struct packed_git *p)
{
if (p->revindex || p->revindex_data)
return 0;
- if (!load_pack_revindex_from_disk(p))
+ prepare_repo_settings(r);
+
+ if (r->settings.pack_read_reverse_index &&
+ !load_pack_revindex_from_disk(p))
return 0;
else if (!create_pack_revindex_in_memory(p))
return 0;
return -1;
}
+/*
+ * verify_pack_revindex verifies that the on-disk rev-index for the given
+ * pack-file is the same that would be created if written from scratch.
+ *
+ * A negative number is returned on error.
+ */
+int verify_pack_revindex(struct packed_git *p)
+{
+ int res = 0;
+
+ /* Do not bother checking if not initialized. */
+ if (!p->revindex_map || !p->revindex_data)
+ return res;
+
+ if (!hashfile_checksum_valid((const unsigned char *)p->revindex_map, p->revindex_size)) {
+ error(_("invalid checksum"));
+ res = -1;
+ }
+
+ /* This may fail due to a broken .idx. */
+ if (create_pack_revindex_in_memory(p))
+ return res;
+
+ for (size_t i = 0; i < p->num_objects; i++) {
+ uint32_t nr = p->revindex[i].nr;
+ uint32_t rev_val = get_be32(p->revindex_data + i);
+
+ if (nr != rev_val) {
+ error(_("invalid rev-index position at %"PRIu64": %"PRIu32" != %"PRIu32""),
+ (uint64_t)i, nr, rev_val);
+ res = -1;
+ }
+ }
+
+ return res;
+}
+
int load_midx_revindex(struct multi_pack_index *m)
{
struct strbuf revindex_name = STRBUF_INIT;
{
unsigned lo, hi;
- if (load_pack_revindex(p) < 0)
+ if (load_pack_revindex(the_repository, p) < 0)
return -1;
lo = 0;
#define RIDX_SIGNATURE 0x52494458 /* "RIDX" */
#define RIDX_VERSION 1
-#define GIT_TEST_WRITE_REV_INDEX "GIT_TEST_WRITE_REV_INDEX"
+#define GIT_TEST_NO_WRITE_REV_INDEX "GIT_TEST_NO_WRITE_REV_INDEX"
#define GIT_TEST_REV_INDEX_DIE_IN_MEMORY "GIT_TEST_REV_INDEX_DIE_IN_MEMORY"
+#define GIT_TEST_REV_INDEX_DIE_ON_DISK "GIT_TEST_REV_INDEX_DIE_ON_DISK"
struct packed_git;
struct multi_pack_index;
+struct repository;
/*
* load_pack_revindex populates the revindex's internal data-structures for the
* If a '.rev' file is present it is mmap'd, and pointers are assigned into it
* (instead of using the in-memory variant).
*/
-int load_pack_revindex(struct packed_git *p);
+int load_pack_revindex(struct repository *r, struct packed_git *p);
+
+/*
+ * Specifically load a pack revindex from disk.
+ *
+ * Returns 0 on success, 1 on "no .rev file", and -1 when there is an
+ * error parsing the .rev file.
+ */
+int load_pack_revindex_from_disk(struct packed_git *p);
+
+/*
+ * verify_pack_revindex verifies that the on-disk rev-index for the given
+ * pack-file is the same that would be created if written from scratch.
+ *
+ * A negative number is returned on error.
+ */
+int verify_pack_revindex(struct packed_git *p);
/*
* load_midx_revindex loads the '.rev' file corresponding to the given
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "pack-mtimes.h"
#include "oidmap.h"
#include "pack-objects.h"
+#include "pack-revindex.h"
+#include "wrapper.h"
void reset_pack_idx_option(struct pack_idx_option *opts)
{
hashwrite(f, hash, the_hash_algo->rawsz);
}
-static const char *write_mtimes_file(struct packing_data *to_pack,
- struct pack_idx_entry **objects,
- uint32_t nr_objects,
- const unsigned char *hash)
+static char *write_mtimes_file(struct packing_data *to_pack,
+ struct pack_idx_entry **objects,
+ uint32_t nr_objects,
+ const unsigned char *hash)
{
struct strbuf tmp_file = STRBUF_INIT;
- const char *mtimes_name;
+ char *mtimes_name;
struct hashfile *f;
int fd;
char **idx_tmp_name)
{
const char *rev_tmp_name = NULL;
- const char *mtimes_tmp_name = NULL;
+ char *mtimes_tmp_name = NULL;
if (adjust_shared_perm(pack_tmp_name))
die_errno("unable to make temporary pack file readable");
rename_tmp_packfile(name_buffer, rev_tmp_name, "rev");
if (mtimes_tmp_name)
rename_tmp_packfile(name_buffer, mtimes_tmp_name, "mtimes");
+
+ free((char *)rev_tmp_name);
+ free(mtimes_tmp_name);
}
void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought)
#include "commit.h"
#include "object.h"
#include "tag.h"
+#include "trace.h"
#include "tree-walk.h"
#include "tree.h"
+#include "object-file.h"
#include "object-store.h"
#include "midx.h"
#include "commit-graph.h"
+#include "pack-revindex.h"
#include "promisor-remote.h"
#include "wrapper.h"
int r = 0;
if (flags & FOR_EACH_OBJECT_PACK_ORDER) {
- if (load_pack_revindex(p))
+ if (load_pack_revindex(the_repository, p))
return -1;
}
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
+#include "editor.h"
+#include "pager.h"
#include "run-command.h"
#include "sigchain.h"
#include "alias.h"
+int pager_use_color = 1;
+
#ifndef DEFAULT_PAGER
#define DEFAULT_PAGER "less"
#endif
--- /dev/null
+#ifndef PAGER_H
+#define PAGER_H
+
+struct child_process;
+
+const char *git_pager(int stdout_is_tty);
+void setup_pager(void);
+int pager_in_use(void);
+int term_columns(void);
+void term_clear_line(void);
+int decimal_width(uintmax_t);
+int check_pager_config(const char *cmd);
+void prepare_pager_args(struct child_process *, const char *pager);
+
+extern int pager_use_color;
+
+#endif /* PAGER_H */
#include "git-compat-util.h"
#include "parse-options.h"
#include "branch.h"
-#include "cache.h"
#include "commit.h"
#include "color.h"
#include "environment.h"
#include "gettext.h"
+#include "object-name.h"
#include "string-list.h"
#include "strvec.h"
#include "oid-array.h"
#include "object-store.h"
#include "lockfile.h"
#include "exec-cmd.h"
+#include "wrapper.h"
static int get_st_mode_bits(const char *path, int *mode)
{
#include "gettext.h"
#include "hex.h"
#include "run-command.h"
+#include "trace.h"
#include "wrapper.h"
#include "write-or-die.h"
#include "progress.h"
#include "thread-utils.h"
#include "repository.h"
+#include "trace2.h"
/*
* Mostly randomly chosen maximum thread counts: we
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "config.h"
#include "commit.h"
#include "hex.h"
#include "utf8.h"
#include "diff.h"
+#include "pager.h"
#include "revision.h"
#include "string-list.h"
#include "mailmap.h"
*/
#define GIT_TEST_PROGRESS_ONLY
-#include "cache.h"
+#include "git-compat-util.h"
+#include "pager.h"
#include "progress.h"
#include "strbuf.h"
#include "trace.h"
+#include "trace2.h"
#include "utf8.h"
#include "config.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "hex.h"
#include "object-store.h"
#include "promisor-remote.h"
#include "config.h"
+#include "trace2.h"
#include "transport.h"
#include "strvec.h"
#include "packfile.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "environment.h"
#include "protocol.h"
+#include "trace2.h"
static enum protocol_version parse_protocol_version(const char *value)
{
#ifndef PROTOCOL_H
#define PROTOCOL_H
+/*
+ * Intensive research over the course of many years has shown that
+ * port 9418 is totally unused by anything else. Or
+ *
+ * Your search - "port 9418" - did not match any documents.
+ *
+ * as www.google.com puts it.
+ *
+ * This port has been properly assigned for git use by IANA:
+ * git (Assigned-9418) [I06-050728-0001].
+ *
+ * git 9418/tcp git pack transfer service
+ * git 9418/udp git pack transfer service
+ *
+ * with Linus Torvalds <torvalds@osdl.org> as the point of
+ * contact. September 2005.
+ *
+ * See http://www.iana.org/assignments/port-numbers
+ */
+#define DEFAULT_GIT_PORT 9418
+
enum protocol_version {
protocol_unknown_version = -1,
protocol_v0 = 0,
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
+#include "path.h"
#include "quote.h"
#include "strbuf.h"
#include "strvec.h"
struct strbuf;
+extern int quote_path_fully;
+
/* Help to copy the thing properly quoted for the shell safety.
* any single quote is replaced with '\'', any exclamation point
* is replaced with '\!', and the whole thing is enclosed in a
#include "environment.h"
#include "gettext.h"
#include "range-diff.h"
+#include "object-name.h"
#include "string-list.h"
#include "run-command.h"
#include "strvec.h"
#include "linear-assignment.h"
#include "diffcore.h"
#include "commit.h"
+#include "pager.h"
#include "pretty.h"
#include "userdiff.h"
#include "apply.h"
#include "cache-tree.h"
#include "refs.h"
#include "dir.h"
+#include "object-file.h"
#include "object-store.h"
+#include "oid-array.h"
#include "tree.h"
#include "commit.h"
#include "blob.h"
#include "environment.h"
#include "gettext.h"
+#include "mem-pool.h"
+#include "object-name.h"
#include "resolve-undo.h"
#include "run-command.h"
#include "strbuf.h"
+#include "trace2.h"
#include "varint.h"
#include "split-index.h"
#include "utf8.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "commit.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
#include "sequencer.h"
#include "commit-slab.h"
#include "config.h"
#include "dir.h"
+#include "object-name.h"
#include "wrapper.h"
static const char edit_todo_list_advice[] =
#include "parse-options.h"
#include "refs.h"
#include "wildmatch.h"
+#include "object-name.h"
#include "object-store.h"
+#include "oid-array.h"
#include "repository.h"
#include "commit.h"
#include "remote.h"
* The backend-independent part of the reference module.
*/
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
#include "refs/refs-internal.h"
#include "run-command.h"
#include "hook.h"
+#include "object-name.h"
#include "object-store.h"
#include "object.h"
#include "tag.h"
#include "../dir-iterator.h"
#include "../lockfile.h"
#include "../object.h"
+#include "../object-file.h"
#include "../dir.h"
#include "../chdir-notify.h"
#include "../setup.h"
#include "../iterator.h"
#include "../lockfile.h"
#include "../chdir-notify.h"
+#include "../wrapper.h"
#include "../write-or-die.h"
enum mmap_strategy {
#ifndef REFS_REF_CACHE_H
#define REFS_REF_CACHE_H
-#include "cache.h"
+#include "hash.h"
struct ref_dir;
struct ref_store;
#include "setup.h"
#include "protocol.h"
#include "quote.h"
+#include "trace2.h"
#include "transport.h"
#include "write-or-die.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
#include "urlmatch.h"
#include "refs.h"
#include "refspec.h"
+#include "object-name.h"
#include "object-store.h"
#include "commit.h"
#include "diff.h"
repo_cfg_bool(r, "feature.experimental", &experimental, 0);
/* Defaults modified by feature.* */
- if (experimental) {
+ if (experimental)
r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_SKIPPING;
- r->settings.gc_cruft_packs = 1;
- }
if (manyfiles) {
r->settings.index_version = 4;
r->settings.index_skip_hash = 1;
repo_cfg_bool(r, "core.multipackindex", &r->settings.core_multi_pack_index, 1);
repo_cfg_bool(r, "index.sparse", &r->settings.sparse_index, 0);
repo_cfg_bool(r, "index.skiphash", &r->settings.index_skip_hash, r->settings.index_skip_hash);
+ repo_cfg_bool(r, "pack.readreverseindex", &r->settings.pack_read_reverse_index, 1);
/*
* The GIT_TEST_MULTI_PACK_INDEX variable is special in that
#include "setup.h"
#include "submodule-config.h"
#include "sparse-index.h"
+#include "trace2.h"
#include "promisor-remote.h"
/* The main repository */
int commit_graph_generation_version;
int commit_graph_read_changed_paths;
int gc_write_commit_graph;
- int gc_cruft_packs;
int fetch_write_commit_graph;
int command_requires_full_index;
int sparse_index;
+ int pack_read_reverse_index;
struct fsmonitor_settings *fsmonitor; /* lazily loaded */
-#include "git-compat-util.h"
+#include "cache.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
#include "ll-merge.h"
#include "attr.h"
#include "pathspec.h"
+#include "object-file.h"
#include "object-store.h"
#include "hash-lookup.h"
#include "strmap.h"
#include "gettext.h"
#include "hex.h"
#include "lockfile.h"
+#include "object-name.h"
#include "refs.h"
#include "reset.h"
#include "run-command.h"
#ifndef RESOLVE_UNDO_H
#define RESOLVE_UNDO_H
-#include "cache.h"
+struct cache_entry;
+struct index_state;
+struct pathspec;
+struct string_list;
+
+#include "hash.h"
struct resolve_undo_info {
unsigned int mode[3];
-#include "git-compat-util.h"
+#include "cache.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
+#include "object-file.h"
#include "object-store.h"
#include "tag.h"
#include "blob.h"
#include "worktree.h"
#include "setup.h"
#include "strvec.h"
+#include "trace2.h"
#include "commit-reach.h"
#include "commit-graph.h"
#include "prio-queue.h"
#include "thread-utils.h"
#include "strbuf.h"
#include "string-list.h"
+#include "trace.h"
+#include "trace2.h"
#include "quote.h"
#include "config.h"
#include "packfile.h"
* The Scalar command-line interface.
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "gettext.h"
#include "parse-options.h"
#include "packfile.h"
#include "help.h"
#include "setup.h"
+#include "trace2.h"
static void setup_enlistment_directory(int argc, const char **argv,
const char * const *usagestr,
#include "quote.h"
#include "transport.h"
#include "version.h"
+#include "wrapper.h"
#include "oid-array.h"
#include "gpg-interface.h"
#include "shallow.h"
die(_("the receiving end does not support this repository's hash algorithm"));
if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) {
- int len;
+ size_t len;
push_cert_nonce = server_feature_value("push-cert", &len);
if (push_cert_nonce) {
reject_invalid_nonce(push_cert_nonce, len);
#include "cache.h"
#include "abspath.h"
+#include "advice.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
#include "hex.h"
#include "lockfile.h"
#include "dir.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "object.h"
+#include "pager.h"
#include "commit.h"
#include "sequencer.h"
#include "tag.h"
#include "commit.h"
#include "tag.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
#include "strbuf.h"
#include "wrapper.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "environment.h"
#include "gettext.h"
+#include "object-name.h"
#include "repository.h"
#include "config.h"
#include "dir.h"
#include "chdir-notify.h"
#include "promisor-remote.h"
#include "quote.h"
+#include "trace2.h"
+#include "wrapper.h"
static int inside_git_dir = -1;
static int inside_work_tree = -1;
#include "list-objects.h"
#include "commit-reach.h"
#include "shallow.h"
+#include "trace.h"
#include "wrapper.h"
void set_alternate_shallow_file(struct repository *r, const char *path, int override)
-#include "cache.h"
+#include "git-compat-util.h"
#include "color.h"
#include "config.h"
+#include "editor.h"
#include "gettext.h"
#include "sideband.h"
#include "help.h"
#include "cache.h"
#include "alloc.h"
#include "gettext.h"
+#include "mem-pool.h"
#include "split-index.h"
#include "ewah/ewok.h"
#ifndef SPLIT_INDEX_H
#define SPLIT_INDEX_H
-#include "cache.h"
+#include "hash.h"
struct index_state;
struct strbuf;
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "alloc.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "refs.h"
#include "string-list.h"
#include "utf8.h"
return 0;
}
-int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
- const char *const *env)
-{
- char *path2 = NULL;
- int fd, res = 0;
-
- if (!is_absolute_path(path))
- path = path2 = xstrdup(git_path("%s", path));
-
- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
- if (fd < 0)
- res = error_errno(_("could not open '%s' for writing"), path);
- else if (write_in_full(fd, buffer->buf, buffer->len) < 0) {
- res = error_errno(_("could not write to '%s'"), path);
- close(fd);
- } else if (close(fd) < 0)
- res = error_errno(_("could not close '%s'"), path);
- else {
- strbuf_reset(buffer);
- if (launch_editor(path, buffer, env) < 0)
- res = error_errno(_("could not edit '%s'"), path);
- unlink(path);
- }
-
- free(path2);
- return res;
-}
-
void strbuf_strip_file_from_path(struct strbuf *sb)
{
char *path_sep = find_last_dir_sep(sb->buf);
void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid,
int abbrev_len);
-/**
- * Launch the user preferred editor to edit a file and fill the buffer
- * with the file's contents upon the user completing their editing. The
- * third argument can be used to set the environment which the editor is
- * run in. If the buffer is NULL the editor is launched as usual but the
- * file's contents are not read into the buffer upon completion.
- */
-int launch_editor(const char *path, struct strbuf *buffer,
- const char *const *env);
-
-int launch_sequence_editor(const char *path, struct strbuf *buffer,
- const char *const *env);
-
-/*
- * In contrast to `launch_editor()`, this function writes out the contents
- * of the specified file first, then clears the `buffer`, then launches
- * the editor and reads back in the file contents into the `buffer`.
- * Finally, it deletes the temporary file.
- *
- * If `path` is relative, it refers to a file in the `.git` directory.
- */
-int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
- const char *const *env);
-
/*
* Remove the filename from the provided path string. If the path
* contains a trailing separator, then the path is considered a directory
/*
* Copyright (c) 2011, Google Inc.
*/
-#include "cache.h"
+#include "git-compat-util.h"
+#include "convert.h"
#include "environment.h"
#include "streaming.h"
#include "repository.h"
+#include "object-file.h"
#include "object-store.h"
#include "replace-object.h"
#include "packfile.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "dir.h"
#include "environment.h"
#include "submodule-config.h"
#include "submodule.h"
#include "strbuf.h"
+#include "object-name.h"
#include "object-store.h"
#include "parse-options.h"
#include "tree-walk.h"
#include "remote.h"
#include "worktree.h"
#include "parse-options.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "commit-reach.h"
#include "setup.h"
#include "shallow.h"
+#include "trace2.h"
static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF;
static int initialized_fetch_ref_tips;
use in the test scripts. Recognized values for <hash-algo> are "sha1"
and "sha256".
-GIT_TEST_WRITE_REV_INDEX=<boolean>, when true enables the
+GIT_TEST_NO_WRITE_REV_INDEX=<boolean>, when true disables the
'pack.writeReverseIndex' setting.
GIT_TEST_SPARSE_INDEX=<boolean>, when true enables index writes to use the
if (timespec_arg(argv[i], &set_time, &set_eq)) {
++i;
} else {
- if (get == 0) {
+ if (get == 0 && verbose == 0) {
fprintf(stderr, "Not a base-10 integer: %s\n", argv[i] + 1);
goto usage;
}
#include "test-tool.h"
-#include "cache.h"
#include "date.h"
+#include "trace.h"
static const char *usage_msg = "\n"
" test-tool date relative [time_t]...\n"
#include "hex.h"
#include "lockfile.h"
#include "merge-ort.h"
+#include "object-name.h"
#include "refs.h"
#include "revision.h"
#include "sequencer.h"
#include "environment.h"
#include "parse-options.h"
#include "setup.h"
+#include "trace.h"
static int single;
static int multi;
#include "test-tool.h"
#include "cache.h"
#include "hex.h"
+#include "object-name.h"
#include "setup.h"
#include "tree.h"
#include "test-tool.h"
#include "cache.h"
+#include "mem-pool.h"
#include "mergesort.h"
static uint32_t minstd_rand(uint32_t *state)
#include "test-tool.h"
-#include "cache.h"
#include "hex.h"
+#include "object-name.h"
#include "oidmap.h"
#include "setup.h"
#include "strbuf.h"
#include "environment.h"
#include "setup.h"
#include "string-list.h"
+#include "trace.h"
#include "utf8.h"
/*
#include "test-tool.h"
-#include "cache.h"
#include "alloc.h"
#include "commit.h"
#include "commit-reach.h"
#include "config.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "ref-filter.h"
#include "setup.h"
#include "test-tool.h"
-#include "cache.h"
#include "config.h"
+#include "object-name.h"
#include "setup.h"
#include "submodule-config.h"
#include "submodule.h"
test_perf_large_repo
test_expect_success 'setup bitmap config' '
- git config pack.writebitmaps true &&
- git config pack.writeReverseIndex true
+ git config pack.writebitmaps true
'
# we need to create the tag up front such that it is covered by the repack and
test_must_fail git config --rename-section branch.zwei "bogus name"
'
+test_expect_success 'renaming a section with a long line' '
+ {
+ printf "[b]\\n" &&
+ printf " c = d %1024s [a] e = f\\n" " " &&
+ printf "[a] g = h\\n"
+ } >y &&
+ git config -f y --rename-section a xyz &&
+ test_must_fail git config -f y b.e
+'
+
+test_expect_success 'renaming an embedded section with a long line' '
+ {
+ printf "[b]\\n" &&
+ printf " c = d %1024s [a] [foo] e = f\\n" " " &&
+ printf "[a] g = h\\n"
+ } >y &&
+ git config -f y --rename-section a xyz &&
+ test_must_fail git config -f y foo.e
+'
+
+test_expect_success 'renaming a section with an overly-long line' '
+ {
+ printf "[b]\\n" &&
+ printf " c = d %525000s e" " " &&
+ printf "[a] g = h\\n"
+ } >y &&
+ test_must_fail git config -f y --rename-section a xyz 2>err &&
+ grep "refusing to work with overly long line in .y. on line 2" err
+'
+
cat >> .git/config << EOF
[branch "zwei"] a = 1 [branch "vier"]
EOF
test_path_is_file .git/delete-me
'
+test_expect_success SYMLINKS '--reject removes .rej symlink if it exists' '
+ test_when_finished "git reset --hard && git clean -dfx" &&
+
+ test_commit file &&
+ echo modified >file.t &&
+ git diff -- file.t >patch &&
+ echo modified-again >file.t &&
+
+ ln -s foo file.t.rej &&
+ test_must_fail git apply patch --reject 2>err &&
+ test_i18ngrep "Rejected hunk" err &&
+ test_path_is_missing foo &&
+ test_path_is_file file.t.rej
+'
+
test_done
test_line_count = 1 donelines
'
-test_expect_success 'setup for --stdin-packs tests' '
- git init stdin-packs &&
- (
- cd stdin-packs &&
-
- test_commit A &&
- test_commit B &&
- test_commit C &&
-
- for id in A B C
- do
- git pack-objects .git/objects/pack/pack-$id \
- --incremental --revs <<-EOF || exit 1
- refs/tags/$id
- EOF
- done &&
-
- ls -la .git/objects/pack
- )
-'
-
-test_expect_success '--stdin-packs with excluded packs' '
- (
- cd stdin-packs &&
-
- PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
- PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
- PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
-
- git pack-objects test --stdin-packs <<-EOF &&
- $PACK_A
- ^$PACK_B
- $PACK_C
- EOF
-
- (
- git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-C-*.idx)
- ) >expect.raw &&
- git show-index <$(ls test-*.idx) >actual.raw &&
-
- cut -d" " -f2 <expect.raw | sort >expect &&
- cut -d" " -f2 <actual.raw | sort >actual &&
- test_cmp expect actual
- )
-'
-
-test_expect_success '--stdin-packs is incompatible with --filter' '
- (
- cd stdin-packs &&
- test_must_fail git pack-objects --stdin-packs --stdout \
- --filter=blob:none </dev/null 2>err &&
- test_i18ngrep "cannot use --filter with --stdin-packs" err
- )
-'
-
-test_expect_success '--stdin-packs is incompatible with --revs' '
- (
- cd stdin-packs &&
- test_must_fail git pack-objects --stdin-packs --revs out \
- </dev/null 2>err &&
- test_i18ngrep "cannot use internal rev list with --stdin-packs" err
- )
-'
-
-test_expect_success '--stdin-packs with loose objects' '
- (
- cd stdin-packs &&
-
- PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
- PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
- PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
-
- test_commit D && # loose
-
- git pack-objects test2 --stdin-packs --unpacked <<-EOF &&
- $PACK_A
- ^$PACK_B
- $PACK_C
- EOF
-
- (
- git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
- git rev-list --objects --no-object-names \
- refs/tags/C..refs/tags/D
-
- ) >expect.raw &&
- ls -la . &&
- git show-index <$(ls test2-*.idx) >actual.raw &&
-
- cut -d" " -f2 <expect.raw | sort >expect &&
- cut -d" " -f2 <actual.raw | sort >actual &&
- test_cmp expect actual
- )
-'
-
-test_expect_success '--stdin-packs with broken links' '
- (
- cd stdin-packs &&
-
- # make an unreachable object with a bogus parent
- git cat-file -p HEAD >commit &&
- sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit |
- git hash-object -w -t commit --stdin >in &&
-
- git pack-objects .git/objects/pack/pack-D <in &&
-
- PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
- PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
- PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
- PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" &&
-
- git pack-objects test3 --stdin-packs --unpacked <<-EOF &&
- $PACK_A
- ^$PACK_B
- $PACK_C
- $PACK_D
- EOF
-
- (
- git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-D-*.idx) &&
- git rev-list --objects --no-object-names \
- refs/tags/C..refs/tags/D
- ) >expect.raw &&
- git show-index <$(ls test3-*.idx) >actual.raw &&
-
- cut -d" " -f2 <expect.raw | sort >expect &&
- cut -d" " -f2 <actual.raw | sort >actual &&
- test_cmp expect actual
- )
-'
-
test_expect_success 'negative window clamps to 0' '
git pack-objects --progress --window=-1 neg-window <obj-list 2>stderr &&
check_deltas stderr = 0
test_expect_success 'gc: implicit prune --expire' '
add_blob &&
test-tool chmtime =-$((2*$week-30)) $BLOB_FILE &&
- git gc &&
+ git gc --no-cruft &&
verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
test-tool chmtime =-$((2*$week+1)) $BLOB_FILE &&
- git gc &&
+ git gc --no-cruft &&
verbose test $before = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc: start with ok gc.pruneExpire' '
git config gc.pruneExpire 2.days.ago &&
- git gc
+ git gc --no-cruft
'
test_expect_success 'prune: prune nonsense parameters' '
add_blob &&
test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
git config gc.pruneExpire 2.days.ago &&
- git gc --no-prune &&
+ git gc --no-prune --no-cruft &&
verbose test 1 = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE
'
test_expect_success 'gc respects gc.pruneExpire' '
git config gc.pruneExpire 5002.days.ago &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_file $BLOB_FILE &&
git config gc.pruneExpire 5000.days.ago &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc --prune=<date>' '
add_blob &&
test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
- git gc --prune=5002.days.ago &&
+ git gc --prune=5002.days.ago --no-cruft &&
test_path_is_file $BLOB_FILE &&
- git gc --prune=5000.days.ago &&
+ git gc --prune=5000.days.ago --no-cruft &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc --prune=never' '
add_blob &&
- git gc --prune=never &&
+ git gc --prune=never --no-cruft &&
test_path_is_file $BLOB_FILE &&
- git gc --prune=now &&
+ git gc --prune=now --no-cruft &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc respects gc.pruneExpire=never' '
git config gc.pruneExpire never &&
add_blob &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_file $BLOB_FILE &&
git config gc.pruneExpire now &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_missing $BLOB_FILE
'
cd aclone &&
verbose test 1 = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
- git gc --prune &&
+ git gc --prune --no-cruft &&
verbose test 0 = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
)
>.git/objects/pack/fake2.keep &&
>.git/objects/pack/fake2.idx &&
>.git/objects/pack/fake3.keep &&
- git gc &&
+ git gc --no-cruft &&
git count-objects -v 2>stderr &&
grep "^warning:" stderr | sort >actual &&
cat >expected <<\EOF &&
compare_results_with_midx "mixed mode (one pack + extra)"
+test_expect_success 'write with no objects and preferred pack' '
+ test_when_finished "rm -rf empty" &&
+ git init empty &&
+ test_must_fail git -C empty multi-pack-index write \
+ --stdin-packs --preferred-pack=does-not-exist </dev/null 2>err &&
+ cat >expect <<-EOF &&
+ warning: unknown preferred pack: ${SQ}does-not-exist${SQ}
+ error: no pack files to index.
+ EOF
+ test_cmp expect err
+'
+
test_expect_success 'write progress off for redirected stderr' '
git multi-pack-index --object-dir=$objdir write 2>err &&
test_line_count = 0 err
#!/bin/sh
test_description='on-disk reverse index'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# The below tests want control over the 'pack.writeReverseIndex' setting
# themselves to assert various combinations of it with other options.
-sane_unset GIT_TEST_WRITE_REV_INDEX
+sane_unset GIT_TEST_NO_WRITE_REV_INDEX
packdir=.git/objects/pack
test_expect_success 'setup' '
test_commit base &&
+ test_config pack.writeReverseIndex false &&
pack=$(git pack-objects --all $packdir/pack) &&
rev=$packdir/pack-$pack.rev &&
--batch-check="%(objectsize:disk)" <tip
'
+test_expect_success 'reverse index is ignored when pack.readReverseIndex is false' '
+ test_index_pack true &&
+ test_path_is_file $rev &&
+
+ test_config pack.readReverseIndex false &&
+
+ git rev-parse HEAD >tip &&
+ GIT_TEST_REV_INDEX_DIE_ON_DISK=1 git cat-file \
+ --batch-check="%(objectsize:disk)" <tip
+'
+
test_expect_success 'revindex in-memory vs on-disk' '
git init repo &&
test_when_finished "rm -fr repo" &&
test_cmp on-disk in-core
)
'
+
+test_expect_success 'fsck succeeds on good rev-index' '
+ test_when_finished rm -fr repo &&
+ git init repo &&
+ (
+ cd repo &&
+
+ test_commit commit &&
+ git -c pack.writeReverseIndex=true repack -ad &&
+ git fsck 2>err &&
+ test_must_be_empty err
+ )
+'
+
+test_expect_success 'set up rev-index corruption tests' '
+ git init corrupt &&
+ (
+ cd corrupt &&
+
+ test_commit commit &&
+ git -c pack.writeReverseIndex=true repack -ad &&
+
+ revfile=$(ls .git/objects/pack/pack-*.rev) &&
+ chmod a+w $revfile &&
+ cp $revfile $revfile.bak
+ )
+'
+
+corrupt_rev_and_verify () {
+ (
+ pos="$1" &&
+ value="$2" &&
+ error="$3" &&
+
+ cd corrupt &&
+ revfile=$(ls .git/objects/pack/pack-*.rev) &&
+
+ # Reset to original rev-file.
+ cp $revfile.bak $revfile &&
+
+ printf "$value" | dd of=$revfile bs=1 seek="$pos" conv=notrunc &&
+ test_must_fail git fsck 2>err &&
+ grep "$error" err
+ )
+}
+
+test_expect_success 'fsck catches invalid checksum' '
+ revfile=$(ls corrupt/.git/objects/pack/pack-*.rev) &&
+ orig_size=$(wc -c <$revfile) &&
+ hashpos=$((orig_size - 10)) &&
+ corrupt_rev_and_verify $hashpos bogus \
+ "invalid checksum"
+'
+
+test_expect_success 'fsck catches invalid row position' '
+ corrupt_rev_and_verify 14 "\07" \
+ "invalid rev-index position"
+'
+
+test_expect_success 'fsck catches invalid header: magic number' '
+ corrupt_rev_and_verify 1 "\07" \
+ "reverse-index file .* has unknown signature"
+'
+
+test_expect_success 'fsck catches invalid header: version' '
+ corrupt_rev_and_verify 7 "\02" \
+ "reverse-index file .* has unsupported version"
+'
+
+test_expect_success 'fsck catches invalid header: hash function' '
+ corrupt_rev_and_verify 11 "\03" \
+ "reverse-index file .* has unsupported hash id"
+'
+
test_done
--- /dev/null
+#!/bin/sh
+
+test_description='pack-objects --stdin'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+packed_objects () {
+ git show-index <"$1" >tmp-object-list &&
+ cut -d' ' -f2 tmp-object-list | sort &&
+ rm tmp-object-list
+ }
+
+test_expect_success 'setup for --stdin-packs tests' '
+ git init stdin-packs &&
+ (
+ cd stdin-packs &&
+
+ test_commit A &&
+ test_commit B &&
+ test_commit C &&
+
+ for id in A B C
+ do
+ git pack-objects .git/objects/pack/pack-$id \
+ --incremental --revs <<-EOF || exit 1
+ refs/tags/$id
+ EOF
+ done &&
+
+ ls -la .git/objects/pack
+ )
+'
+
+test_expect_success '--stdin-packs with excluded packs' '
+ (
+ cd stdin-packs &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+
+ git pack-objects test --stdin-packs <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx)
+ ) >expect.raw &&
+ git show-index <$(ls test-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success '--stdin-packs is incompatible with --filter' '
+ (
+ cd stdin-packs &&
+ test_must_fail git pack-objects --stdin-packs --stdout \
+ --filter=blob:none </dev/null 2>err &&
+ test_i18ngrep "cannot use --filter with --stdin-packs" err
+ )
+'
+
+test_expect_success '--stdin-packs is incompatible with --revs' '
+ (
+ cd stdin-packs &&
+ test_must_fail git pack-objects --stdin-packs --revs out \
+ </dev/null 2>err &&
+ test_i18ngrep "cannot use internal rev list with --stdin-packs" err
+ )
+'
+
+test_expect_success '--stdin-packs with loose objects' '
+ (
+ cd stdin-packs &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+
+ test_commit D && # loose
+
+ git pack-objects test2 --stdin-packs --unpacked <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
+ git rev-list --objects --no-object-names \
+ refs/tags/C..refs/tags/D
+
+ ) >expect.raw &&
+ ls -la . &&
+ git show-index <$(ls test2-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success '--stdin-packs with broken links' '
+ (
+ cd stdin-packs &&
+
+ # make an unreachable object with a bogus parent
+ git cat-file -p HEAD >commit &&
+ sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit |
+ git hash-object -w -t commit --stdin >in &&
+
+ git pack-objects .git/objects/pack/pack-D <in &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+ PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" &&
+
+ git pack-objects test3 --stdin-packs --unpacked <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ $PACK_D
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-D-*.idx) &&
+ git rev-list --objects --no-object-names \
+ refs/tags/C..refs/tags/D
+ ) >expect.raw &&
+ git show-index <$(ls test3-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'pack-objects --stdin with duplicate packfile' '
+ test_when_finished "rm -fr repo" &&
+
+ git init repo &&
+ (
+ cd repo &&
+ test_commit "commit" &&
+ git repack -ad &&
+
+ {
+ basename .git/objects/pack/pack-*.pack &&
+ basename .git/objects/pack/pack-*.pack
+ } >packfiles &&
+
+ git pack-objects --stdin-packs generated-pack <packfiles &&
+ packed_objects .git/objects/pack/pack-*.idx >expect &&
+ packed_objects generated-pack-*.idx >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'pack-objects --stdin with same packfile excluded and included' '
+ test_when_finished "rm -fr repo" &&
+
+ git init repo &&
+ (
+ cd repo &&
+ test_commit "commit" &&
+ git repack -ad &&
+
+ {
+ basename .git/objects/pack/pack-*.pack &&
+ printf "^%s\n" "$(basename .git/objects/pack/pack-*.pack)"
+ } >packfiles &&
+
+ git pack-objects --stdin-packs generated-pack <packfiles &&
+ packed_objects generated-pack-*.idx >packed-objects &&
+ test_must_be_empty packed-objects
+ )
+'
+
+test_expect_success 'pack-objects --stdin with packfiles from alternate object database' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Set up a shared repository with a single packfile.
+ git init shared &&
+ test_commit -C shared "shared-objects" &&
+ git -C shared repack -ad &&
+ basename shared/.git/objects/pack/pack-*.pack >packfile &&
+
+ # Set up a repository that is connected to the shared repository. This
+ # repository has no objects on its own, but we still expect to be able
+ # to pack objects from its alternate.
+ git clone --shared shared member &&
+ git -C member pack-objects --stdin-packs generated-pack <packfile &&
+ test_cmp shared/.git/objects/pack/pack-*.pack member/generated-pack-*.pack
+'
+
+test_expect_success 'pack-objects --stdin with packfiles from main and alternate object database' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Set up a shared repository with a single packfile.
+ git init shared &&
+ test_commit -C shared "shared-commit" &&
+ git -C shared repack -ad &&
+
+ # Set up a repository that is connected to the shared repository. This
+ # repository has a second packfile so that we can verify that it is
+ # possible to write packs that include packfiles from different object
+ # databases.
+ git clone --shared shared member &&
+ test_commit -C member "local-commit" &&
+ git -C member repack -dl &&
+
+ {
+ basename shared/.git/objects/pack/pack-*.pack &&
+ basename member/.git/objects/pack/pack-*.pack
+ } >packfiles &&
+
+ {
+ packed_objects shared/.git/objects/pack/pack-*.idx &&
+ packed_objects member/.git/objects/pack/pack-*.idx
+ } | sort >expected-objects &&
+
+ git -C member pack-objects --stdin-packs generated-pack <packfiles &&
+ packed_objects member/generated-pack-*.idx >actual-objects &&
+ test_cmp expected-objects actual-objects
+'
+
+test_done
done
}
+test_expect_success 'set up fake upload-pack' '
+ # This can be used to simulate an upload-pack that just shows the
+ # contents of the "input" file (prepared with the test-tool pkt-line
+ # helper), and does not do any negotiation (since ls-remote does not
+ # need it).
+ write_script cat-input <<-\EOF
+ # send our initial advertisement/response
+ cat input
+ # soak up the flush packet from the client
+ cat
+ EOF
+'
+
test_expect_success 'dies when no remote found' '
test_must_fail git ls-remote
'
test_expect_success 'ls-remote --symref' '
git fetch origin &&
- echo "ref: refs/heads/main HEAD" >expect &&
+ echo "ref: refs/heads/main HEAD" >expect.v2 &&
generate_references \
HEAD \
- refs/heads/main >>expect &&
+ refs/heads/main >>expect.v2 &&
+ echo "ref: refs/remotes/origin/main refs/remotes/origin/HEAD" >>expect.v2 &&
oid=$(git rev-parse HEAD) &&
- echo "$oid refs/remotes/origin/HEAD" >>expect &&
+ echo "$oid refs/remotes/origin/HEAD" >>expect.v2 &&
generate_references \
refs/remotes/origin/main \
refs/tags/mark \
refs/tags/mark1.1 \
refs/tags/mark1.10 \
- refs/tags/mark1.2 >>expect &&
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref >actual &&
- test_cmp expect actual
+ refs/tags/mark1.2 >>expect.v2 &&
+ # v0 does not show non-HEAD symrefs
+ grep -v "ref: refs/remotes" <expect.v2 >expect.v0 &&
+ git -c protocol.version=0 ls-remote --symref >actual.v0 &&
+ test_cmp expect.v0 actual.v0 &&
+ git -c protocol.version=2 ls-remote --symref >actual.v2 &&
+ test_cmp expect.v2 actual.v2
'
test_expect_success 'ls-remote with filtered symref (refname)' '
ref: refs/heads/main HEAD
$rev HEAD
EOF
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . HEAD >actual &&
+ git ls-remote --symref . HEAD >actual &&
test_cmp expect actual
'
-test_expect_failure 'ls-remote with filtered symref (--heads)' '
+test_expect_success 'ls-remote with filtered symref (--heads)' '
git symbolic-ref refs/heads/foo refs/tags/mark &&
- cat >expect <<-EOF &&
+ cat >expect.v2 <<-EOF &&
ref: refs/tags/mark refs/heads/foo
$rev refs/heads/foo
$rev refs/heads/main
EOF
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual &&
- test_cmp expect actual
+ grep -v "^ref: refs/tags/" <expect.v2 >expect.v0 &&
+ git -c protocol.version=0 ls-remote --symref --heads . >actual.v0 &&
+ test_cmp expect.v0 actual.v0 &&
+ git -c protocol.version=2 ls-remote --symref --heads . >actual.v2 &&
+ test_cmp expect.v2 actual.v2
'
-test_expect_success 'ls-remote --symref omits filtered-out matches' '
- cat >expect <<-EOF &&
- $rev refs/heads/foo
- $rev refs/heads/main
+test_expect_success 'indicate no refs in v0 standards-compliant empty remote' '
+ # Git does not produce an output like this, but it does match the
+ # standard and is produced by other implementations like JGit. So
+ # hard-code the case we care about.
+ #
+ # The actual capabilities do not matter; there are none that would
+ # change how ls-remote behaves.
+ oid=0000000000000000000000000000000000000000 &&
+ test-tool pkt-line pack >input.q <<-EOF &&
+ $oid capabilities^{}Qcaps-go-here
+ 0000
EOF
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual &&
- test_cmp expect actual &&
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . "refs/heads/*" >actual &&
- test_cmp expect actual
-'
-
-test_lazy_prereq GIT_DAEMON '
- test_bool_env GIT_TEST_GIT_DAEMON true
-'
+ q_to_nul <input.q >input &&
-# This test spawns a daemon, so run it only if the user would be OK with
-# testing with git-daemon.
-test_expect_success PIPE,JGIT,GIT_DAEMON 'indicate no refs in standards-compliant empty remote' '
- test_set_port JGIT_DAEMON_PORT &&
- JGIT_DAEMON_PID= &&
- git init --bare empty.git &&
- >empty.git/git-daemon-export-ok &&
- mkfifo jgit_daemon_output &&
- {
- jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
- JGIT_DAEMON_PID=$!
- } &&
- test_when_finished kill "$JGIT_DAEMON_PID" &&
- {
- read line &&
- case $line in
- Exporting*)
- ;;
- *)
- echo "Expected: Exporting" &&
- false;;
- esac &&
- read line &&
- case $line in
- "Listening on"*)
- ;;
- *)
- echo "Expected: Listening on" &&
- false;;
- esac
- } <jgit_daemon_output &&
# --exit-code asks the command to exit with 2 when no
# matching refs are found.
- test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
+ test_expect_code 2 git ls-remote --exit-code --upload-pack=./cat-input .
'
test_expect_success 'ls-remote works outside repository' '
test_expect_success 'ls-remote patterns work with all protocol versions' '
git for-each-ref --format="%(objectname) %(refname)" \
refs/heads/main refs/remotes/origin/main >expect &&
- git -c protocol.version=1 ls-remote . main >actual.v1 &&
- test_cmp expect actual.v1 &&
+ git -c protocol.version=0 ls-remote . main >actual.v0 &&
+ test_cmp expect actual.v0 &&
git -c protocol.version=2 ls-remote . main >actual.v2 &&
test_cmp expect actual.v2
'
test_expect_success 'ls-remote prefixes work with all protocol versions' '
git for-each-ref --format="%(objectname) %(refname)" \
refs/heads/ refs/tags/ >expect &&
- git -c protocol.version=1 ls-remote --heads --tags . >actual.v1 &&
- test_cmp expect actual.v1 &&
+ git -c protocol.version=0 ls-remote --heads --tags . >actual.v0 &&
+ test_cmp expect actual.v0 &&
git -c protocol.version=2 ls-remote --heads --tags . >actual.v2 &&
test_cmp expect actual.v2
'
+test_expect_success 'v0 clients can handle multiple symrefs' '
+ # Modern versions of Git will not return multiple symref capabilities
+ # for v0, so we have to hard-code the response. Note that we will
+ # always use both v0 and object-format=sha1 here, as the hard-coded
+ # response reflects a server that only supports those.
+ oid=1234567890123456789012345678901234567890 &&
+ symrefs="symref=refs/remotes/origin/HEAD:refs/remotes/origin/main" &&
+ symrefs="$symrefs symref=HEAD:refs/heads/main" &&
+
+ # Likewise we want to make sure our parser is not fooled by the string
+ # "symref" appearing as part of an earlier cap. But there is no way to
+ # do that via upload-pack, as arbitrary strings can appear only in a
+ # "symref" value itself (where we skip past the values as a whole)
+ # and "agent" (which always appears after "symref", so putting our
+ # parser in a confused state is less interesting).
+ caps="some other caps including a-fake-symref-cap" &&
+
+ test-tool pkt-line pack >input.q <<-EOF &&
+ $oid HEADQ$caps $symrefs
+ $oid refs/heads/main
+ $oid refs/remotes/origin/HEAD
+ $oid refs/remotes/origin/main
+ 0000
+ EOF
+ q_to_nul <input.q >input &&
+
+ cat >expect <<-EOF &&
+ ref: refs/heads/main HEAD
+ $oid HEAD
+ $oid refs/heads/main
+ ref: refs/remotes/origin/main refs/remotes/origin/HEAD
+ $oid refs/remotes/origin/HEAD
+ $oid refs/remotes/origin/main
+ EOF
+
+ git ls-remote --symref --upload-pack=./cat-input . >actual &&
+ test_cmp expect actual
+'
+
test_done
git reset HEAD^^
}
-assert_cruft_packs () {
- find .git/objects/pack -name "*.mtimes" >mtimes &&
- sed -e 's/\.mtimes$/\.pack/g' mtimes >packs &&
-
- test_file_not_empty packs &&
- while read pack
- do
- test_path_is_file "$pack" || return 1
- done <packs
-}
-
assert_no_cruft_packs () {
find .git/objects/pack -name "*.mtimes" >mtimes &&
test_must_be_empty mtimes
}
-test_expect_success 'gc --cruft generates a cruft pack' '
- test_when_finished "rm -fr crufts" &&
- git init crufts &&
+for argv in \
+ "gc" \
+ "-c gc.cruftPacks=true gc" \
+ "-c gc.cruftPacks=false gc --cruft"
+do
+ test_expect_success "git $argv generates a cruft pack" '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ prepare_cruft_history &&
+ git $argv &&
+
+ find .git/objects/pack -name "*.mtimes" >mtimes &&
+ sed -e 's/\.mtimes$/\.pack/g' mtimes >packs &&
+
+ test_file_not_empty packs &&
+ while read pack
+ do
+ test_path_is_file "$pack" || return 1
+ done <packs
+ )
+ '
+done
+
+for argv in \
+ "gc --no-cruft" \
+ "-c gc.cruftPacks=false gc" \
+ "-c gc.cruftPacks=true gc --no-cruft"
+do
+ test_expect_success "git $argv does not generate a cruft pack" '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ prepare_cruft_history &&
+ git $argv &&
+
+ assert_no_cruft_packs
+ )
+ '
+done
+
+test_expect_success '--keep-largest-pack ignores cruft packs' '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
(
- cd crufts &&
+ cd repo &&
+ # Generate a pack for reachable objects (of which there
+ # are 3), and one for unreachable objects (of which
+ # there are 6).
prepare_cruft_history &&
git gc --cruft &&
- assert_cruft_packs
- )
-'
-
-test_expect_success 'gc.cruftPacks=true generates a cruft pack' '
- test_when_finished "rm -fr crufts" &&
- git init crufts &&
- (
- cd crufts &&
-
- prepare_cruft_history &&
- git -c gc.cruftPacks=true gc &&
- assert_cruft_packs
- )
-'
-
-test_expect_success 'feature.experimental=true generates a cruft pack' '
- git init crufts &&
- test_when_finished "rm -fr crufts" &&
- (
- cd crufts &&
- prepare_cruft_history &&
- git -c feature.experimental=true gc &&
- assert_cruft_packs
- )
-'
+ mtimes="$(find .git/objects/pack -type f -name "pack-*.mtimes")" &&
+ sz="$(test_file_size "${mtimes%.mtimes}.pack")" &&
-test_expect_success 'feature.experimental=false allows explicit cruft packs' '
- git init crufts &&
- test_when_finished "rm -fr crufts" &&
- (
- cd crufts &&
+ # Ensure that the cruft pack gets removed (due to
+ # `--prune=now`) despite it being the largest pack.
+ git -c gc.bigPackThreshold=$sz gc --cruft --prune=now &&
- prepare_cruft_history &&
- git -c gc.cruftPacks=true -c feature.experimental=false gc &&
- assert_cruft_packs
+ assert_no_cruft_packs
)
'
-test_expect_success 'feature.experimental=true can be overridden' '
- git init crufts &&
- test_when_finished "rm -fr crufts" &&
+test_expect_success 'gc.bigPackThreshold ignores cruft packs' '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
(
- cd crufts &&
+ cd repo &&
+ # Generate a pack for reachable objects (of which there
+ # are 3), and one for unreachable objects (of which
+ # there are 6).
prepare_cruft_history &&
- git -c feature.expiremental=true -c gc.cruftPacks=false gc &&
- assert_no_cruft_packs
- )
-'
+ git gc --cruft &&
-test_expect_success 'feature.experimental=false avoids cruft packs by default' '
- git init crufts &&
- test_when_finished "rm -fr crufts" &&
- (
- cd crufts &&
+ # Ensure that the cruft pack gets removed (due to
+ # `--prune=now`) despite it being the largest pack.
+ git gc --cruft --prune=now --keep-largest-pack &&
- prepare_cruft_history &&
- git -c feature.experimental=false gc &&
assert_no_cruft_packs
)
'
'
test_expect_success "simultaneous gc ($title)" '
- git gc --prune=12.hours.ago
+ git gc --no-cruft --prune=12.hours.ago
'
test_expect_success "finish writing out commit ($title)" '
'
test_expect_success "simultaneous gc ($title)" '
- git gc --prune=12.hours.ago
+ git gc --no-cruft --prune=12.hours.ago
'
# tree should have been refreshed by write-tree
some message
EOF
commit=$(git hash-object -t commit -w broken-commit) &&
- git gc -q 2>stderr &&
+ git gc --no-cruft -q 2>stderr &&
verbose git cat-file -e $commit &&
test_must_be_empty stderr
'
100644 blob $(test_oid 003) foo
EOF
tree=$(git mktree --missing <broken-tree) &&
- git gc -q 2>stderr &&
+ git gc --no-cruft -q 2>stderr &&
git cat-file -e $tree &&
test_must_be_empty stderr
'
this is a broken tag
EOF
tag=$(git hash-object -t tag -w broken-tag) &&
- git gc -q 2>stderr &&
+ git gc --no-cruft -q 2>stderr &&
git cat-file -e $tag &&
test_must_be_empty stderr
'
test_expect_success GPG 'show good signature with custom format' '
cat >expect <<-\EOF &&
G
+ ultimate
13B6F51ECDDE430D
C O Mitter <committer@example.com>
73D758744BE721698EC54E8713B6F51ECDDE430D
73D758744BE721698EC54E8713B6F51ECDDE430D
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show bad signature with custom format' '
cat >expect <<-\EOF &&
B
+ undefined
13B6F51ECDDE430D
C O Mitter <committer@example.com>
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show untrusted signature with custom format' '
cat >expect <<-\EOF &&
U
+ undefined
65A0EEA02E30CAD7
Eris Discordia <discord@example.net>
F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
D4BE22311AD3131E5EDA29A461092E85B7227189
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show untrusted signature with undefined trust level' '
cat >expect <<-\EOF &&
+ U
undefined
65A0EEA02E30CAD7
Eris Discordia <discord@example.net>
F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
D4BE22311AD3131E5EDA29A461092E85B7227189
EOF
- git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show untrusted signature with ultimate trust level' '
cat >expect <<-\EOF &&
+ G
ultimate
13B6F51ECDDE430D
C O Mitter <committer@example.com>
73D758744BE721698EC54E8713B6F51ECDDE430D
73D758744BE721698EC54E8713B6F51ECDDE430D
EOF
- git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show unknown signature with custom format' '
cat >expect <<-\EOF &&
E
+ undefined
65A0EEA02E30CAD7
EOF
- GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show lack of signature with custom format' '
cat >expect <<-\EOF &&
N
+ undefined
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual &&
test_cmp expect actual
'
test_cmp expect actual
'
+test_expect_success '--local disables writing bitmaps when connected to alternate ODB' '
+ test_when_finished "rm -rf shared member" &&
+
+ git init shared &&
+ git clone --shared shared member &&
+ (
+ cd member &&
+ test_commit "object" &&
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adl --write-bitmap-index 2>err &&
+ cat >expect <<-EOF &&
+ warning: disabling bitmap writing, as some objects are not being packed
+ EOF
+ test_cmp expect err &&
+ test_path_is_missing .git/objects/pack-*.bitmap
+ )
+'
+
test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
mkdir alt_objects/pack &&
mv .git/objects/pack/* alt_objects/pack &&
packdir=$objdir/pack
midx=$objdir/pack/multi-pack-index
+packed_objects () {
+ git show-index <"$1" >tmp-object-list &&
+ cut -d' ' -f2 tmp-object-list | sort &&
+ rm tmp-object-list
+ }
+
test_expect_success '--geometric with no packs' '
git init geometric &&
test_when_finished "rm -fr geometric" &&
)
'
+test_expect_success '--geometric --write-midx with packfiles in main and alternate ODB' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Create a shared repository that will serve as the alternate object
+ # database for the member linked to it. It has got some objects on its
+ # own that are packed into a single packfile.
+ git init shared &&
+ test_commit -C shared common-object &&
+ git -C shared repack -ad &&
+
+ # We create member so that its alternates file points to the shared
+ # repository. We then create a commit in it so that git-repack(1) has
+ # something to repack.
+ # of the shared object database.
+ git clone --shared shared member &&
+ test_commit -C member unique-object &&
+ git -C member repack --geometric=2 --write-midx 2>err &&
+ test_must_be_empty err &&
+
+ # We should see that a new packfile was generated.
+ find shared/.git/objects/pack -type f -name "*.pack" >packs &&
+ test_line_count = 1 packs &&
+
+ # We should also see a multi-pack-index. This multi-pack-index should
+ # never refer to any packfiles in the alternate object database.
+ test_path_is_file member/.git/objects/pack/multi-pack-index &&
+ test-tool read-midx member/.git/objects >packs.midx &&
+ grep "^pack-.*\.idx$" packs.midx | sort >actual &&
+ basename member/.git/objects/pack/pack-*.idx >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success '--geometric --with-midx with no local objects' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Create a repository with a single packfile that acts as alternate
+ # object database.
+ git init shared &&
+ test_commit -C shared "shared-objects" &&
+ git -C shared repack -ad &&
+
+ # Create a second repository linked to the first one and perform a
+ # geometric repack on it.
+ git clone --shared shared member &&
+ git -C member repack --geometric 2 --write-midx 2>err &&
+ test_must_be_empty err &&
+
+ # Assert that we wrote neither a new packfile nor a multi-pack-index.
+ # We should not have a packfile because the single packfile in the
+ # alternate object database does not invalidate the geometric sequence.
+ # And we should not have a multi-pack-index because these only index
+ # local packfiles, and there are none.
+ test_dir_is_empty member/$packdir
+'
+
+test_expect_success '--geometric with same pack in main and alternate ODB' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Create a repository with a single packfile that acts as alternate
+ # object database.
+ git init shared &&
+ test_commit -C shared "shared-objects" &&
+ git -C shared repack -ad &&
+
+ # We create the member repository as an exact copy so that it has the
+ # same packfile.
+ cp -r shared member &&
+ test-tool path-utils real_path shared/.git/objects >member/.git/objects/info/alternates &&
+ find shared/.git/objects -type f >expected-files &&
+
+ # Verify that we can repack objects as expected without observing any
+ # error. Having the same packfile in both ODBs used to cause an error
+ # in git-pack-objects(1).
+ git -C member repack --geometric 2 2>err &&
+ test_must_be_empty err &&
+ # Nothing should have changed.
+ find shared/.git/objects -type f >actual-files &&
+ test_cmp expected-files actual-files
+'
+
+test_expect_success '--geometric -l with non-intact geometric sequence across ODBs' '
+ test_when_finished "rm -fr shared member" &&
+
+ git init shared &&
+ test_commit_bulk -C shared --start=1 1 &&
+
+ git clone --shared shared member &&
+ test_commit_bulk -C member --start=2 1 &&
+
+ # Verify that our assumptions actually hold: both generated packfiles
+ # should have three objects and should be non-equal.
+ packed_objects shared/.git/objects/pack/pack-*.idx >shared-objects &&
+ packed_objects member/.git/objects/pack/pack-*.idx >member-objects &&
+ test_line_count = 3 shared-objects &&
+ test_line_count = 3 member-objects &&
+ ! test_cmp shared-objects member-objects &&
+
+ # Perform the geometric repack. With `-l`, we should only see the local
+ # packfile and thus arrive at the conclusion that the geometric
+ # sequence is intact. We thus expect no changes.
+ #
+ # Note that we are tweaking mtimes of the packfiles so that we can
+ # verify they did not change. This is done in order to detect the case
+ # where we do repack objects, but the resulting packfile is the same.
+ test-tool chmtime --verbose =0 member/.git/objects/pack/* >expected-member-packs &&
+ git -C member repack --geometric=2 -l -d &&
+ test-tool chmtime --verbose member/.git/objects/pack/* >actual-member-packs &&
+ test_cmp expected-member-packs actual-member-packs &&
+
+ {
+ packed_objects shared/.git/objects/pack/pack-*.idx &&
+ packed_objects member/.git/objects/pack/pack-*.idx
+ } | sort >expected-objects &&
+
+ # On the other hand, when doing a non-local geometric repack we should
+ # see both packfiles and thus repack them. We expect that the shared
+ # object database was not changed.
+ test-tool chmtime --verbose =0 shared/.git/objects/pack/* >expected-shared-packs &&
+ git -C member repack --geometric=2 -d &&
+ test-tool chmtime --verbose shared/.git/objects/pack/* >actual-shared-packs &&
+ test_cmp expected-shared-packs actual-shared-packs &&
+
+ # Furthermore, we expect that the member repository now has a single
+ # packfile that contains the combined shared and non-shared objects.
+ ls member/.git/objects/pack/pack-*.idx >actual &&
+ test_line_count = 1 actual &&
+ packed_objects member/.git/objects/pack/pack-*.idx >actual-objects &&
+ test_line_count = 6 actual-objects &&
+ test_cmp expected-objects actual-objects
+'
+
+test_expect_success '--geometric -l disables writing bitmaps with non-local packfiles' '
+ test_when_finished "rm -fr shared member" &&
+
+ git init shared &&
+ test_commit_bulk -C shared --start=1 1 &&
+
+ git clone --shared shared member &&
+ test_commit_bulk -C member --start=2 1 &&
+
+ # When performing a geometric repack with `-l` while connected to an
+ # alternate object database that has a packfile we do not have full
+ # coverage of objects. As a result, we expect that writing the bitmap
+ # will be disabled.
+ git -C member repack -l --geometric=2 --write-midx --write-bitmap-index 2>err &&
+ cat >expect <<-EOF &&
+ warning: disabling bitmap writing, as some objects are not being packed
+ EOF
+ test_cmp expect err &&
+ test_path_is_missing member/.git/objects/pack/multi-pack-index-*.bitmap &&
+
+ # On the other hand, when we repack without `-l`, we should see that
+ # the bitmap gets created.
+ git -C member repack --geometric=2 --write-midx --write-bitmap-index 2>err &&
+ test_must_be_empty err &&
+ test_path_is_file member/.git/objects/pack/multi-pack-index-*.bitmap
+'
+
test_done
)
'
+expected_file_counter_output () {
+ total=$1
+ count=0
+ while test $count -ne $total
+ do
+ count=$((count + 1)) &&
+ echo "$count/$total" || return
+ done
+}
+
+test_expect_success $PREREQ '--validate hook allows counting of messages' '
+ test_when_finished "rm -rf my-hooks.log" &&
+ test_config core.hooksPath "my-hooks" &&
+ mkdir -p my-hooks &&
+
+ write_script my-hooks/sendemail-validate <<-\EOF &&
+ num=$GIT_SENDEMAIL_FILE_COUNTER &&
+ tot=$GIT_SENDEMAIL_FILE_TOTAL &&
+ echo "$num/$tot" >>my-hooks.log || exit 1
+ EOF
+
+ >my-hooks.log &&
+ expected_file_counter_output 4 >expect &&
+ git send-email \
+ --from="Example <from@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --validate -3 --cover-letter --force &&
+ test_cmp expect my-hooks.log
+'
+
test_expect_success $PREREQ 'test that send-email works outside a repo' '
nongit git send-email \
--from="Example <nobody@example.com>" \
INPUT_END
- test_when_finished "rm -f .git/TEMP_TAG
- git gc
- git prune" &&
+ test_when_finished "rm -f .git/TEMP_TAG && git gc --prune=now" &&
git fast-import <input &&
test $(test-tool ref-store main resolve-ref TEMP_TAG 0 | cut -f1 -d " " ) != "$ZERO_OID" &&
test $(git rev-parse main) = $(git rev-parse TEMP_TAG^)
INPUT_END
test_when_finished "git update-ref -d refs/heads/empty-committer-1
- git gc
- git prune" &&
+ git gc --prune=now" &&
git fast-import <input &&
out=$(git fsck) &&
echo "$out" &&
INPUT_END
test_when_finished "git update-ref -d refs/heads/empty-committer-2
- git gc
- git prune" &&
+ git gc --prune=now" &&
git fast-import <input &&
out=$(git fsck) &&
echo "$out" &&
INPUT_END
git branch -D sub &&
- git gc &&
- git prune &&
+ git gc --prune=now &&
git fast-import <input &&
test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)
'
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "tag.h"
+#include "object-name.h"
#include "object-store.h"
#include "commit.h"
#include "tree.h"
--- /dev/null
+#!/bin/sh
+
+# An example hook script to validate a patch (and/or patch series) before
+# sending it via email.
+#
+# The hook should exit with non-zero status after issuing an appropriate
+# message if it wants to prevent the email(s) from being sent.
+#
+# To enable this hook, rename this file to "sendemail-validate".
+#
+# By default, it will only check that the patch(es) can be applied on top of
+# the default upstream branch without conflicts in a secondary worktree. After
+# validation (successful or not) of the last patch of a series, the worktree
+# will be deleted.
+#
+# The following config variables can be set to change the default remote and
+# remote ref that are used to apply the patches against:
+#
+# sendemail.validateRemote (default: origin)
+# sendemail.validateRemoteRef (default: HEAD)
+#
+# Replace the TODO placeholders with appropriate checks according to your
+# needs.
+
+validate_cover_letter () {
+ file="$1"
+ # TODO: Replace with appropriate checks (e.g. spell checking).
+ true
+}
+
+validate_patch () {
+ file="$1"
+ # Ensure that the patch applies without conflicts.
+ git am -3 "$file" || return
+ # TODO: Replace with appropriate checks for this patch
+ # (e.g. checkpatch.pl).
+ true
+}
+
+validate_series () {
+ # TODO: Replace with appropriate checks for the whole series
+ # (e.g. quick build, coding style checks, etc.).
+ true
+}
+
+# main -------------------------------------------------------------------------
+
+if test "$GIT_SENDEMAIL_FILE_COUNTER" = 1
+then
+ remote=$(git config --default origin --get sendemail.validateRemote) &&
+ ref=$(git config --default HEAD --get sendemail.validateRemoteRef) &&
+ worktree=$(mktemp --tmpdir -d sendemail-validate.XXXXXXX) &&
+ git worktree add -fd --checkout "$worktree" "refs/remotes/$remote/$ref" &&
+ git config --replace-all sendemail.validateWorktree "$worktree"
+else
+ worktree=$(git config --get sendemail.validateWorktree)
+fi || {
+ echo "sendemail-validate: error: failed to prepare worktree" >&2
+ exit 1
+}
+
+unset GIT_DIR GIT_WORK_TREE
+cd "$worktree" &&
+
+if grep -q "^diff --git " "$1"
+then
+ validate_patch "$1"
+else
+ validate_cover_letter "$1"
+fi &&
+
+if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL"
+then
+ git config --unset-all sendemail.validateWorktree &&
+ trap 'git worktree remove -ff "$worktree"' EXIT &&
+ validate_series
+fi
-#include "cache.h"
+#include "git-compat-util.h"
#include "tmp-objdir.h"
#include "abspath.h"
#include "chdir-notify.h"
#include "dir.h"
#include "environment.h"
+#include "object-file.h"
#include "sigchain.h"
#include "string-list.h"
#include "strbuf.h"
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "environment.h"
#include "quote.h"
#include "setup.h"
+#include "trace.h"
#include "wrapper.h"
struct trace_key trace_default_key = { "GIT_TRACE", 0, 0, 0 };
#include "thread-utils.h"
#include "version.h"
#include "trace.h"
+#include "trace2.h"
#include "trace2/tr2_cfg.h"
#include "trace2/tr2_cmd_name.h"
#include "trace2/tr2_ctr.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "transport.h"
#include "quote.h"
#include "run-command.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "revision.h"
#include "remote.h"
#include "string-list.h"
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
#include "string-list.h"
#include "oid-array.h"
#include "sigchain.h"
+#include "trace2.h"
#include "transport-internal.h"
#include "protocol.h"
+#include "object-name.h"
#include "object-store.h"
#include "color.h"
#include "bundle-uri.h"
struct git_transport_data *data = transport->data;
struct ref *refs = NULL;
struct packet_reader reader;
- int sid_len;
+ size_t sid_len;
const char *server_sid;
connect_setup(transport, for_push);
#include "dir.h"
#include "gettext.h"
#include "hex.h"
+#include "object-file.h"
#include "object-store.h"
+#include "trace2.h"
#include "tree.h"
#include "pathspec.h"
#include "json-writer.h"
#include "cache-tree.h"
#include "hex.h"
#include "tree.h"
+#include "object-name.h"
#include "object-store.h"
#include "blob.h"
#include "commit.h"
#include "cache.h"
+#include "advice.h"
#include "strvec.h"
#include "repository.h"
#include "config.h"
#include "sparse-index.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "trace2.h"
#include "fsmonitor.h"
#include "object-store.h"
#include "promisor-remote.h"
#define UNPACK_TREES_H
#include "cache.h"
+#include "convert.h"
#include "strvec.h"
#include "string-list.h"
#include "tree-walk.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
#include "sideband.h"
#include "repository.h"
#include "object-store.h"
+#include "oid-array.h"
#include "tag.h"
#include "object.h"
#include "commit.h"
#include "version.h"
#include "string-list.h"
#include "strvec.h"
+#include "trace2.h"
#include "prio-queue.h"
#include "protocol.h"
#include "quote.h"
#include "commit-graph.h"
#include "commit-reach.h"
#include "shallow.h"
+#include "wrapper.h"
#include "write-or-die.h"
/* Remember to update object flag allocation in object.h */
const char *features;
struct object_id oid_buf;
const char *arg;
- int feature_len;
+ size_t feature_len;
reset_timeout(data->timeout);
if (packet_reader_read(reader) != PACKET_READ_NORMAL)
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "hex.h"
#include "walker.h"
#include "abspath.h"
#include "config.h"
#include "gettext.h"
+#include "trace2.h"
#include "wrapper.h"
static intmax_t count_fsync_writeout_only;
#include "cache.h"
+#include "advice.h"
#include "wt-status.h"
#include "object.h"
#include "dir.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "revision.h"
#include "diffcore.h"
#include "quote.h"
#include "column.h"
#include "setup.h"
#include "strbuf.h"
+#include "trace.h"
+#include "trace2.h"
#include "utf8.h"
#include "worktree.h"
#include "lockfile.h"