summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2024-01-12Merge branch 'jx/sideband-chomp-newline-fix'Junio C Hamano4-10/+147
Sideband demultiplexer fixes. * jx/sideband-chomp-newline-fix: pkt-line: do not chomp newlines for sideband messages pkt-line: memorize sideband fragment in reader test-pkt-line: add option parser for unpack-sideband
2024-01-12Merge branch 'tb/multi-pack-verbatim-reuse'Junio C Hamano21-192/+1033
Streaming spans of packfile data used to be done only from a single, primary, pack in a repository with multiple packfiles. It has been extended to allow reuse from other packfiles, too. * tb/multi-pack-verbatim-reuse: (26 commits) t/perf: add performance tests for multi-pack reuse pack-bitmap: enable reuse from all bitmapped packs pack-objects: allow setting `pack.allowPackReuse` to "single" t/test-lib-functions.sh: implement `test_trace2_data` helper pack-objects: add tracing for various packfile metrics pack-bitmap: prepare to mark objects from multiple packs for reuse pack-revindex: implement `midx_pair_to_pack_pos()` pack-revindex: factor out `midx_key_to_pack_pos()` helper midx: implement `midx_preferred_pack()` git-compat-util.h: implement checked size_t to uint32_t conversion pack-objects: include number of packs reused in output pack-objects: prepare `write_reused_pack_verbatim()` for multi-pack reuse pack-objects: prepare `write_reused_pack()` for multi-pack reuse pack-objects: pass `bitmapped_pack`'s to pack-reuse functions pack-objects: keep track of `pack_start` for each reuse pack pack-objects: parameterize pack-reuse routines over a single pack pack-bitmap: return multiple packs via `reuse_partial_packfile_from_bitmap()` pack-bitmap: simplify `reuse_partial_packfile_from_bitmap()` signature ewah: implement `bitmap_is_empty()` pack-bitmap: pass `bitmapped_pack` struct to pack-reuse functions ...
2024-01-12Merge branch 'jk/t1006-cat-file-objectsize-disk'Junio C Hamano1-0/+36
Test update. * jk/t1006-cat-file-objectsize-disk: t1006: prefer shell loop to awk for packed object sizes t1006: add tests for %(objectsize:disk)
2024-01-12Merge branch 'jw/builtin-objectmode-attr'Junio C Hamano5-3/+210
The builtin_objectmode attribute is populated for each path without adding anything in .gitattributes files, which would be useful in magic pathspec, e.g., ":(attr:builtin_objectmode=100755)" to limit to executables. * jw/builtin-objectmode-attr: attr: add builtin objectmode values support
2024-01-12Merge branch 'js/contributor-docs-updates'Junio C Hamano2-11/+24
Doc update. * js/contributor-docs-updates: SubmittingPatches: hyphenate non-ASCII SubmittingPatches: clarify GitHub artifact format SubmittingPatches: clarify GitHub visual SubmittingPatches: provide tag naming advice SubmittingPatches: update extra tags list SubmittingPatches: discourage new trailers SubmittingPatches: drop ref to "What's in git.git" CodingGuidelines: write punctuation marks CodingGuidelines: move period inside parentheses
2024-01-12strvec: use correct member name in commentsLinus Arver1-4/+4
In d70a9eb611 (strvec: rename struct fields, 2020-07-28), we renamed the "argv" member to "v". In the same patch we also did the following rename in strvec.c: -void strvec_pushv(struct strvec *array, const char **argv) +void strvec_pushv(struct strvec *array, const char **items) and it appears that this s/argv/items operation was erroneously applied to strvec.h. Rename "items" to "v". Signed-off-by: Linus Arver <linusa@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-12messages: mark some strings with "up-to-date" not to touchJunio C Hamano3-0/+4
The treewide clean-up of "up-to-date" strings done in 7560f547 (treewide: correct several "up-to-date" to "up to date", 2017-08-23) deliberately left some out, but unlike the lines that were changed by the commit, the lines that were deliberately left untouched by the commit is impossible to ask "git blame" to link back to the commit that did not touch them. Let's do the second best thing, leave a short comment near them explaining why those strings should not be modified or localized. Signed-off-by: Junio C Hamano <gitster@pobox.com> [es: make in-code comment more developer-friendly] Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-12t5541: remove lockfile creationJustin Tobler1-13/+5
To create error conditions, some tests set up reference locks by directly creating its lockfile. While this works for the files reference backend, this approach is incompatible with the reftable backend. Refactor the test to create a d/f conflict via git-update-ref(1) instead so that the test is reference backend agnostic. Signed-off-by: Justin Tobler <jltobler@gmail.com> Acked-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-12t1401: remove lockfile creationJustin Tobler1-3/+2
To create error conditions, some tests set up reference locks by directly creating its lockfile. While this works for the files reference backend, this approach is incompatible with the reftable backend. Refactor the test to create a d/f conflict via git-symbolic-ref(1) instead so that the test is reference backend agnostic. Signed-off-by: Justin Tobler <jltobler@gmail.com> Acked-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-11branch: make the advice to force-deleting a conditional oneRubén Justo4-3/+10
The error message we show when the user tries to delete a not fully merged branch describes the error and gives a hint to the user: error: the branch 'foo' is not fully merged. If you are sure you want to delete it, run 'git branch -D foo'. Let's move the hint part so that it is displayed using the advice machinery: error: the branch 'foo' is not fully merged hint: If you are sure you want to delete it, run 'git branch -D foo' hint: Disable this message with "git config advice.forceDeleteBranch false" Signed-off-by: Rubén Justo <rjusto@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-11advice: fix an unexpected leading spaceRubén Justo1-1/+1
This space was introduced, presumably unintentionally, in b3b18d1621 (advice: revamp advise API, 2020-03-02) I notice this space due to confuse diff outputs while doing some changes to enum advice_type. As a reference, a recent change we have to that enum is: $ git show 35f0383 ... diff --git a/advice.h b/advice.h index 0f584163f5..2affbe1426 100644 --- a/advice.h +++ b/advice.h @@ -49,6 +49,7 @@ struct string_list; ADVICE_UPDATE_SPARSE_PATH, ADVICE_WAITING_FOR_EDITOR, ADVICE_SKIPPED_CHERRY_PICKS, + ADVICE_WORKTREE_ADD_ORPHAN, }; Note the hunk header, instead of a much more expected: @@ -49,6 +49,7 @@ enum advice_type Signed-off-by: Rubén Justo <rjusto@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-11advice: sort the advice related listsRubén Justo3-91/+88
Let's keep the advice related lists sorted to make them more digestible. A multi-line comment has also been changed; that produces the unexpected 'insertion != deletion' in this supposedly 'only sort lines' commit. Signed-off-by: Rubén Justo <rjusto@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-11git-p4: stop reaching into the refdbPatrick Steinhardt1-1/+2
The git-p4 tool creates a bunch of temporary branches that share a common prefix "refs/git-p4-tmp/". These branches get cleaned up via git-update-ref(1) after the import has finished. Once done, we try to manually remove the now supposedly-empty ".git/refs/git-p4-tmp/" directory. This last step can fail in case there still are any temporary branches around that we failed to delete because `os.rmdir()` refuses to delete a non-empty directory. It can thus be seen as kind of a sanity check to verify that we really did delete all temporary branches. Another failure mode though is when the directory didn't exist in the first place, which can be the case when using an alternate ref backend like the upcoming "reftable" backend. Convert the code to instead use git-for-each-ref(1) to verify that there are no more temporary branches around. This works alright with alternate ref backends while retaining the sanity check that we really did prune all temporary branches. This is a modification in behaviour for the "files" backend because the empty directory does not get deleted anymore. But arguably we should not care about such implementation details of the ref backend anyway, and this should not cause any user-visible change in behaviour. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-11reftable/blocksource: use mmap to read tablesPatrick Steinhardt1-15/+7
The blocksource interface provides an interface to read blocks from a reftable table. This interface is implemented using read(3P) calls on the underlying file descriptor. While this works alright, this pattern is very inefficient when repeatedly querying the reftable stack for one or more refs. This inefficiency can mostly be attributed to the fact that we often need to re-read the same blocks over and over again, and every single time we need to call read(3P) again. A natural fit in this context is to use mmap(3P) instead of read(3P), which has a bunch of benefits: - We do not need to come up with a caching strategy for some of the blocks as this will be handled by the kernel already. - We can avoid the overhead of having to call into the read(3P) syscall repeatedly. - We do not need to allocate returned blocks repeatedly, but can instead hand out pointers into the mmapped region directly. Using mmap comes with a significant drawback on Windows though, because mmapped files cannot be deleted and neither is it possible to rename files onto an mmapped file. But for one, the reftable library gracefully handles the case where auto-compaction cannot delete a still-open stack already and ignores any such errors. Also, `reftable_stack_clean()` will prune stale tables which are not referenced by "tables.list" anymore so that those files can eventually be pruned. And second, we never rewrite already-written stacks, so it does not matter that we cannot rename a file over an mmaped file, either. Another unfortunate property of mmap is that it is not supported by all systems. But given that the size of reftables should typically be rather limited (megabytes at most in the vast majority of repositories), we can use the fallback implementation provided by `git_mmap()` which reads the whole file into memory instead. This is the same strategy that the "packed" backend uses. While this change doesn't significantly improve performance in the case where we're seeking through stacks once (like e.g. git-for-each-ref(1) would). But it does speed up usecases where there is lots of random access to refs, e.g. when writing. The following benchmark demonstrates these savings with git-update-ref(1) creating N refs in an otherwise empty repository: Benchmark 1: update-ref: create many refs (refcount = 1, revision = HEAD~) Time (mean ± σ): 5.1 ms ± 0.2 ms [User: 2.5 ms, System: 2.5 ms] Range (min … max): 4.8 ms … 7.1 ms 111 runs Benchmark 2: update-ref: create many refs (refcount = 100, revision = HEAD~) Time (mean ± σ): 14.8 ms ± 0.5 ms [User: 7.1 ms, System: 7.5 ms] Range (min … max): 14.1 ms … 18.7 ms 84 runs Benchmark 3: update-ref: create many refs (refcount = 10000, revision = HEAD~) Time (mean ± σ): 926.4 ms ± 5.6 ms [User: 448.5 ms, System: 477.7 ms] Range (min … max): 920.0 ms … 936.1 ms 10 runs Benchmark 4: update-ref: create many refs (refcount = 1, revision = HEAD) Time (mean ± σ): 5.0 ms ± 0.2 ms [User: 2.4 ms, System: 2.5 ms] Range (min … max): 4.7 ms … 5.4 ms 111 runs Benchmark 5: update-ref: create many refs (refcount = 100, revision = HEAD) Time (mean ± σ): 10.5 ms ± 0.2 ms [User: 5.0 ms, System: 5.3 ms] Range (min … max): 10.0 ms … 10.9 ms 93 runs Benchmark 6: update-ref: create many refs (refcount = 10000, revision = HEAD) Time (mean ± σ): 529.6 ms ± 9.1 ms [User: 268.0 ms, System: 261.4 ms] Range (min … max): 522.4 ms … 547.1 ms 10 runs Summary update-ref: create many refs (refcount = 1, revision = HEAD) ran 1.01 ± 0.06 times faster than update-ref: create many refs (refcount = 1, revision = HEAD~) 2.08 ± 0.07 times faster than update-ref: create many refs (refcount = 100, revision = HEAD) 2.95 ± 0.14 times faster than update-ref: create many refs (refcount = 100, revision = HEAD~) 105.33 ± 3.76 times faster than update-ref: create many refs (refcount = 10000, revision = HEAD) 184.24 ± 5.89 times faster than update-ref: create many refs (refcount = 10000, revision = HEAD~) Theoretically, we could also replicate the strategy of the "packed" backend where small tables are read into memory instead of using mmap. Benchmarks did not confirm that this has a performance benefit though. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-11reftable/blocksource: refactor code to match our coding stylePatrick Steinhardt1-9/+8
Refactor `reftable_block_source_from_file()` to match our coding style better. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-11reftable/stack: use stat info to avoid re-reading stack listPatrick Steinhardt3-1/+13
Whenever we call into the refs interfaces we potentially have to reload refs in case they have been concurrently modified, either in-process or externally. While this happens somewhat automatically for loose refs because we simply try to re-read the files, the "packed" backend will reload its snapshot of the packed-refs file in case its stat info has changed since last reading it. In the reftable backend we have a similar mechanism that is provided by `reftable_stack_reload()`. This function will read the list of stacks from "tables.list" and, if they have changed from the currently stored list, reload the stacks. This is heavily inefficient though, as we have to check whether the stack is up-to-date on basically every read and thus keep on re-reading the file all the time even if it didn't change at all. We can do better and use the same stat(3P)-based mechanism that the "packed" backend uses. Instead of reading the file, we will only open the file descriptor, fstat(3P) it, and then compare the info against the cached value from the last time we have updated the stack. This should always work alright because "tables.list" is updated atomically via a rename, so even if the ctime or mtime wasn't granular enough to identify a change, at least the inode number or file size should have changed. This change significantly speeds up operations where many refs are read, like when using git-update-ref(1). The following benchmark creates N refs in an otherwise-empty repository via `git update-ref --stdin`: Benchmark 1: update-ref: create many refs (refcount = 1, revision = HEAD~) Time (mean ± σ): 5.1 ms ± 0.2 ms [User: 2.4 ms, System: 2.6 ms] Range (min … max): 4.8 ms … 7.2 ms 109 runs Benchmark 2: update-ref: create many refs (refcount = 100, revision = HEAD~) Time (mean ± σ): 19.1 ms ± 0.9 ms [User: 8.9 ms, System: 9.9 ms] Range (min … max): 18.4 ms … 26.7 ms 72 runs Benchmark 3: update-ref: create many refs (refcount = 10000, revision = HEAD~) Time (mean ± σ): 1.336 s ± 0.018 s [User: 0.590 s, System: 0.724 s] Range (min … max): 1.314 s … 1.373 s 10 runs Benchmark 4: update-ref: create many refs (refcount = 1, revision = HEAD) Time (mean ± σ): 5.1 ms ± 0.2 ms [User: 2.4 ms, System: 2.6 ms] Range (min … max): 4.8 ms … 7.2 ms 109 runs Benchmark 5: update-ref: create many refs (refcount = 100, revision = HEAD) Time (mean ± σ): 14.8 ms ± 0.2 ms [User: 7.1 ms, System: 7.5 ms] Range (min … max): 14.2 ms … 15.2 ms 82 runs Benchmark 6: update-ref: create many refs (refcount = 10000, revision = HEAD) Time (mean ± σ): 927.6 ms ± 5.3 ms [User: 437.8 ms, System: 489.5 ms] Range (min … max): 919.4 ms … 936.4 ms 10 runs Summary update-ref: create many refs (refcount = 1, revision = HEAD) ran 1.00 ± 0.07 times faster than update-ref: create many refs (refcount = 1, revision = HEAD~) 2.89 ± 0.14 times faster than update-ref: create many refs (refcount = 100, revision = HEAD) 3.74 ± 0.25 times faster than update-ref: create many refs (refcount = 100, revision = HEAD~) 181.26 ± 8.30 times faster than update-ref: create many refs (refcount = 10000, revision = HEAD) 261.01 ± 12.35 times faster than update-ref: create many refs (refcount = 10000, revision = HEAD~) Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-11reftable/stack: refactor reloading to use file descriptorPatrick Steinhardt1-3/+18
We're about to introduce a stat(3P)-based caching mechanism to reload the list of stacks only when it has changed. In order to avoid race conditions this requires us to have a file descriptor available that we can use to call fstat(3P) on. Prepare for this by converting the code to use `fd_read_lines()` so that we have the file descriptor readily available. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-11reftable/stack: refactor stack reloading to have common exit pathPatrick Steinhardt1-43/+41
The `reftable_stack_reload_maybe_reuse()` function is responsible for reloading the reftable list from disk. The function is quite hard to follow though because it has a bunch of different exit paths, many of which have to free the same set of resources. Refactor the function to have a common exit path. While at it, touch up the style of this function a bit to match our usual coding style better. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-10gitweb: die when a configuration file cannot be readMarcelo Roberto Jimenez1-1/+3
Fix a possibility of a permission to access error go unnoticed. Perl uses two different variables to manage errors from a "do $filename" construct. One is $@, which is set in this case when do is unable to compile the file. The other is $!, which is set in case do cannot read the file. The current code only checks "$@", which means a configuration file passed to GitWeb that is not readable by the server process does not cause it to "die". Make sure we also check and act on "$!" to fix this. Signed-off-by: Marcelo Roberto Jimenez <marcelo.jimenez@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-10doc: refer to pathspec instead of pathBritton Leo Kerin1-2/+2
Signed-off-by: Britton Leo Kerin <britton.kerin@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-10doc: use singular form of repeatable path argBritton Leo Kerin1-1/+1
This is more correct because the <path>... doc syntax already indicates that the arg is "array-type". It's how other tools do it. Finally, the later document text mentions 'path' arguments, while it doesn't mention 'paths'. Signed-off-by: Britton Leo Kerin <britton.kergin@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-10t4129: prevent loss of exit code due to the use of pipesChandra Pratap1-2/+4
Piping the output of git commands like git-ls-files to another command (grep in this case) hides the exit code returned by these commands. Prevent this by storing the output of git-ls-files to a temporary file and then "grep-ping" from that file. Replace grep with test_grep as the latter is more verbose when it fails. Signed-off-by: Chandra Pratap <chandrapratap3519@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-10mingw: give more details about unsafe directory's ownershipSören Krecker1-13/+57
Add domain/username in error message, if owner sid of repository and user sid are not equal on windows systems. Old error message: ''' fatal: detected dubious ownership in repository at 'C:/Users/test/source/repos/git' 'C:/Users/test/source/repos/git' is owned by: 'S-1-5-21-571067702-4104414259-3379520149-500' but the current user is: 'S-1-5-21-571067702-4104414259-3379520149-1001' To add an exception for this directory, call: git config --global --add safe.directory C:/Users/test/source/repos/git ''' New error message: ''' fatal: detected dubious ownership in repository at 'C:/Users/test/source/repos/git' 'C:/Users/test/source/repos/git' is owned by: DESKTOP-L78JVA6/Administrator (S-1-5-21-571067702-4104414259-3379520149-500) but the current user is: DESKTOP-L78JVA6/test (S-1-5-21-571067702-4104414259-3379520149-1001) To add an exception for this directory, call: git config --global --add safe.directory C:/Users/test/source/repos/git ''' Signed-off-by: Sören Krecker <soekkle@freenet.de> Acked-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08The sixth batchJunio C Hamano1-0/+15
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08Merge branch 'rs/mem-pool-improvements'Junio C Hamano3-6/+36
MemPool allocator fixes. * rs/mem-pool-improvements: mem-pool: simplify alignment calculation mem-pool: fix big allocations
2024-01-08Merge branch 'rs/fast-import-simplify-mempool-allocation'Junio C Hamano1-2/+1
Code simplification. * rs/fast-import-simplify-mempool-allocation: fast-import: use mem_pool_calloc()
2024-01-08Merge branch 'en/sparse-checkout-eoo'Junio C Hamano2-7/+10
"git sparse-checkout (add|set) --[no-]cone --end-of-options" did not handle "--end-of-options" correctly after a recent update. * en/sparse-checkout-eoo: sparse-checkout: be consistent with end of options markers
2024-01-08Merge branch 'jc/sparse-checkout-set-default-fix'Junio C Hamano1-1/+1
"git sparse-checkout set" added default patterns even when the patterns are being fed from the standard input, which has been corrected. * jc/sparse-checkout-set-default-fix: sparse-checkout: use default patterns for 'set' only !stdin
2024-01-08Merge branch 'en/header-cleanup'Junio C Hamano191-335/+25
Remove unused header "#include". * en/header-cleanup: treewide: remove unnecessary includes in source files treewide: add direct includes currently only pulled in transitively trace2/tr2_tls.h: remove unnecessary include submodule-config.h: remove unnecessary include pkt-line.h: remove unnecessary include line-log.h: remove unnecessary include http.h: remove unnecessary include fsmonitor--daemon.h: remove unnecessary includes blame.h: remove unnecessary includes archive.h: remove unnecessary include treewide: remove unnecessary includes in source files treewide: remove unnecessary includes from header files
2024-01-08Merge branch 'ml/doc-merge-updates'Junio C Hamano1-35/+35
Doc update. * ml/doc-merge-updates: Documentation/git-merge.txt: use backticks for command wrapping Documentation/git-merge.txt: fix reference to synopsis
2024-01-08Merge branch 'jc/archive-list-with-extra-args'Junio C Hamano2-0/+12
"git archive --list extra garbage" silently ignored excess command line parameters, which has been corrected. * jc/archive-list-with-extra-args: archive: "--list" does not take further options
2024-01-08fetch: add new config option fetch.allTamino Bauknecht4-3/+186
Introduce a boolean configuration option fetch.all which allows to fetch all available remotes by default. The config option can be overridden by explicitly specifying a remote or by using --no-all. The behavior for --all is unchanged and calling git-fetch with --all and a remote will still result in an error. Additionally, describe the configuration variable in the config documentation and implement new tests to cover the expected behavior. Also add --no-all to the command-line documentation of git-fetch. Signed-off-by: Tamino Bauknecht <dev@tb6.eu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08builtin/worktree: create refdb via ref backendPatrick Steinhardt1-26/+22
When creating a worktree we create the worktree's ref database manually by first writing a "HEAD" file so that the directory is recognized as a Git repository by other commands, and then running git-update-ref(1) or git-symbolic-ref(1) to write the actual value. But while this is fine for the files backend, this logic simply assumes too much about how the ref backend works and will leave behind an invalid ref database once any other ref backend lands. Refactor the code to instead use `refs_init_db()` to initialize the ref database so that git-worktree(1) itself does not need to know about how to initialize it. This will allow future ref backends to customize how the per-worktree ref database is set up. Furthermore, as we now already have a worktree ref store around, we can also avoid spawning external commands to write the HEAD reference and instead use the refs API to do so. Note that we do not have an equivalent to passing the `--quiet` flag to git-symbolic-ref(1) as we did before. This flag does not have an effect anyway though, as git-symbolic-ref(1) only honors it when reading a symref, but never when writing one. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08worktree: expose interface to look up worktree by namePatrick Steinhardt2-11/+28
Our worktree interfaces do not provide a way to look up a worktree by its name. Expose `get_linked_worktree()` to allow for this usecase. As callers are responsible for freeing this worktree, introduce a new function `free_worktree()` that does so. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08builtin/worktree: move setup of commondir file earlierPatrick Steinhardt1-3/+4
Shuffle around how we create supporting worktree files so that we first ensure that the worktree has all link files ("gitdir", "commondir") before we try to initialize the ref database by writing "HEAD". This will be required by a subsequent commit where we start to initialize the ref database via `refs_init_db()`, which will require an initialized `struct worktree *`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08refs/files: skip creation of "refs/{heads,tags}" for worktreesPatrick Steinhardt2-8/+16
The files ref backend will create both "refs/heads" and "refs/tags" in the Git directory. While this logic makes sense for normal repositories, it does not for worktrees because those refs are "common" refs that would always be contained in the main repository's ref database. Introduce a new flag telling the backend that it is expected to create a per-worktree ref database and skip creation of these dirs in the files backend when the flag is set. No other backends (currently) need worktree-specific logic, so this is the only required change to start creating per-worktree ref databases via `refs_init_db()`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08setup: move creation of "refs/" into the files backendPatrick Steinhardt2-15/+17
When creating the ref database we unconditionally create the "refs/" directory in "setup.c". This is a mandatory prerequisite for all Git repositories regardless of the ref backend in use, because Git will be unable to detect the directory as a repository if "refs/" doesn't exist. We are about to add another new caller that will want to create a ref database when creating worktrees. We would require the same logic to create the "refs/" directory even though the caller really should not care about such low-level details. Ideally, the ref database should be fully initialized after calling `refs_init_db()`. Move the code to create the directory into the files backend itself to make it so. This means that future ref backends will also need to have equivalent logic around to ensure that the directory exists, but it seems a lot more sensible to have it this way round than to require callers to create the directory themselves. An alternative to this would be to create "refs/" in `refs_init_db()` directly. This feels conceptually unclean though as the creation of the refdb is now cluttered across different callsites. Furthermore, both the "files" and the upcoming "reftable" backend write backend-specific data into the "refs/" directory anyway, so splitting up this logic would only make it harder to reason about. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08refs: prepare `refs_init_db()` for initializing worktree refsPatrick Steinhardt7-10/+13
The purpose of `refs_init_db()` is to initialize the on-disk files of a new ref database. The function is quite inflexible right now though, as callers can neither specify the `struct ref_store` nor can they pass any flags. Refactor the interface to accept both of these. This will be required so that we can start initializing per-worktree ref databases via the ref backend instead of open-coding the initialization in "worktree.c". Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08Merge branch 'ps/refstorage-extension' into ps/worktree-refdb-initializationJunio C Hamano34-121/+479
* ps/refstorage-extension: t9500: write "extensions.refstorage" into config builtin/clone: introduce `--ref-format=` value flag builtin/init: introduce `--ref-format=` value flag builtin/rev-parse: introduce `--show-ref-format` flag t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvar setup: introduce GIT_DEFAULT_REF_FORMAT envvar setup: introduce "extensions.refStorage" extension setup: set repository's formats on init setup: start tracking ref storage format refs: refactor logic to look up storage backends worktree: skip reading HEAD when repairing worktrees t: introduce DEFAULT_REPO_FORMAT prereq builtin/clone: create the refdb with the correct object format builtin/clone: skip reading HEAD when retrieving remote builtin/clone: set up sparse checkout later builtin/clone: fix bundle URIs with mismatching object formats remote-curl: rediscover repository when fetching refs setup: allow skipping creation of the refdb setup: extract function to create the refdb
2024-01-08ci: add job performing static analysis on GitLab CIPatrick Steinhardt2-1/+16
Our GitHub Workflows definitions have a static analysis job that runs the following tasks: - Coccinelle to check for suggested refactorings. - `make hdr-check` to check for missing includes or forward declarations in our header files. - `make check-pot` to check our translations for issues. - `./ci/check-directional-formatting.bash` to check whether our sources contain any Unicode directional formatting code points. Add an equivalent job to our GitLab CI definitions. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08git-prompt: stop manually parsing HEAD with unknown ref formatsPatrick Steinhardt1-7/+24
We're manually parsing the HEAD reference in git-prompt to figure out whether it is a symbolic or direct reference. This makes it intimately tied to the on-disk format we use to store references and will stop working once we gain additional reference backends in the Git project. Ideally, we would refactor the code to exclusively use plumbing tools to read refs such that we do not have to care about the on-disk format at all. Unfortunately though, spawning processes can be quite expensive on some systems like Windows. As the Git prompt logic may be executed quite frequently we try very hard to spawn as few processes as possible. This refactoring is thus out of question for now. Instead, condition the logic on the repository's ref format: if the repo uses the the "files" backend we can continue to use the old logic and read the respective files from disk directly. If it's anything else, then we use git-symbolic-ref(1) to read the value of HEAD. This change makes the Git prompt compatible with the upcoming "reftable" format. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-08Merge branch 'ps/refstorage-extension' into ps/prompt-parse-HEAD-futureproofJunio C Hamano29-35/+334
* ps/refstorage-extension: t9500: write "extensions.refstorage" into config builtin/clone: introduce `--ref-format=` value flag builtin/init: introduce `--ref-format=` value flag builtin/rev-parse: introduce `--show-ref-format` flag t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvar setup: introduce GIT_DEFAULT_REF_FORMAT envvar setup: introduce "extensions.refStorage" extension setup: set repository's formats on init setup: start tracking ref storage format refs: refactor logic to look up storage backends worktree: skip reading HEAD when repairing worktrees t: introduce DEFAULT_REPO_FORMAT prereq
2024-01-08branch: clarify <oldbranch> termRubén Justo1-1/+2
Since 52d59cc645 (branch: add a --copy (-c) option to go with --move (-m), 2017-06-18) <oldbranch> is used in more operations than just -m. Let's also clarify what we do if <oldbranch> is omitted. Signed-off-by: Rubén Justo <rjusto@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-05rebase: clarify --reschedule-failed-exec defaultIllia Bobyr1-7/+10
Documentation should mention the default behavior. It is better to explain the persistent nature of the --reschedule-failed-exec flag from the user standpoint, rather than from the implementation standpoint. Signed-off-by: Illia Bobyr <illia.bobyr@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-05index-pack: spawn threads atomicallyJeff King1-0/+2
The t5309 script triggers a racy false positive with SANITIZE=leak on a multi-core system. Running with "--stress --run=6" usually fails within 10 seconds or so for me, complaining with something like: + git index-pack --fix-thin --stdin fatal: REF_DELTA at offset 46 already resolved (duplicate base 01d7713666f4de822776c7622c10f1b07de280dc?) ================================================================= ==3904583==ERROR: LeakSanitizer: detected memory leaks Direct leak of 32 byte(s) in 1 object(s) allocated from: #0 0x7fa790d01986 in __interceptor_realloc ../../../../src/libsanitizer/lsan/lsan_interceptors.cpp:98 #1 0x7fa790add769 in __pthread_getattr_np nptl/pthread_getattr_np.c:180 #2 0x7fa790d117c5 in __sanitizer::GetThreadStackTopAndBottom(bool, unsigned long*, unsigned long*) ../../../../src/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp:150 #3 0x7fa790d11957 in __sanitizer::GetThreadStackAndTls(bool, unsigned long*, unsigned long*, unsigned long*, unsigned long*) ../../../../src/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp:598 #4 0x7fa790d03fe8 in __lsan::ThreadStart(unsigned int, unsigned long long, __sanitizer::ThreadType) ../../../../src/libsanitizer/lsan/lsan_posix.cpp:51 #5 0x7fa790d013fd in __lsan_thread_start_func ../../../../src/libsanitizer/lsan/lsan_interceptors.cpp:440 #6 0x7fa790adc3eb in start_thread nptl/pthread_create.c:444 #7 0x7fa790b5ca5b in clone3 ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81 SUMMARY: LeakSanitizer: 32 byte(s) leaked in 1 allocation(s). Aborted What happens is this: 0. We construct a bogus pack with a duplicate object in it and trigger index-pack. 1. We spawn a bunch of worker threads to resolve deltas (on my system it is 16 threads). 2. One of the threads sees the duplicate object and bails by calling exit(), taking down all of the threads. This is expected and is the point of the test. 3. At the time exit() is called, we may still be spawning threads from the main process via pthread_create(). LSan hooks thread creation to update its book-keeping; it has to know where each thread's stack is (so it can find entry points for reachable memory). So it calls pthread_getattr_np() to get information about the new thread. That may allocate memory that must be freed with a matching call to pthread_attr_destroy(). Probably LSan does that immediately, but if you're unlucky enough, the exit() will happen while it's between those two calls, and the allocated pthread_attr_t appears as a leak. This isn't a real leak. It's not even in our code, but rather in the LSan instrumentation code. So we could just ignore it. But the false positive can cause people to waste time tracking it down. It's possibly something that LSan could protect against (e.g., cover the getattr/destroy pair with a mutex, and then in the final post-exit() check for leaks try to take the same mutex). But I don't know enough about LSan to say if that's a reasonable approach or not (or if my analysis is even completely correct). In the meantime, it's pretty easy to avoid the race by making creation of the worker threads "atomic". That is, we'll spawn all of them before letting any of them start to work. That's easy to do because we already have a work_lock() mutex for handing out that work. If the main process takes it, then all of the threads will immediately block until we've finished spawning and released it. This shouldn't make any practical difference for non-LSan runs. The thread spawning is quick, and could happen before any worker thread gets scheduled anyway. Probably other spots that use threads are subject to the same issues. But since we have to manually insert locking (and since this really is kind of a hack), let's not bother with them unless somebody experiences a similar racy false-positive in practice. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-05commit-graph: retain commit slab when closing NULL commit_graphJeff King2-1/+5
This fixes a regression introduced in ac6d45d11f (commit-graph: move slab-clearing to close_commit_graph(), 2023-10-03), in which running: git -c fetch.writeCommitGraph=true fetch --recurse-submodules multiple times in a freshly cloned repository causes a segfault. What happens in the second (and subsequent) runs is this: 1. We make a "struct commit" for any ref tips which we're storing (even if we already have them, they still go into FETCH_HEAD). Because the first run will have created a commit graph, we'll find those commits in the graph. The commit struct is therefore created with a NULL "maybe_tree" entry, because we can load its oid from the graph later. But to do that we need to remember that we got the commit from the graph, which is recorded in a global commit_graph_data_slab object. 2. Because we're using --recurse-submodules, we'll try to fetch each of the possible submodules. That implies creating a separate "struct repository" in-process for each submodule, which will require a later call to repo_clear(). The call to repo_clear() calls raw_object_store_clear(), which in turn calls close_object_store(), which in turn calls close_commit_graph(). And the latter frees the commit graph data slab. 3. Later, when trying to write out a new commit graph, we'll ask for their tree oid via get_commit_tree_oid(), which will see that the object is parsed but with a NULL maybe_tree field. We'd then usually pull it from the graph file, but because the slab was cleared, we don't realize that we can do so! We end up returning NULL and segfaulting. (It seems questionable that we'd write a graph entry for such a commit anyway, since we know we already have one. I didn't double-check, but that may simply be another side effect of having cleared the slab). The bug is in step (2) above. We should not be clearing the slab when cleaning up the submodule repository structs. Prior to ac6d45d11f, we did not do so because it was done inside a helper function that returned early when it saw NULL. So the behavior change from that commit is that we'll now _always_ clear the slab via repo_clear(), even if the repository being closed did not have a commit graph (and thus would have a NULL commit_graph struct). The most immediate fix is to add in a NULL check in close_commit_graph(), making it a true noop when passed in an object_store with a NULL commit_graph (it's OK to just return early, since the rest of its code is already a noop when passed NULL). That restores the pre-ac6d45d11f behavior. And that's what this patch does, along with a test that exercises it (we already have a test that uses submodules along with fetch.writeCommitGraph, but the bug only triggers when there is a subsequent fetch and when that fetch uses --recurse-submodules). So that fixes the regression in the least-risky way possible. I do think there's some fragility here that we might want to follow up on. We have a global commit_graph_data_slab that contains graph positions, and our global commit structs depend on the that slab remaining valid. But close_commit_graph() is just about closing _one_ object store's graph. So it's dangerous to call that function and clear the slab without also throwing away any "struct commit" we might have parsed that depends on it. Which at first glance seems like a bug we could already trigger. In the situation described here, there is no commit graph in the submodule repository, so our commit graph is NULL (in fact, in our test script there is no submodule repo at all, so we immediately return from repo_init() and call repo_clear() only to free up memory). But what would happen if there was one? Wouldn't we see a non-NULL commit_graph entry, and then clear the global slab anyway? The answer is "no", but for very bizarre reasons. Remember that repo_clear() calls raw_object_store_clear(), which then calls close_object_store() and thus close_commit_graph(). But before it does so, raw_object_store_clear() does something else: it frees the commit graph and sets it to NULL! So by this code path we'll _never_ see a non-NULL commit_graph struct, and thus never clear the slab. So it happens to work out. But it still seems questionable to me that we would clear a global slab (which might still be in use) when closing the commit graph. This clearing comes from 957ba814bf (commit-graph: when closing the graph, also release the slab, 2021-09-08), and was fixing a case where we really did need it to be closed (and in that case we presumably call close_object_store() more directly). So I suspect there may still be a bug waiting to happen there, as any object loaded before the call to close_object_store() may be stranded with a bogus maybe_tree entry (and thus looking at it after the call might cause an error). But I'm not sure how to trigger it, nor what the fix should look like (you probably would need to "unparse" any objects pulled from the graph). And so this patch punts on that for now in favor of fixing the recent regression in the most direct way, which should not have any other fallouts. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-04write-or-die: make GIT_FLUSH a Boolean environment variableChandra Pratap2-14/+10
Among Git's environment variables, the ones marked as "Boolean" accept values in a way similar to Boolean configuration variables, i.e. values like 'yes', 'on', 'true' and positive numbers are taken as "on" and values like 'no', 'off', 'false' are taken as "off". GIT_FLUSH can be used to force Git to use non-buffered I/O when writing to stdout. It can only accept two values, '1' which causes Git to flush more often and '0' which makes all output buffered. Make GIT_FLUSH accept more values besides '0' and '1' by turning it into a Boolean environment variable, modifying the required logic. Update the related documentation. Signed-off-by: Chandra Pratap <chandrapratap3519@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-03push: region_leave trace for negotiate_using_fetchSam Delmerico1-1/+1
There were two region_enter events for negotiate_using_fetch instead of one enter and one leave. This commit replaces the second region_enter event with a region_leave. Signed-off-by: Sam Delmerico <delmerico@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-03Documentation: fix statement about rebase.instructionFormatMaarten van der Schrieck2-2/+2
Since commit 62db5247 (rebase -i: generate the script via rebase--helper, 2017-07-14), the short hash is given in rebase-todo. Specifying rebase.instructionFormat does not alter this behavior, contrary to what the documentation implies. Signed-off-by: Maarten van der Schrieck <maarten@thingsconnected.nl> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-03reftable/merged: transfer ownership of records when iteratingPatrick Steinhardt1-2/+4
When iterating over records with the merged iterator we put the records into a priority queue before yielding them to the caller. This means that we need to allocate the contents of these records before we can pass them over to the caller. The handover to the caller is quite inefficient though because we first deallocate the record passed in by the caller and then copy over the new record, which requires us to reallocate memory. Refactor the code to instead transfer ownership of the new record to the caller. So instead of reallocating all contents, we now release the old record and then copy contents of the new record into place. The following benchmark of `git show-ref --quiet` in a repository with around 350k refs shows a clear improvement. Before: HEAP SUMMARY: in use at exit: 21,163 bytes in 193 blocks total heap usage: 708,058 allocs, 707,865 frees, 36,783,255 bytes allocated After: HEAP SUMMARY: in use at exit: 21,163 bytes in 193 blocks total heap usage: 357,007 allocs, 356,814 frees, 24,193,602 bytes allocated This shows that we now have roundabout a single allocation per record that we're yielding from the iterator. Ideally, we'd also get rid of this allocation so that the number of allocations doesn't scale with the number of refs anymore. This would require some larger surgery though because the memory is owned by the priority queue before transferring it over to the caller. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>