aboutsummaryrefslogtreecommitdiffstats
path: root/merge-blobs.c (unfollow)
AgeCommit message (Collapse)AuthorFilesLines
2024-01-16The eighth batchJunio C Hamano1-0/+9
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-16rev-list-options: fix off-by-one in '--filter=blob:limit=<n>' explainerNikolay Edigaryev1-4/+4
'--filter=blob:limit=<n>' was introduced in 25ec7bcac0 (list-objects: filter objects in traverse_commit_list, 2017-11-21) and later expanded to bitmaps in 84243da129 (pack-bitmap: implement BLOB_LIMIT filtering, 2020-02-14) The logic that was introduced in these commits (and that still persists to this day) omits blobs larger than _or equal_ to n bytes or units. However, the documentation (Documentation/rev-list-options.txt) states: >The form '--filter=blob:limit=<n>[kmg]' omits blobs larger than n bytes or units. n may be zero. Moreover, the t6113-rev-list-bitmap-filters.sh tests for exactly this logic, so it seems it is the documentation that needs fixing, not the code. This changes the explanation to be similar to Documentation/git-clone.txt, which is correct. Signed-off-by: Nikolay Edigaryev <edigaryev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-16unit-tests: rewrite t/helper/test-ctype.c as a unit testAchu Luma6-77/+81
In the recent codebase update (8bf6fbd00d (Merge branch 'js/doc-unit-tests', 2023-12-09)), a new unit testing framework was merged, providing a standardized approach for testing C code. Prior to this update, some unit tests relied on the test helper mechanism, lacking a dedicated unit testing framework. It's more natural to perform these unit tests using the new unit test framework. This commit migrates the unit tests for C character classification functions (isdigit(), isspace(), etc) from the legacy approach using the test-tool command `test-tool ctype` in t/helper/test-ctype.c to the new unit testing framework (t/unit-tests/test-lib.h). The migration involves refactoring the tests to utilize the testing macros provided by the framework (TEST() and check_*()). Mentored-by: Christian Couder <chriscool@tuxfamily.org> Helped-by: René Scharfe <l.s.r@web.de> Helped-by: Phillip Wood <phillip.wood123@gmail.com> Helped-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Achu Luma <ach.lumap@gmail.com> Acked-by: Phillip Wood <phillip.wood123@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-15commit-graph: fix memory leak when not writing graphPatrick Steinhardt1-11/+8
When `write_commit_graph()` bails out writing a split commit-graph early then it may happen that we have already gathered the set of existing commit-graph file names without yet determining the new merged set of files. This can result in a memory leak though because we only clear the preimage of files when we have collected the postimage. Fix this issue by dropping the condition altogether so that we always try to free both preimage and postimage filenames. As the context structure is zero-initialized this simplification is safe to do. Signed-off-by: Patrick Steinhardt <ps@pks.im> Acked-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-12The seventh batchJunio C Hamano1-1/+18
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-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-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-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-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-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-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>
2024-01-03reftable/merged: really reuse buffers to compute record keysPatrick Steinhardt1-2/+0
In 829231dc20 (reftable/merged: reuse buffer to compute record keys, 2023-12-11), we have refactored the merged iterator to reuse a pair of long-living strbufs by relying on the fact that `reftable_record_key()` tries to reuse already allocated strbufs by calling `strbuf_reset()`, which should give us significantly fewer reallocations compared to the old code that used on-stack strbufs that are allocated for each and every iteration. Unfortunately, we called `strbuf_release()` on these long-living strbufs that we meant to reuse on each iteration, defeating the optimization. Fix this performance issue by not releasing those buffers on iteration anymore, where we instead rely on `merged_iter_close()` to release the buffers for us. Using `git show-ref --quiet` in a repository with ~350k refs this leads to a significant drop in allocations. Before: HEAP SUMMARY: in use at exit: 21,163 bytes in 193 blocks total heap usage: 1,410,148 allocs, 1,409,955 frees, 61,976,068 bytes allocated After: 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 Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-03reftable/record: store "val2" hashes as static arraysPatrick Steinhardt4-20/+6
Similar to the preceding commit, convert ref records of type "val2" to store their object IDs in static arrays instead of allocating them for every single record. We're using the same benchmark as in the preceding commit, with `git show-ref --quiet` in a repository with ~350k refs. This time around though the effects aren't this huge. Before: HEAP SUMMARY: in use at exit: 21,163 bytes in 193 blocks total heap usage: 1,419,040 allocs, 1,418,847 frees, 62,153,868 bytes allocated After: HEAP SUMMARY: in use at exit: 21,163 bytes in 193 blocks total heap usage: 1,410,148 allocs, 1,409,955 frees, 61,976,068 bytes allocated This is because "val2"-type records are typically only stored for peeled tags, and the number of annotated tags in the benchmark repository is rather low. Still, it can be seen that this change leads to a reduction of allocations overall, even if only a small one. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-03reftable/record: store "val1" hashes as static arraysPatrick Steinhardt7-30/+13
When reading ref records of type "val1", we store its object ID in an allocated array. This results in an additional allocation for every single ref record we read, which is rather inefficient especially when iterating over refs. Refactor the code to instead use an embedded array of `GIT_MAX_RAWSZ` bytes. While this means that `struct ref_record` is bigger now, we typically do not store all refs in an array anyway and instead only handle a limited number of records at the same point in time. Using `git show-ref --quiet` in a repository with ~350k refs this leads to a significant drop in allocations. Before: HEAP SUMMARY: in use at exit: 21,098 bytes in 192 blocks total heap usage: 2,116,683 allocs, 2,116,491 frees, 76,098,060 bytes allocated After: HEAP SUMMARY: in use at exit: 21,098 bytes in 192 blocks total heap usage: 1,419,031 allocs, 1,418,839 frees, 62,145,036 bytes allocated Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-03reftable/record: constify some parts of the interfacePatrick Steinhardt2-6/+6
We're about to convert reftable records to stop storing their object IDs as allocated hashes. Prepare for this refactoring by constifying some parts of the interface that will be impacted by this. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-03reftable/writer: fix index corruption when writing multiple indicesPatrick Steinhardt2-2/+82
Each reftable may contain multiple types of blocks for refs, objects and reflog records, where each of these may have an index that makes it more efficient to find the records. It was observed that the index for log records can become corrupted under certain circumstances, where the first entry of the index points into the object index instead of to the log records. As it turns out, this corruption can occur whenever we write a log index as well as at least one additional index. Writing records and their index is basically a two-step process: 1. We write all blocks for the corresponding record. Each block that gets written is added to a list of blocks to index. 2. Once all blocks were written we finish the section. If at least two blocks have been added to the list of blocks to index then we will now write the index for those blocks and flush it, as well. When we have a very large number of blocks then we may decide to write a multi-level index, which is why we also keep track of the list of the index blocks in the same way as we previously kept track of the blocks to index. Now when we have finished writing all index blocks we clear the index and flush the last block to disk. This is done in the wrong order though because flushing the block to disk will re-add it to the list of blocks to be indexed. The result is that the next section we are about to write will have an entry in the list of blocks to index that points to the last block of the preceding section's index, which will corrupt the log index. Fix this corruption by clearing the index after having written the last block. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-03reftable/stack: do not auto-compact twice in `reftable_stack_add()`Patrick Steinhardt1-3/+0
In 5c086453ff (reftable/stack: perform auto-compaction with transactional interface, 2023-12-11), we fixed a bug where the transactional interface to add changes to a reftable stack did not perform auto-compaction by calling `reftable_stack_auto_compact()` in `reftable_stack_addition_commit()`. While correct, this change may now cause us to perform auto-compaction twice in the non-transactional interface `reftable_stack_add()`: - It performs auto-compaction by itself. - It now transitively performs auto-compaction via the transactional interface. Remove the first instance so that we only end up doing auto-compaction once. Reported-by: Han-Wen Nienhuys <hanwenn@gmail.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-03reftable/stack: do not overwrite errors when compactingPatrick Steinhardt1-12/+8
In order to compact multiple stacks we iterate through the merged ref and log records. When there is any error either when reading the records from the old merged table or when writing the records to the new table then we break out of the respective loops. When breaking out of the loop for the ref records though the error code will be overwritten, which may cause us to inadvertently skip over bad ref records. In the worst case, this can lead to a compacted stack that is missing records. Fix the code by using `goto done` instead so that any potential error codes are properly returned to the caller. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-03t1006: prefer shell loop to awk for packed object sizesRené Scharfe1-6/+8
To compute the expected on-disk size of packed objects, we sort the output of show-index by pack offset and then compute the difference between adjacent entries using awk. This works but has a few readability problems: 1. Reading the index in pack order means don't find out the size of an oid's entry until we see the _next_ entry. So we have to save it to print later. We can instead iterate in reverse order, so we compute each oid's size as we see it. 2. Since the awk invocation is inside a text_expect block, we can't easily use single-quotes to hold the script. So we use double-quotes, but then have to escape the dollar signs in the awk script. We can swap this out for a shell loop instead (which is made much easier by the first change). Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02The fifth batchJunio C Hamano1-0/+12
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02t9500: write "extensions.refstorage" into configPatrick Steinhardt1-0/+5
In t9500 we're writing a custom configuration that sets up gitweb. This requires us to manually ensure that the repository format is configured as required, including both the repository format version and extensions. With the introduction of the "extensions.refStorage" extension we need to update the test to also write this new one. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02builtin/clone: introduce `--ref-format=` value flagPatrick Steinhardt3-1/+34
Introduce a new `--ref-format` value flag for git-clone(1) that allows the user to specify the ref format that is to be used for a newly initialized repository. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02builtin/init: introduce `--ref-format=` value flagPatrick Steinhardt3-1/+45
Introduce a new `--ref-format` value flag for git-init(1) that allows the user to specify the ref format that is to be used for a newly initialized repository. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02builtin/rev-parse: introduce `--show-ref-format` flagPatrick Steinhardt3-0/+24
Introduce a new `--show-ref-format` to git-rev-parse(1) that causes it to print the ref format used by a repository. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvarPatrick Steinhardt3-1/+18
Introduce a new GIT_TEST_DEFAULT_REF_FORMAT environment variable that lets developers run the test suite with a different default ref format without impacting the ref format used by non-test Git invocations. This is modeled after GIT_TEST_DEFAULT_OBJECT_FORMAT, which does the same thing for the repository's object format. Adapt the setup of the `REFFILES` test prerequisite to be conditionally set based on the default ref format. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02setup: introduce GIT_DEFAULT_REF_FORMAT envvarPatrick Steinhardt3-0/+30
Introduce a new GIT_DEFAULT_REF_FORMAT environment variable that lets users control the default ref format used by both git-init(1) and git-clone(1). This is modeled after GIT_DEFAULT_OBJECT_FORMAT, which does the same thing for the repository's object format. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02setup: introduce "extensions.refStorage" extensionPatrick Steinhardt8-6/+69
Introduce a new "extensions.refStorage" extension that allows us to specify the ref storage format used by a repository. For now, the only supported format is the "files" format, but this list will likely soon be extended to also support the upcoming "reftable" format. There have been discussions on the Git mailing list in the past around how exactly this extension should look like. One alternative [1] that was discussed was whether it would make sense to model the extension in such a way that backends are arbitrarily stackable. This would allow for a combined value of e.g. "loose,packed-refs" or "loose,reftable", which indicates that new refs would be written via "loose" files backend and compressed into "packed-refs" or "reftable" backends, respectively. It is arguable though whether this flexibility and the complexity that it brings with it is really required for now. It is not foreseeable that there will be a proliferation of backends in the near-term future, and the current set of existing formats and formats which are on the horizon can easily be configured with the much simpler proposal where we have a single value, only. Furthermore, if we ever see that we indeed want to gain the ability to arbitrarily stack the ref formats, then we can adapt the current extension rather easily. Given that Git clients will refuse any unknown value for the "extensions.refStorage" extension they would also know to ignore a stacked "loose,packed-refs" in the future. So let's stick with the easy proposal for the time being and wire up the extension. [1]: <pull.1408.git.1667846164.gitgitgadget@gmail.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02setup: set repository's formats on initPatrick Steinhardt1-0/+7
The proper hash algorithm and ref storage format that will be used for a newly initialized repository will be figured out in `init_db()` via `validate_hash_algorithm()` and `validate_ref_storage_format()`. Until now though, we never set up the hash algorithm or ref storage format of `the_repository` accordingly. There are only two callsites of `init_db()`, one in git-init(1) and one in git-clone(1). The former function doesn't care for the formats to be set up properly because it never access the repository after calling the function in the first place. For git-clone(1) it's a different story though, as we call `init_db()` before listing remote refs. While we do indeed have the wrong hash function in `the_repository` when `init_db()` sets up a non-default object format for the repository, it never mattered because we adjust the hash after learning about the remote's hash function via the listed refs. So the current state is correct for the hash algo, but it's not for the ref storage format because git-clone(1) wouldn't know to set it up properly. But instead of adjusting only the `ref_storage_format`, set both the hash algo and the ref storage format so that `the_repository` is in the correct state when `init_db()` exits. This is fine as we will adjust the hash later on anyway and makes it easier to reason about the end state of `the_repository`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02setup: start tracking ref storage formatPatrick Steinhardt7-9/+48
In order to discern which ref storage format a repository is supposed to use we need to start setting up and/or discovering the format. This needs to happen in two separate code paths. - The first path is when we create a repository via `init_db()`. When we are re-initializing a preexisting repository we need to retain the previously used ref storage format -- if the user asked for a different format then this indicates an error and we error out. Otherwise we either initialize the repository with the format asked for by the user or the default format, which currently is the "files" backend. - The second path is when discovering repositories, where we need to read the config of that repository. There is not yet any way to configure something other than the "files" backend, so we can just blindly set the ref storage format to this backend. Wire up this logic so that we have the ref storage format always readily available when needed. As there is only a single backend and because it is not configurable we cannot yet verify that this tracking works as expected via tests, but tests will be added in subsequent commits. To countermand this ommission now though, raise a BUG() in case the ref storage format is not set up properly in `ref_store_init()`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02refs: refactor logic to look up storage backendsPatrick Steinhardt7-13/+31
In order to look up ref storage backends, we're currently using a linked list of backends, where each backend is expected to set up its `next` pointer to the next ref storage backend. This is kind of a weird setup as backends need to be aware of other backends without much of a reason. Refactor the code so that the array of backends is centrally defined in "refs.c", where each backend is now identified by an integer constant. Expose functions to translate from those integer constants to the name and vice versa, which will be required by subsequent patches. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02worktree: skip reading HEAD when repairing worktreesPatrick Steinhardt1-8/+23
When calling `git init --separate-git-dir=<new-path>` on a preexisting repository, we move the Git directory of that repository to the new path specified by the user. If there are worktrees present in the repository, we need to repair the worktrees so that their gitlinks point to the new location of the repository. This repair logic will load repositories via `get_worktrees()`, which will enumerate up and initialize all worktrees. Part of initialization is logic that we resolve their respective worktree HEADs, even though that information may not actually be needed in the end by all callers. Although not a problem presently with the file-based reference backend, it will become a problem with the upcoming reftable backend. In the context of git-init(1) we do not have a fully-initialized repository set up via `setup_git_directory()` or friends. Consequently, we do not know about the repository format when `repair_worktrees()` is called, and properly setting up all parts of the repositroy in `init_db()` before we try to repair worktrees is not an easy task. With the introduction of the reftable backend, we would ultimately try to look up the worktree HEADs before we have figured out the reference format, which does not work. We do not require the worktree HEADs at all to repair worktrees. So let's fix this issue by skipping over the step that reads them. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-01-02t: introduce DEFAULT_REPO_FORMAT prereqPatrick Steinhardt2-1/+5
A limited number of tests require repositories to have the default repository format or otherwise they would fail to run, e.g. because they fail to detect the correct hash function. While the hash function is the only extension right now that creates problems like this, we are about to add a second extension for the ref format. Introduce a new DEFAULT_REPO_FORMAT prereq that can easily be amended whenever we add new format extensions. Next to making any such changes easier on us, the prerequisite's name should also help to clarify the intent better. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-12-28attr: add builtin objectmode values supportJoanna Wang5-3/+210
Gives all paths builtin objectmode values based on the paths' modes (one of 100644, 100755, 120000, 040000, 160000). Users may use this feature to filter by file types. For example a pathspec such as ':(attr:builtin_objectmode=160000)' could filter for submodules without needing to have `builtin_objectmode=160000` to be set in .gitattributes for every submodule path. These values are also reflected in `git check-attr` results. If the git_attr_direction is set to GIT_ATTR_INDEX or GIT_ATTR_CHECKIN and a path is not found in the index, the value will be unspecified. This patch also reserves the builtin_* attribute namespace for objectmode and any future builtin attributes. Any user defined attributes using this reserved namespace will result in a warning. This is a breaking change for any existing builtin_* attributes. Pathspecs with some builtin_* attribute name (excluding builtin_objectmode) will behave like any attribute where there are no user specified values. Signed-off-by: Joanna Wang <jojwang@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-12-28mem-pool: simplify alignment calculationRené Scharfe1-3/+1
Use DIV_ROUND_UP in mem_pool_alloc() to round the allocation length to the next multiple of GIT_MAX_ALIGNMENT instead of twiddling bits explicitly. This is shorter and clearer, to the point that we no longer need the comment that explains what's being calculated. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-12-28mem-pool: fix big allocationsRené Scharfe3-3/+35
Memory pool allocations that require a new block and would fill at least half of it are handled specially. Before 158dfeff3d (mem-pool: add life cycle management functions, 2018-07-02) they used to be allocated outside of the pool. This patch made mem_pool_alloc() create a bespoke block instead, to allow releasing it when the pool gets discarded. Unfortunately mem_pool_alloc() returns a pointer to the start of such a bespoke block, i.e. to the struct mp_block at its top. When the caller writes to it, the management information gets corrupted. This affects mem_pool_discard() and -- if there are no other blocks in the pool -- also mem_pool_alloc(). Return the payload pointer of bespoke blocks, just like for smaller allocations, to protect the management struct. Also update next_free to mark the block as full. This is only strictly necessary for the first allocated block, because subsequent ones are inserted after the current block and never considered for further allocations, but it's easier to just do it in all cases. Add a basic unit test to demonstrate the issue by using mem_pool_calloc() with a tiny block size, which forces the creation of a bespoke block. Helped-by: Phillip Wood <phillip.wood123@gmail.com> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-12-28sideband.c: remove redundant 'NEEDSWORK' tagChandra Pratap1-1/+4
Signed-off-by: Chandra Pratap <chandrapratap3519@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>