Commit Graph

21727 Commits

Author SHA1 Message Date
Patrick Steinhardt
e69e8ffef7 refs/files: sort reflogs returned by the reflog iterator
We use a directory iterator to return reflogs via the reflog iterator.
This iterator returns entries in the same order as readdir(3P) would and
will thus yield reflogs with no discernible order.

Set the new `DIR_ITERATOR_SORTED` flag that was introduced in the
preceding commit so that the order is deterministic. While the effect of
this can only been observed in a test tool, a subsequent commit will
start to expose this functionality to users via a new `git reflog list`
subcommand.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-21 09:58:05 -08:00
Junio C Hamano
f7cdeafdd0 Merge branch 'ps/reftable-backend' into ps/reflog-list
* ps/reftable-backend:
  refs/reftable: fix leak when copying reflog fails
  ci: add jobs to test with the reftable backend
  refs: introduce reftable backend
2024-02-19 10:50:07 -08:00
Junio C Hamano
9115864cb5 Merge branch 'jc/unit-tests-make-relative-fix'
The mechanism to report the filename in the source code, used by
the unit-test machinery, assumed that the compiler expanded __FILE__
to the path to the source given to the $(CC), but some compilers
give full path, breaking the output.  This has been corrected.

* jc/unit-tests-make-relative-fix:
  unit-tests: do show relative file paths on non-Windows, too
2024-02-13 14:31:11 -08:00
Junio C Hamano
3b89ff16aa Merge branch 'tb/multi-pack-reuse-experiment'
Setting `feature.experimental` opts the user into multi-pack reuse
experiment

* tb/multi-pack-reuse-experiment:
  pack-objects: enable multi-pack reuse via `feature.experimental`
  t5332-multi-pack-reuse.sh: extract pack-objects helper functions
2024-02-12 13:16:11 -08:00
Junio C Hamano
d4833b22ab Merge branch 'vd/for-each-ref-sort-with-formatted-timestamp'
"git branch" and friends learned to use the formatted text as
sorting key, not the underlying timestamp value, when the --sort
option is used with author or committer timestamp with a format
specifier (e.g., "--sort=creatordate:format:%H:%M:%S").

* vd/for-each-ref-sort-with-formatted-timestamp:
  ref-filter.c: sort formatted dates by byte value
2024-02-12 13:16:11 -08:00
Junio C Hamano
b3370dd51e Merge branch 'pw/show-ref-pseudorefs'
"git show-ref --verify" did not show things like "CHERRY_PICK_HEAD",
which has been corrected.

* pw/show-ref-pseudorefs:
  t1400: use show-ref to check pseudorefs
  show-ref --verify: accept pseudorefs
2024-02-12 13:16:11 -08:00
Junio C Hamano
70550a2242 Merge branch 'ps/report-failure-from-git-stash'
"git stash" sometimes was silent even when it failed due to
unwritable index file, which has been corrected.

* ps/report-failure-from-git-stash:
  builtin/stash: report failure to write to index
2024-02-12 13:16:11 -08:00
Junio C Hamano
46761378c3 Merge branch 'bk/complete-bisect'
Command line completion support (in contrib/) has been
updated for "git bisect".

* bk/complete-bisect:
  completion: bisect: recognize but do not complete view subcommand
  completion: bisect: complete log opts for visualize subcommand
  completion: new function __git_complete_log_opts
  completion: bisect: complete missing --first-parent and - -no-checkout options
  completion: bisect: complete custom terms and related options
  completion: bisect: complete bad, new, old, and help subcommands
  completion: tests: always use 'master' for default initial branch name
2024-02-12 13:16:10 -08:00
Junio C Hamano
f66286364f unit-tests: do show relative file paths on non-Windows, too
There are compilers other than Visual C that want to show absolute
paths.  Generalize the helper introduced by a2c5e294 (unit-tests: do
show relative file paths, 2023-09-25) so that it can also work with
a path that uses slash as the directory separator, and becomes
almost no-op once one-time preparation finds out that we are using a
compiler that already gives relative paths.  Incidentally, this also
should do the right thing on Windows with a compiler that shows
relative paths but with backslash as the directory separator (if
such a thing exists and is used to build git).

Reported-by: Randall S. Becker <rsbecker@nexbridge.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-12 08:44:22 -08:00
Junio C Hamano
6dbc1eb664 Merge branch 'jk/unit-tests-buildfix'
Build dependency around unit tests has been fixed.

* jk/unit-tests-buildfix:
  t/Makefile: say the default target upfront
  t/Makefile: get UNIT_TESTS list from C sources
  Makefile: remove UNIT_TEST_BIN directory with "make clean"
  Makefile: use mkdir_p_parent_template for UNIT_TEST_BIN
2024-02-08 13:20:33 -08:00
Junio C Hamano
2c90347a94 Merge branch 'jc/index-pack-fsck-levels'
The "--fsck-objects" option of "git index-pack" now can take the
optional parameter to tweak severity of different fsck errors.

* jc/index-pack-fsck-levels:
  index-pack: --fsck-objects to take an optional argument for fsck msgs
  index-pack: test and document --strict=<msg-id>=<severity>...
2024-02-08 13:20:33 -08:00
Junio C Hamano
107023e1c9 Merge branch 'cp/unit-test-prio-queue'
The priority queue test has been migrated to the unit testing
framework.

* cp/unit-test-prio-queue:
  tests: move t0009-prio-queue.sh to the new unit testing framework
2024-02-08 13:20:33 -08:00
Victoria Dye
46176d77c9 ref-filter.c: sort formatted dates by byte value
Update the ref sorting functions of 'ref-filter.c' so that when date fields
are specified with a format string (such as in 'git for-each-ref
--sort=creatordate:<something>'), they are sorted by their formatted string
value rather than by the underlying numeric timestamp. Currently, date
fields are always sorted by timestamp, regardless of whether formatting
information is included in the '--sort' key.

Leaving the default (unformatted) date sorting unchanged, sorting by the
formatted date string adds some flexibility to 'for-each-ref' by allowing
for behavior like "sort by year, then by refname within each year" or "sort
by time of day". Because the inclusion of a format string previously had no
effect on sort behavior, this change likely will not affect existing usage
of 'for-each-ref' or other ref listing commands.

Additionally, update documentation & tests to document the new sorting
mechanism.

Signed-off-by: Victoria Dye <vdye@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-07 21:33:37 -08:00
Phillip Wood
1af410d455 t1400: use show-ref to check pseudorefs
Now that "git show-ref --verify" accepts pseudorefs use that in
preference to "git rev-parse" when checking pseudorefs as we do when
checking branches etc.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-07 09:14:48 -08:00
Phillip Wood
1dbe401563 show-ref --verify: accept pseudorefs
"git show-ref --verify" is useful for scripts that want to look up a
fully qualified refname without falling back to the DWIM rules used by
"git rev-parse" rules when the ref does not exist. Currently it will
only accept "HEAD" or a refname beginning with "refs/". Running

    git show-ref --verify CHERRY_PICK_HEAD

will always result in

    fatal: 'CHERRY_PICK_HEAD' - not a valid ref

even when CHERRY_PICK_HEAD exists. By calling refname_is_safe() instead
of comparing the refname to "HEAD" we can accept all one-level refs that
contain only uppercase ascii letters and underscores.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-07 09:12:47 -08:00
Patrick Steinhardt
57db2a094d refs: introduce reftable backend
Due to scalability issues, Shawn Pearce has originally proposed a new
"reftable" format more than six years ago [1]. Initially, this new
format was implemented in JGit with promising results. Around two years
ago, we have then added the "reftable" library to the Git codebase via
a4bbd13be3 (Merge branch 'hn/reftable', 2021-12-15). With this we have
landed all the low-level code to read and write reftables. Notably
missing though was the integration of this low-level code into the Git
code base in the form of a new ref backend that ties all of this
together.

This gap is now finally closed by introducing a new "reftable" backend
into the Git codebase. This new backend promises to bring some notable
improvements to Git repositories:

  - It becomes possible to do truly atomic writes where either all refs
    are committed to disk or none are. This was not possible with the
    "files" backend because ref updates were split across multiple loose
    files.

  - The disk space required to store many refs is reduced, both compared
    to loose refs and packed-refs. This is enabled both by the reftable
    format being a binary format, which is more compact, and by prefix
    compression.

  - We can ignore filesystem-specific behaviour as ref names are not
    encoded via paths anymore. This means there is no need to handle
    case sensitivity on Windows systems or Unicode precomposition on
    macOS.

  - There is no need to rewrite the complete refdb anymore every time a
    ref is being deleted like it was the case for packed-refs. This
    means that ref deletions are now constant time instead of scaling
    linearly with the number of refs.

  - We can ignore file/directory conflicts so that it becomes possible
    to store both "refs/heads/foo" and "refs/heads/foo/bar".

  - Due to this property we can retain reflogs for deleted refs. We have
    previously been deleting reflogs together with their refs to avoid
    file/directory conflicts, which is not necessary anymore.

  - We can properly enumerate all refs. With the "files" backend it is
    not easily possible to distinguish between refs and non-refs because
    they may live side by side in the gitdir.

Not all of these improvements are realized with the current "reftable"
backend implementation. At this point, the new backend is supposed to be
a drop-in replacement for the "files" backend that is used by basically
all Git repositories nowadays. It strives for 1:1 compatibility, which
means that a user can expect the same behaviour regardless of whether
they use the "reftable" backend or the "files" backend for most of the
part.

Most notably, this means we artificially limit the capabilities of the
"reftable" backend to match the limits of the "files" backend. It is not
possible to create refs that would end up with file/directory conflicts,
we do not retain reflogs, we perform stricter-than-necessary checks.
This is done intentionally due to two main reasons:

  - It makes it significantly easier to land the "reftable" backend as
    tests behave the same. It would be tough to argue for each and every
    single test that doesn't pass with the "reftable" backend.

  - It ensures compatibility between repositories that use the "files"
    backend and repositories that use the "reftable" backend. Like this,
    hosters can migrate their repositories to use the "reftable" backend
    without causing issues for clients that use the "files" backend in
    their clones.

It is expected that these artificial limitations may eventually go away
in the long term.

Performance-wise things very much depend on the actual workload. The
following benchmarks compare the "files" and "reftable" backends in the
current version:

  - Creating N refs in separate transactions shows that the "files"
    backend is ~50% faster. This is not surprising given that creating a
    ref only requires us to create a single loose ref. The "reftable"
    backend will also perform auto compaction on updates. In real-world
    workloads we would likely also want to perform pack loose refs,
    which would likely change the picture.

        Benchmark 1: update-ref: create refs sequentially (refformat = files, refcount = 1)
          Time (mean ± σ):       2.1 ms ±   0.3 ms    [User: 0.6 ms, System: 1.7 ms]
          Range (min … max):     1.8 ms …   4.3 ms    133 runs

        Benchmark 2: update-ref: create refs sequentially (refformat = reftable, refcount = 1)
          Time (mean ± σ):       2.7 ms ±   0.1 ms    [User: 0.6 ms, System: 2.2 ms]
          Range (min … max):     2.4 ms …   2.9 ms    132 runs

        Benchmark 3: update-ref: create refs sequentially (refformat = files, refcount = 1000)
          Time (mean ± σ):      1.975 s ±  0.006 s    [User: 0.437 s, System: 1.535 s]
          Range (min … max):    1.969 s …  1.980 s    3 runs

        Benchmark 4: update-ref: create refs sequentially (refformat = reftable, refcount = 1000)
          Time (mean ± σ):      2.611 s ±  0.013 s    [User: 0.782 s, System: 1.825 s]
          Range (min … max):    2.597 s …  2.622 s    3 runs

        Benchmark 5: update-ref: create refs sequentially (refformat = files, refcount = 100000)
          Time (mean ± σ):     198.442 s ±  0.241 s    [User: 43.051 s, System: 155.250 s]
          Range (min … max):   198.189 s … 198.670 s    3 runs

        Benchmark 6: update-ref: create refs sequentially (refformat = reftable, refcount = 100000)
          Time (mean ± σ):     294.509 s ±  4.269 s    [User: 104.046 s, System: 190.326 s]
          Range (min … max):   290.223 s … 298.761 s    3 runs

  - Creating N refs in a single transaction shows that the "files"
    backend is significantly slower once we start to write many refs.
    The "reftable" backend only needs to update two files, whereas the
    "files" backend needs to write one file per ref.

        Benchmark 1: update-ref: create many refs (refformat = files, refcount = 1)
          Time (mean ± σ):       1.9 ms ±   0.1 ms    [User: 0.4 ms, System: 1.4 ms]
          Range (min … max):     1.8 ms …   2.6 ms    151 runs

        Benchmark 2: update-ref: create many refs (refformat = reftable, refcount = 1)
          Time (mean ± σ):       2.5 ms ±   0.1 ms    [User: 0.7 ms, System: 1.7 ms]
          Range (min … max):     2.4 ms …   3.4 ms    148 runs

        Benchmark 3: update-ref: create many refs (refformat = files, refcount = 1000)
          Time (mean ± σ):     152.5 ms ±   5.2 ms    [User: 19.1 ms, System: 133.1 ms]
          Range (min … max):   148.5 ms … 167.8 ms    15 runs

        Benchmark 4: update-ref: create many refs (refformat = reftable, refcount = 1000)
          Time (mean ± σ):      58.0 ms ±   2.5 ms    [User: 28.4 ms, System: 29.4 ms]
          Range (min … max):    56.3 ms …  72.9 ms    40 runs

        Benchmark 5: update-ref: create many refs (refformat = files, refcount = 1000000)
          Time (mean ± σ):     152.752 s ±  0.710 s    [User: 20.315 s, System: 131.310 s]
          Range (min … max):   152.165 s … 153.542 s    3 runs

        Benchmark 6: update-ref: create many refs (refformat = reftable, refcount = 1000000)
          Time (mean ± σ):     51.912 s ±  0.127 s    [User: 26.483 s, System: 25.424 s]
          Range (min … max):   51.769 s … 52.012 s    3 runs

  - Deleting a ref in a fully-packed repository shows that the "files"
    backend scales with the number of refs. The "reftable" backend has
    constant-time deletions.

        Benchmark 1: update-ref: delete ref (refformat = files, refcount = 1)
          Time (mean ± σ):       1.7 ms ±   0.1 ms    [User: 0.4 ms, System: 1.2 ms]
          Range (min … max):     1.6 ms …   2.1 ms    316 runs

        Benchmark 2: update-ref: delete ref (refformat = reftable, refcount = 1)
          Time (mean ± σ):       1.8 ms ±   0.1 ms    [User: 0.4 ms, System: 1.3 ms]
          Range (min … max):     1.7 ms …   2.1 ms    294 runs

        Benchmark 3: update-ref: delete ref (refformat = files, refcount = 1000)
          Time (mean ± σ):       2.0 ms ±   0.1 ms    [User: 0.5 ms, System: 1.4 ms]
          Range (min … max):     1.9 ms …   2.5 ms    287 runs

        Benchmark 4: update-ref: delete ref (refformat = reftable, refcount = 1000)
          Time (mean ± σ):       1.9 ms ±   0.1 ms    [User: 0.5 ms, System: 1.3 ms]
          Range (min … max):     1.8 ms …   2.1 ms    217 runs

        Benchmark 5: update-ref: delete ref (refformat = files, refcount = 1000000)
          Time (mean ± σ):     229.8 ms ±   7.9 ms    [User: 182.6 ms, System: 46.8 ms]
          Range (min … max):   224.6 ms … 245.2 ms    6 runs

        Benchmark 6: update-ref: delete ref (refformat = reftable, refcount = 1000000)
          Time (mean ± σ):       2.0 ms ±   0.0 ms    [User: 0.6 ms, System: 1.3 ms]
          Range (min … max):     2.0 ms …   2.1 ms    3 runs

  - Listing all refs shows no significant advantage for either of the
    backends. The "files" backend is a bit faster, but not by a
    significant margin. When repositories are not packed the "reftable"
    backend outperforms the "files" backend because the "reftable"
    backend performs auto-compaction.

        Benchmark 1: show-ref: print all refs (refformat = files, refcount = 1, packed = true)
          Time (mean ± σ):       1.6 ms ±   0.1 ms    [User: 0.4 ms, System: 1.1 ms]
          Range (min … max):     1.5 ms …   2.0 ms    1729 runs

        Benchmark 2: show-ref: print all refs (refformat = reftable, refcount = 1, packed = true)
          Time (mean ± σ):       1.6 ms ±   0.1 ms    [User: 0.4 ms, System: 1.1 ms]
          Range (min … max):     1.5 ms …   1.8 ms    1816 runs

        Benchmark 3: show-ref: print all refs (refformat = files, refcount = 1000, packed = true)
          Time (mean ± σ):       4.3 ms ±   0.1 ms    [User: 0.9 ms, System: 3.3 ms]
          Range (min … max):     4.1 ms …   4.6 ms    645 runs

        Benchmark 4: show-ref: print all refs (refformat = reftable, refcount = 1000, packed = true)
          Time (mean ± σ):       4.5 ms ±   0.2 ms    [User: 1.0 ms, System: 3.3 ms]
          Range (min … max):     4.2 ms …   5.9 ms    643 runs

        Benchmark 5: show-ref: print all refs (refformat = files, refcount = 1000000, packed = true)
          Time (mean ± σ):      2.537 s ±  0.034 s    [User: 0.488 s, System: 2.048 s]
          Range (min … max):    2.511 s …  2.627 s    10 runs

        Benchmark 6: show-ref: print all refs (refformat = reftable, refcount = 1000000, packed = true)
          Time (mean ± σ):      2.712 s ±  0.017 s    [User: 0.653 s, System: 2.059 s]
          Range (min … max):    2.692 s …  2.752 s    10 runs

        Benchmark 7: show-ref: print all refs (refformat = files, refcount = 1, packed = false)
          Time (mean ± σ):       1.6 ms ±   0.1 ms    [User: 0.4 ms, System: 1.1 ms]
          Range (min … max):     1.5 ms …   1.9 ms    1834 runs

        Benchmark 8: show-ref: print all refs (refformat = reftable, refcount = 1, packed = false)
          Time (mean ± σ):       1.6 ms ±   0.1 ms    [User: 0.4 ms, System: 1.1 ms]
          Range (min … max):     1.4 ms …   2.0 ms    1840 runs

        Benchmark 9: show-ref: print all refs (refformat = files, refcount = 1000, packed = false)
          Time (mean ± σ):      13.8 ms ±   0.2 ms    [User: 2.8 ms, System: 10.8 ms]
          Range (min … max):    13.3 ms …  14.5 ms    208 runs

        Benchmark 10: show-ref: print all refs (refformat = reftable, refcount = 1000, packed = false)
          Time (mean ± σ):       4.5 ms ±   0.2 ms    [User: 1.2 ms, System: 3.3 ms]
          Range (min … max):     4.3 ms …   6.2 ms    624 runs

        Benchmark 11: show-ref: print all refs (refformat = files, refcount = 1000000, packed = false)
          Time (mean ± σ):     12.127 s ±  0.129 s    [User: 2.675 s, System: 9.451 s]
          Range (min … max):   11.965 s … 12.370 s    10 runs

        Benchmark 12: show-ref: print all refs (refformat = reftable, refcount = 1000000, packed = false)
          Time (mean ± σ):      2.799 s ±  0.022 s    [User: 0.735 s, System: 2.063 s]
          Range (min … max):    2.769 s …  2.836 s    10 runs

  - Printing a single ref shows no real difference between the "files"
    and "reftable" backends.

        Benchmark 1: show-ref: print single ref (refformat = files, refcount = 1)
          Time (mean ± σ):       1.5 ms ±   0.1 ms    [User: 0.4 ms, System: 1.0 ms]
          Range (min … max):     1.4 ms …   1.8 ms    1779 runs

        Benchmark 2: show-ref: print single ref (refformat = reftable, refcount = 1)
          Time (mean ± σ):       1.6 ms ±   0.1 ms    [User: 0.4 ms, System: 1.1 ms]
          Range (min … max):     1.4 ms …   2.5 ms    1753 runs

        Benchmark 3: show-ref: print single ref (refformat = files, refcount = 1000)
          Time (mean ± σ):       1.5 ms ±   0.1 ms    [User: 0.3 ms, System: 1.1 ms]
          Range (min … max):     1.4 ms …   1.9 ms    1840 runs

        Benchmark 4: show-ref: print single ref (refformat = reftable, refcount = 1000)
          Time (mean ± σ):       1.6 ms ±   0.1 ms    [User: 0.4 ms, System: 1.1 ms]
          Range (min … max):     1.5 ms …   2.0 ms    1831 runs

        Benchmark 5: show-ref: print single ref (refformat = files, refcount = 1000000)
          Time (mean ± σ):       1.6 ms ±   0.1 ms    [User: 0.4 ms, System: 1.1 ms]
          Range (min … max):     1.5 ms …   2.1 ms    1848 runs

        Benchmark 6: show-ref: print single ref (refformat = reftable, refcount = 1000000)
          Time (mean ± σ):       1.6 ms ±   0.1 ms    [User: 0.4 ms, System: 1.1 ms]
          Range (min … max):     1.5 ms …   2.1 ms    1762 runs

So overall, performance depends on the usecases. Except for many
sequential writes the "reftable" backend is roughly on par or
significantly faster than the "files" backend though. Given that the
"files" backend has received 18 years of optimizations by now this can
be seen as a win. Furthermore, we can expect that the "reftable" backend
will grow faster over time when attention turns more towards
optimizations.

The complete test suite passes, except for those tests explicitly marked
to require the REFFILES prerequisite. Some tests in t0610 are marked as
failing because they depend on still-in-flight bug fixes. Tests can be
run with the new backend by setting the GIT_TEST_DEFAULT_REF_FORMAT
environment variable to "reftable".

There is a single known conceptual incompatibility with the dumb HTTP
transport. As "info/refs" SHOULD NOT contain the HEAD reference, and
because the "HEAD" file is not valid anymore, it is impossible for the
remote client to figure out the default branch without changing the
protocol. This shortcoming needs to be handled in a subsequent patch
series.

As the reftable library has already been introduced a while ago, this
commit message will not go into the details of how exactly the on-disk
format works. Please refer to our preexisting technical documentation at
Documentation/technical/reftable for this.

[1]: https://public-inbox.org/git/CAJo=hJtyof=HRy=2sLP0ng0uZ4=S-DpZ5dR1aF+VHVETKG20OQ@mail.gmail.com/

Original-idea-by: Shawn Pearce <spearce@spearce.org>
Based-on-patch-by: Han-Wen Nienhuys <hanwen@google.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-07 08:28:37 -08:00
Britton Leo Kerin
d8e08f0717 completion: bisect: recognize but do not complete view subcommand
The "view" alias for the visualize subcommand is neither completed nor
recognized.  It's undesirable to complete it because it's first letters
are the same as for visualize, making completion less rather than more
efficient without adding much in the way of interface discovery.
However, it needs to be recognized in order to enable log option
completion for it.

Recognize but do not complete the view command by creating and using
separate lists of completable_subcommands and all_subcommands.  Add
tests.

Signed-off-by: Britton Leo Kerin <britton.kerin@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-06 15:11:46 -08:00
Britton Leo Kerin
d115b87787 completion: bisect: complete log opts for visualize subcommand
Arguments passed to the "visualize" subcommand of git-bisect(1) get
forwarded to git-log(1). It thus supports the same options as git-log(1)
would, but our Bash completion script does not know to handle this.

Make completion of porcelain git-log options and option arguments to the
visualize subcommand work by calling __git_complete_log_opts when the
start of an option to the subcommand is seen (visualize doesn't support
any options besides the git-log options).  Add test.

Signed-off-by: Britton Leo Kerin <britton.kerin@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-06 15:11:46 -08:00
Britton Leo Kerin
41928aeb45 completion: bisect: complete missing --first-parent and - -no-checkout options
The --first-parent and --no-checkout options to the start subcommand of
git-bisect(1) are not completed.

Enable completion of the --first-parent and --no-checkout options to the
start subcommand.  Add test.

Signed-off-by: Britton Leo Kerin <britton.kerin@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-06 15:11:46 -08:00
Britton Leo Kerin
af8910a2d4 completion: bisect: complete custom terms and related options
git bisect supports the use of custom terms via the --term-(new|bad) and
--term-(old|good) options, but the completion code doesn't know about
these options or the new subcommands they define.

Add support for these options and the custom subcommands by checking for
BISECT_TERMS and adding them to the list of subcommands.  Add tests.

Signed-off-by: Britton Leo Kerin <britton.kerin@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-06 15:11:46 -08:00
Britton Leo Kerin
e1f74dd58b completion: bisect: complete bad, new, old, and help subcommands
The bad, new, old and help subcommands to git-bisect(1) are not
completed.

Add the bad, new, old, and help subcommands to the appropriate lists
such that the commands and their possible ref arguments are completed.
Add tests.

Signed-off-by: Britton Leo Kerin <britton.kerin@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-06 15:11:46 -08:00
Britton Leo Kerin
db489ea4f3 completion: tests: always use 'master' for default initial branch name
The default initial branch name can normally be configured using the
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME environment variable.  However,
when testing e.g. <rev> completion it's convenient to know the
exact initial branch name that will be used.

To achieve that without too much trouble it is considered sufficient
to force the default initial branch name to 'master' for all of
t9902-completion.sh.

Signed-off-by: Britton Leo Kerin <britton.kerin@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-06 15:11:45 -08:00
Junio C Hamano
097c28db78 Merge branch 'rj/test-with-leak-check'
More tests that are supposed to pass leak sanitizer are marked as such.

* rj/test-with-leak-check:
  t0080: mark as leak-free
  test-lib: check for TEST_PASSES_SANITIZE_LEAK
  t6113: mark as leak-free
  t5332: mark as leak-free
2024-02-06 14:31:22 -08:00
Junio C Hamano
c5887af55d Merge branch 'jc/t0091-with-unknown-git'
The test did not work when Git was built from a repository without
tags.

* jc/t0091-with-unknown-git:
  t0091: allow test in a repository without tags
2024-02-06 14:31:21 -08:00
Junio C Hamano
46b5d75c08 Merge branch 'ps/tests-with-ref-files-backend'
Prepare existing tests on refs to work better with non-default
backends.

* ps/tests-with-ref-files-backend:
  t: mark tests regarding git-pack-refs(1) to be backend specific
  t5526: break test submodule differently
  t1419: mark test suite as files-backend specific
  t1302: make tests more robust with new extensions
  t1301: mark test for `core.sharedRepository` as reffiles specific
  t1300: make tests more robust with non-default ref backends
2024-02-06 14:31:21 -08:00
Junio C Hamano
92e69dfb66 Merge branch 'jk/diff-external-with-no-index'
"git diff --no-index file1 file2" segfaulted while invoking the
external diff driver, which has been corrected.

* jk/diff-external-with-no-index:
  diff: handle NULL meta-info when spawning external diff
2024-02-06 14:31:21 -08:00
Patrick Steinhardt
d2058cb2f0 builtin/stash: report failure to write to index
The git-stash(1) command needs to write to the index for many of its
operations. When the index is locked by a concurrent writer it will thus
fail to operate, which is expected. What is not expected though is that
we do not print any error message at all in this case. The user can thus
easily miss the fact that the command didn't do what they expected it to
do and would be left wondering why that is.

Fix this bug and report failures to write to the index. Add tests for
the subcommands which hit the respective code paths.

While at it, unify error messages when writing to the index fails. The
chosen error message is already used in "builtin/stash.c".

Reported-by: moti sd <motisd8@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-06 12:08:38 -08:00
Taylor Blau
23c1e71369 pack-objects: enable multi-pack reuse via feature.experimental
Now that multi-pack reuse is supported, enable it via the
feature.experimental configuration in addition to the classic
`pack.allowPackReuse`.

This will allow more users to experiment with the new behavior who might
not otherwise be aware of the existing `pack.allowPackReuse`
configuration option.

The enum with values NO_PACK_REUSE, SINGLE_PACK_REUSE, and
MULTI_PACK_REUSE is defined statically in builtin/pack-objects.c's
compilation unit. We could hoist that enum into a scope visible from the
repository_settings struct, and then use that enum value in
pack-objects. Instead, define a single int that indicates what
pack-objects's default value should be to avoid additional unnecessary
code movement.

Though `feature.experimental` implies `pack.allowPackReuse=multi`, this
can still be overridden by explicitly setting the latter configuration
to either "single" or "false". Tests covering all of these cases are
showin t5332.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-05 15:27:01 -08:00
Taylor Blau
7c01878eeb t5332-multi-pack-reuse.sh: extract pack-objects helper functions
Most of the tests in t5332 perform some setup before repeating a common
refrain that looks like:

    : >trace2.txt &&
    GIT_TRACE2_EVENT="$PWD/trace2.txt" \
      git pack-objects --stdout --revs --all >/dev/null &&

    test_pack_reused $objects_nr <trace2.txt &&
    test_packs_reused $packs_nr <trace2.txt

The next commit will add more tests which repeat the above refrain.
Avoid duplicating this invocation even further and prepare for the
following commit by wrapping the above in a helper function called
`test_pack_objects_reused_all()`.

Introduce another similar function `test_pack_objects_reused`, which
expects to read a list of revisions over stdin for tests which need more
fine-grained control of the contents of the pack they generate.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-05 15:27:00 -08:00
Junio C Hamano
4904a4d08c t/Makefile: say the default target upfront
Similar to how 2731d048 (Makefile: say the default target upfront.,
2005-12-01) added the default target to the very beginning of the
main Makefile to prevent a random rule that happens to be defined
first in an included makefile fragments from becoming the default
target, protect this Makefile the same way.

This started to matter as we started to include config.mak.uname
and that included makefile fragment does more than defining Make
macros, unfortunately.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-02 18:41:35 -08:00
Junio C Hamano
cbcf61990f Merge branch 'jk/fetch-auto-tag-following-fix'
Fetching via protocol v0 over Smart HTTP transport sometimes failed
to correctly auto-follow tags.

* jk/fetch-auto-tag-following-fix:
  transport-helper: re-examine object dir after fetching
2024-02-02 11:31:51 -08:00
Junio C Hamano
9e189a03da Merge branch 'ad/custom-merge-placeholder-for-symbolic-pathnames'
The labels on conflict markers for the common ancestor, our version,
and the other version are available to custom 3-way merge driver
via %S, %X, and %Y placeholders.

* ad/custom-merge-placeholder-for-symbolic-pathnames:
  merge-ll: expose revision names to custom drivers
2024-02-02 11:31:50 -08:00
Junio C Hamano
35d94b55f7 Merge branch 'jc/reffiles-tests'
Tests on ref API are moved around to prepare for reftable.

* jc/reffiles-tests:
  t5312: move reffiles specific tests to t0601
  t4202: move reffiles specific tests to t0600
  t3903: make drop stash test ref backend agnostic
  t1503: move reffiles specific tests to t0600
  t1415: move reffiles specific tests to t0601
  t1410: move reffiles specific tests to t0600
  t1406: move reffiles specific tests to t0600
  t1405: move reffiles specific tests to t0601
  t1404: move reffiles specific tests to t0600
  t1414: convert test to use Git commands instead of writing refs manually
  remove REFFILES prerequisite for some tests in t1405 and t2017
  t3210: move to t0601
2024-02-02 11:31:50 -08:00
John Cai
0f8edf7317 index-pack: --fsck-objects to take an optional argument for fsck msgs
git-index-pack has a --strict option that can take an optional argument
to provide a list of fsck issues to change their severity.
--fsck-objects does not have such a utility, which would be useful if
one would like to be more lenient or strict on data integrity in a
repository.

Like --strict, allow --fsck-objects to also take a list of fsck msgs to
change the severity.

Remove the "For internal use only" note for --fsck-objects, and document
the option. This won't often be used by the normal end user, but it
turns out it is useful for Git forges like GitLab.

Reviewed-by: Christian Couder <christian.couder@gmail.com>
Signed-off-by: John Cai <johncai86@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-01 11:09:53 -08:00
John Cai
2811019f47 index-pack: test and document --strict=<msg-id>=<severity>...
5d477a334a (fsck (receive-pack): allow demoting errors to warnings,
2015-06-22) allowed a list of fsck msg to downgrade to be passed to
--strict. However this is a hidden argument that was not documented nor
tested. Though it is true that most users would not call this option
directly, (nor use index-pack for that matter) it is still useful to
document and test this feature.

Reviewed-by: Christian Couder <christian.couder@gmail.com>
Signed-off-by: John Cai <johncai86@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-02-01 11:09:53 -08:00
Jeff King
799d449105 t/Makefile: get UNIT_TESTS list from C sources
We decide on the set of unit tests to run by asking make to expand the
wildcard "t/unit-tests/bin/*". One unfortunate outcome of this is that
we'll run anything in that directory, even if it is leftover cruft from
a previous build. This isn't _quite_ as bad as it sounds, since in
theory the unit tests executables are self-contained (so if they passed
before, they'll pass even though they now have nothing to do with the
checked out version of Git). But at the very least it's wasteful, and if
they _do_ fail it can be quite confusing to understand why they are
being run at all.

This wildcarding presumably came from our handling of the regular
shell-script tests, which use $(wildcard t[0-9][0-9][0-9][0-9]-*.sh).
But the difference there is that those are actual tracked files. So if
you checkout a different commit, they'll go away. Whereas the contents
of unit-tests/bin are ignored (so not only do they stick around, but you
are not even warned of the stale files via "git status").

This patch fixes the situation by looking for the actual unit-test
source files and then massaging those names into the final executable
names. This has two additional benefits:

  1. It will notice if we failed to build one or more unit-tests for
     some reason (whereas the current code just runs whatever made it to
     the bin/ directory).

  2. The wildcard should avoid other build cruft, like the pdb files we
     worked around in 0df903d402 (unit-tests: do not mistake `.pdb`
     files for being executable, 2023-09-25).

Our new wildcard does make an assumption that unit tests are built from
C sources. It would be a bit cleaner if we consulted UNIT_TEST_PROGRAMS
from the top-level Makefile. But doing so is tricky unless we reorganize
that Makefile to split the source file lists into include-able subfiles.
That might be worth doing in general, but in the meantime, the
assumptions made by the wildcard here seems reasonable.

Note that we do need to include config.mak.uname either way, though, as
we need the value of $(X) to compute the correct executable names (which
would be true even if we had access to the top-level's UNIT_TEST_PROGRAMS
variable).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-31 14:41:12 -08:00
Junio C Hamano
a8bf3c0cac Merge branch 'kl/allow-working-in-dot-git-in-non-bare-repository'
The "disable repository discovery of a bare repository" check,
triggered by setting safe.bareRepository configuration variable to
'explicit', has been loosened to exclude the ".git/" directory inside
a non-bare repository from the check.  So you can do "cd .git &&
git cmd" to run a Git command that works on a bare repository without
explicitly specifying $GIT_DIR now.

* kl/allow-working-in-dot-git-in-non-bare-repository:
  setup: allow cwd=.git w/ bareRepository=explicit
2024-01-30 13:34:12 -08:00
Junio C Hamano
fa50e7a8a0 Merge branch 'jx/remote-archive-over-smart-http'
"git archive --remote=<remote>" learned to talk over the smart
http (aka stateless) transport.

* jx/remote-archive-over-smart-http:
  transport-helper: call do_take_over() in process_connect
  transport-helper: call do_take_over() in connect_helper
  http-backend: new rpc-service for git-upload-archive
  transport-helper: protocol v2 supports upload-archive
  remote-curl: supports git-upload-archive service
  transport-helper: no connection restriction in connect_helper
2024-01-30 13:34:12 -08:00
Junio C Hamano
e14c0ab176 Merge branch 'rj/advice-disable-how-to-disable'
All conditional "advice" messages show how to turn them off, which
becomes repetitive.  Setting advice.* configuration explicitly on
now omits the instruction part.

* rj/advice-disable-how-to-disable:
  advice: allow disabling the automatic hint in advise_if_enabled()
2024-01-30 13:34:12 -08:00
Junio C Hamano
2e77b83993 Merge branch 'rs/parse-options-with-keep-unknown-abbrev-fix'
"git diff --no-rename A B" did not disable rename detection but did
not trigger an error from the command line parser.

* rs/parse-options-with-keep-unknown-abbrev-fix:
  parse-options: simplify positivation handling
  parse-options: fully disable option abbreviation with PARSE_OPT_KEEP_UNKNOWN
2024-01-30 13:34:12 -08:00
Junio C Hamano
262fa1e968 Merge branch 'pb/ci-github-skip-logs-for-broken-tests'
GitHub CI update.

* pb/ci-github-skip-logs-for-broken-tests:
  ci(github): also skip logs of broken test cases
2024-01-30 13:34:11 -08:00
Junio C Hamano
3cb4384683 t0091: allow test in a repository without tags
The beginning of the [System Info] section, which should match the
"git version --build-options" output, may not identify our version
as "git version 2.whatever".  When built in a repository cloned
without tags, for example, "git version unknown.g00000000" can be a
legit version string.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-30 13:32:41 -08:00
Junio C Hamano
474df39f58 Merge branch 'al/t2400-depipe'
Coding style fix.

* al/t2400-depipe:
  t2400: avoid losing exit status to pipes
2024-01-29 16:03:01 -08:00
Junio C Hamano
40225ba8b4 Merge branch 'gt/t0024-style-fixes'
Coding style fix.

* gt/t0024-style-fixes:
  t0024: style fix
  t0024: avoid losing exit status to pipes
2024-01-29 16:03:00 -08:00
Junio C Hamano
d3bf8d32d3 Merge branch 'en/diffcore-delta-final-line-fix'
Rename detection logic ignored the final line of a file if it is an
incomplete line.

* en/diffcore-delta-final-line-fix:
  diffcore-delta: avoid ignoring final 'line' of file
2024-01-29 16:03:00 -08:00
Junio C Hamano
cf58f5920d Merge branch 'tc/show-ref-exists-fix'
Update to a new feature recently added, "git show-ref --exists".

* tc/show-ref-exists-fix:
  builtin/show-ref: treat directory as non-existing in --exists
2024-01-29 16:02:59 -08:00
Rubén Justo
03f72a4ed8 t0080: mark as leak-free
This test is leak-free since it was added in e137fe3b29 (unit tests: add
TAP unit test framework, 2023-11-09)

Let's mark it as leak-free to make sure it stays that way (and to reduce
noise when looking for other leak-free scripts after we fix some leaks).

Signed-off-by: Rubén Justo <rjusto@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-29 16:02:47 -08:00
Rubén Justo
92e209be78 test-lib: check for TEST_PASSES_SANITIZE_LEAK
TEST_PASSES_SANITIZE_LEAK must be set before sourcing test-lib.sh, as we
say in t/README:

   GIT_TEST_PASSING_SANITIZE_LEAK=true skips those tests that haven't
   declared themselves as leak-free by setting
   "TEST_PASSES_SANITIZE_LEAK=true" before sourcing "test-lib.sh". This
   test mode is used by the "linux-leaks" CI target.

   GIT_TEST_PASSING_SANITIZE_LEAK=check checks that our
   "TEST_PASSES_SANITIZE_LEAK=true" markings are current. Rather than
   skipping those tests that haven't set "TEST_PASSES_SANITIZE_LEAK=true"
   before sourcing "test-lib.sh" this mode runs them with
   "--invert-exit-code". This is used to check that there's a one-to-one
   mapping between "TEST_PASSES_SANITIZE_LEAK=true" and those tests that
   pass under "SANITIZE=leak". This is especially useful when testing a
   series that fixes various memory leaks with "git rebase -x".

In a recent commit we fixed a test where it was set after sourcing
test-lib.sh, leading to confusing results.

To prevent future oversights, let's add a simple check to ensure the
value for TEST_PASSES_SANITIZE_LEAK remains unchanged at test_done().

Signed-off-by: Rubén Justo <rjusto@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-29 14:21:53 -08:00
Rubén Justo
90a694a27e t6113: mark as leak-free
This test does not leak since a96015a517 (pack-bitmap: plug leak in
find_objects(), 2023-12-14) when the annotation
TEST_PASSES_SANITIZE_LEAK=true was also added.

Unfortunately it was added after test-lib.sh is sourced, which makes
GIT_TEST_PASSING_SANITIZE_LEAK=check error:

   $ make SANITIZE=leak GIT_TEST_PASSING_SANITIZE_LEAK=check test T=t6113-rev-list-bitmap-filters.sh
   ...
   make[2]: Entering directory '/tmp/git/git/t'
   *** t6113-rev-list-bitmap-filters.sh ***
   in GIT_TEST_PASSING_SANITIZE_LEAK=check mode, setting --invert-exit-code for TEST_PASSES_SANITIZE_LEAK != true
   ok 1 - set up bitmapped repo
   ok 2 - filters fallback to non-bitmap traversal
   ok 3 - blob:none filter
   ok 4 - blob:none filter with specified blob
   ok 5 - blob:limit filter
   ok 6 - blob:limit filter with specified blob
   ok 7 - tree:0 filter
   ok 8 - tree:0 filter with specified blob, tree
   ok 9 - tree:1 filter
   ok 10 - object:type filter
   ok 11 - object:type filter with --filter-provided-objects
   ok 12 - combine filter
   ok 13 - combine filter with --filter-provided-objects
   ok 14 - bitmap traversal with --unpacked
   # passed all 14 test(s)
   1..14
   # faking up non-zero exit with --invert-exit-code
   make[2]: *** [Makefile:68: t6113-rev-list-bitmap-filters.sh] Error 1
   make[2]: Leaving directory '/tmp/git/git/t'
   make[1]: *** [Makefile:55: test] Error 2
   make[1]: Leaving directory '/tmp/git/git/t'
   make: *** [Makefile:3212: test] Error 2

Let's move the annotation before sourcing test-lib.sh, to make
GIT_TEST_PASSING_SANITIZE_LEAK=check happy.

Signed-off-by: Rubén Justo <rjusto@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-29 14:20:36 -08:00
Rubén Justo
86b8254144 t5332: mark as leak-free
This test is leak-free since it was added in af626ac0e0 (pack-bitmap:
enable reuse from all bitmapped packs, 2023-12-14).

Let's mark it as leak-free to make sure it stays that way (and to reduce
noise when looking for other leak-free scripts after we fix some leaks).

Signed-off-by: Rubén Justo <rjusto@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-29 14:16:51 -08:00