diff options
268 files changed, 8749 insertions, 3529 deletions
diff --git a/.editorconfig b/.editorconfig index a3c578a43c..2d3929b591 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,7 +4,7 @@ insert_final_newline = true # The settings for C (*.c and *.h) files are mirrored in .clang-format. Keep # them in sync. -[{*.{c,h,sh,perl,pl,pm,txt,adoc},config.mak.*,Makefile}] +[{*.{c,h,sh,bash,perl,pl,pm,txt,adoc},config.mak.*,Makefile}] indent_style = tab tab_width = 8 diff --git a/.gitattributes b/.gitattributes index 43fa883a84..c6a0b35116 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12,7 +12,7 @@ CODE_OF_CONDUCT.md -whitespace /GIT-VERSION-GEN text eol=lf /mergetools/* text eol=lf /t/oid-info/* text eol=lf -/Documentation/git-merge.txt conflict-marker-size=32 -/Documentation/gitk.txt conflict-marker-size=32 -/Documentation/user-manual.txt conflict-marker-size=32 +/Documentation/git-merge.adoc conflict-marker-size=32 +/Documentation/gitk.adoc conflict-marker-size=32 +/Documentation/user-manual.adoc conflict-marker-size=32 /t/t????-*.sh conflict-marker-size=32 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5f756dfc2e..9959b61ece 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -265,7 +265,7 @@ jobs: run: pip install meson ninja - name: Setup shell: pwsh - run: meson setup build -Dperl=disabled + run: meson setup build -Dperl=disabled -Dcredential_helpers=wincred - name: Compile shell: pwsh run: meson compile -C build diff --git a/.gitignore b/.gitignore index 08a66ca508..04c444404e 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,7 @@ /git-diff /git-diff-files /git-diff-index +/git-diff-pairs /git-diff-tree /git-difftool /git-difftool--helper diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3f29181708..2805cdeecb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -164,7 +164,7 @@ build:msvc-meson: extends: .msvc-meson stage: build script: - - meson setup build -Dperl=disabled + - meson setup build -Dperl=disabled -Dbackend_max_links=1 -Dcredential_helpers=wincred - meson compile -C build artifacts: paths: @@ -179,7 +179,7 @@ test:msvc-meson: - job: "build:msvc-meson" artifacts: true script: - - meson test -C build --list | Select-Object -Skip 1 | Select-String .* | Group-Object -Property { $_.LineNumber % $Env:CI_NODE_TOTAL + 1 } | Where-Object Name -EQ $Env:CI_NODE_INDEX | ForEach-Object { meson test -C build --no-rebuild --print-errorlogs $_.Group } + - meson test -C build --list | Select-Object -Skip 1 | Select-String .* | Group-Object -Property { $_.LineNumber % $Env:CI_NODE_TOTAL + 1 } | Where-Object Name -EQ $Env:CI_NODE_INDEX | ForEach-Object { meson test -C build --no-rebuild --print-errorlogs $_.Group; if (!$?) { exit $LASTEXITCODE } } parallel: 10 test:fuzz-smoke-tests: diff --git a/Documentation/.gitattributes b/Documentation/.gitattributes deleted file mode 100644 index ddb030137d..0000000000 --- a/Documentation/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.txt whitespace diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc index 7c388e56c8..bdfad29d8a 100644 --- a/Documentation/BreakingChanges.adoc +++ b/Documentation/BreakingChanges.adoc @@ -66,22 +66,21 @@ changes are made at a certain version boundary, and recording these decisions in this document, are necessary but not sufficient. Because such changes are expected to be numerous, and the design and implementation of them are expected to span over time, they have to -be deployable trivially at such a version boundary. +be deployable trivially at such a version boundary, prepared over long +time. The breaking changes MUST be guarded with the a compile-time switch, WITH_BREAKING_CHANGES, to help this process. When built with it, the resulting Git binary together with its documentation would behave as if these breaking changes slated for the next big version -boundary are already in effect. We may also want to have a CI job -or two to exercise the work-in-progress version of Git with these -breaking changes. +boundary are already in effect. We also have a CI job to exercise +the work-in-progress version of Git with these breaking changes. == Git 3.0 The following subsections document upcoming breaking changes for Git 3.0. There -is no planned release date for this breaking version yet. The early -adopter configuration used for changes for this release is `feature.git3`. +is no planned release date for this breaking version yet. Proposed changes and removals only include items which are "ready" to be done. In other words, this is not supposed to be a wishlist of features that should @@ -169,8 +168,8 @@ started to migrate away from ".git/remotes/" in favor of config-based remotes, and we have marked the directory as legacy in 3d3d282146 (Documentation: Grammar correction, wording fixes and cleanup, 2011-08-23) + -As our documentation mentions, these directories are not to be found in modern -repositories at all and most users aren't even aware of these mechanisms. They +As our documentation mentions, these directories are unlikely to be used in +modern repositories and most users aren't even aware of these mechanisms. They have been deprecated for almost 20 years and 14 years respectively, and we are not aware of any active users that have complained about this deprecation. Furthermore, the ".git/branches/" directory is nowadays misleadingly named and diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index ba047ed224..a0e7041c54 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -44,7 +44,7 @@ code are expected to match the style the surrounding code already uses (even if it doesn't match the overall style of existing code). But if you must have a list of rules, here are some language -specific ones. Note that Documentation/ToolsForGit.txt document +specific ones. Note that Documentation/ToolsForGit.adoc document has a collection of tips to help you use some external tools to conform to these guidelines. @@ -755,7 +755,7 @@ Externally Visible Names Writing Documentation: Most (if not all) of the documentation pages are written in the - AsciiDoc format in *.txt files (e.g. Documentation/git.txt), and + AsciiDoc format in *.adoc files (e.g. Documentation/git.adoc), and processed into HTML and manpages (e.g. git.html and git.1 in the same directory). diff --git a/Documentation/Makefile b/Documentation/Makefile index a734c6d624..671267a8ac 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +all:: + # Import tree-wide shared Makefile behavior and libraries include ../shared.mak @@ -221,6 +224,10 @@ asciidoc.conf: asciidoc.conf.in FORCE $(QUIET_GEN)$(call version_gen,"$(shell pwd)/..",$<,$@) endif +ifdef WITH_BREAKING_CHANGES +ASCIIDOC_EXTRA += -awith-breaking-changes +endif + ASCIIDOC_DEPS += docinfo.html SHELL_PATH ?= $(SHELL) @@ -238,7 +245,7 @@ DEFAULT_EDITOR_SQ = $(subst ','\'',$(DEFAULT_EDITOR)) ASCIIDOC_EXTRA += -a 'git-default-editor=$(DEFAULT_EDITOR_SQ)' endif -all: html man +all:: html man html: $(DOC_HTML) diff --git a/Documentation/MyFirstContribution.adoc b/Documentation/MyFirstContribution.adoc index e41654c00a..ca1d688c9b 100644 --- a/Documentation/MyFirstContribution.adoc +++ b/Documentation/MyFirstContribution.adoc @@ -21,7 +21,7 @@ This tutorial aims to summarize the following documents, but the reader may find useful additional context: - `Documentation/SubmittingPatches` -- `Documentation/howto/new-command.txt` +- `Documentation/howto/new-command.adoc` [[getting-help]] === Getting Help @@ -331,7 +331,7 @@ function body: apply standard precedence rules. `git_config_get_string_tmp()` will look up a specific key ("user.name") and give you the value. There are a number of single-key lookup functions like this one; you can see them all (and more info -about how to use `git_config()`) in `Documentation/technical/api-config.txt`. +about how to use `git_config()`) in `Documentation/technical/api-config.adoc`. You should see that the name printed matches the one you see when you run: @@ -367,6 +367,7 @@ But as we drill down, we can find that `status_init_config()` wraps a call to `git_config()`. Let's modify the code we wrote in the previous commit. Be sure to include the header to allow you to use `struct wt_status`: + ---- #include "wt-status.h" ---- @@ -461,10 +462,10 @@ $ ./bin-wrappers/git help psuh Your new command is undocumented! Let's fix that. -Take a look at `Documentation/git-*.txt`. These are the manpages for the +Take a look at `Documentation/git-*.adoc`. These are the manpages for the subcommands that Git knows about. You can open these up and take a look to get acquainted with the format, but then go ahead and make a new file -`Documentation/git-psuh.txt`. Like with most of the documentation in the Git +`Documentation/git-psuh.adoc`. Like with most of the documentation in the Git project, help pages are written with AsciiDoc (see CodingGuidelines, "Writing Documentation" section). Use the following template to fill out your own manpage: @@ -543,7 +544,7 @@ Try and run `./bin-wrappers/git psuh -h`. Your command should crash at the end. That's because `-h` is a special case which your command should handle by printing usage. -Take a look at `Documentation/technical/api-parse-options.txt`. This is a handy +Take a look at `Documentation/technical/api-parse-options.adoc`. This is a handy tool for pulling out options you need to be able to handle, and it takes a usage string. @@ -1088,14 +1089,14 @@ This gives reviewers a summary of what they're in for when reviewing your topic. The one generated for `psuh` from the sample implementation looks like this: ---- - Documentation/git-psuh.txt | 40 +++++++++++++++++++++ - Makefile | 1 + - builtin.h | 1 + - builtin/psuh.c | 73 ++++++++++++++++++++++++++++++++++++++ - git.c | 1 + - t/t9999-psuh-tutorial.sh | 12 +++++++ + Documentation/git-psuh.adoc | 40 +++++++++++++++++++++ + Makefile | 1 + + builtin.h | 1 + + builtin/psuh.c | 73 ++++++++++++++++++++++++++++++++++++++ + git.c | 1 + + t/t9999-psuh-tutorial.sh | 12 +++++++ 6 files changed, 128 insertions(+) - create mode 100644 Documentation/git-psuh.txt + create mode 100644 Documentation/git-psuh.adoc create mode 100644 builtin/psuh.c create mode 100755 t/t9999-psuh-tutorial.sh ---- diff --git a/Documentation/MyFirstObjectWalk.adoc b/Documentation/MyFirstObjectWalk.adoc index dec8afe5b1..bfe8f5f561 100644 --- a/Documentation/MyFirstObjectWalk.adoc +++ b/Documentation/MyFirstObjectWalk.adoc @@ -15,7 +15,7 @@ revision walk is used for operations like `git log`. === Related Reading -- `Documentation/user-manual.txt` under "Hacking Git" contains some coverage of +- `Documentation/user-manual.adoc` under "Hacking Git" contains some coverage of the revision walker in its various incarnations. - `revision.h` - https://eagain.net/articles/git-for-computer-scientists/[Git for Computer Scientists] @@ -112,7 +112,7 @@ $ GIT_TRACE=1 ./bin-wrappers/git walken ---- NOTE: For a more exhaustive overview of the new command process, take a look at -`Documentation/MyFirstContribution.txt`. +`Documentation/MyFirstContribution.adoc`. NOTE: A reference implementation can be found at https://github.com/nasamuffin/git/tree/revwalk. @@ -132,7 +132,7 @@ used to track the allocated size of the list. Per entry, we find: `item` is the object provided upon which to base the object walk. Items in Git -can be blobs, trees, commits, or tags. (See `Documentation/gittutorial-2.txt`.) +can be blobs, trees, commits, or tags. (See `Documentation/gittutorial-2.adoc`.) `name` is the object ID (OID) of the object - a hex string you may be familiar with from using Git to organize your source in the past. Check the tutorial @@ -141,7 +141,7 @@ from. `whence` indicates some information about what to do with the parents of the specified object. We'll explore this flag more later on; take a look at -`Documentation/revisions.txt` to get an idea of what could set the `whence` +`Documentation/revisions.adoc` to get an idea of what could set the `whence` value. `flags` are used to hint the beginning of the revision walk and are the first @@ -153,7 +153,7 @@ can be used during the walk, as well. This one is quite a bit longer, and many fields are only used during the walk by `revision.c` - not configuration options. Most of the configurable flags in -`struct rev_info` have a mirror in `Documentation/rev-list-options.txt`. It's a +`struct rev_info` have a mirror in `Documentation/rev-list-options.adoc`. It's a good idea to take some time and read through that document. == Basic Commit Walk @@ -287,6 +287,7 @@ static void final_rev_info_setup(struct rev_info *rev) ==== Instead of using the shorthand `add_head_to_pending()`, you could do something like this: + ---- struct setup_revision_opt opt; @@ -295,6 +296,7 @@ something like this: opt.revarg_opt = REVARG_COMMITTISH; setup_revisions(argc, argv, rev, &opt); ---- + Using a `setup_revision_opt` gives you finer control over your walk's starting point. ==== @@ -710,7 +712,7 @@ objects grows along with the Git project. === Adding a Filter There are a handful of filters that we can apply to the object walk laid out in -`Documentation/rev-list-options.txt`. These filters are typically useful for +`Documentation/rev-list-options.adoc`. These filters are typically useful for operations such as creating packfiles or performing a partial clone. They are defined in `list-objects-filter-options.h`. For the purposes of this tutorial we will use the "tree:1" filter, which causes the walk to omit all trees and blobs diff --git a/Documentation/RelNotes/2.49.0.adoc b/Documentation/RelNotes/2.49.0.adoc index 83bab70cb6..494c83096f 100644 --- a/Documentation/RelNotes/2.49.0.adoc +++ b/Documentation/RelNotes/2.49.0.adoc @@ -35,6 +35,23 @@ UI, Workflows & Features * Comes with an updated "gitk". + * The documentation of "git commit" and "git rebase" now refer to + commit titles as such, not "subject". + + * The value of "uname -s" is by default sent over the wire as a part + of the "version" capability. + + * "git refs migrate" can optionally be told not to migrate the reflog. + + * The netrc support (via the cURL library) for the HTTP transport has + been re-enabled. + + * Removal of ".git/branches" and ".git/remotes" support in the + BreakingChanges document has been further clarified. + + * What happens to submodules during merge has been documented in a + bit more detail. + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -43,6 +60,9 @@ Performance, Internal Implementation, Development Support etc. * meson-based build now supports the unsafe-sha1 build knob. + * The meson-based build procedure covers contrib/ and other places as + well. + * The code to check LSan results has been simplified and made more robust. (merge 164a2516eb jk/lsan-race-ignore-false-positive later to maint). @@ -70,6 +90,21 @@ Performance, Internal Implementation, Development Support etc. * "git difftool" code clean-up. + * Rename processing in the recursive merge backend has seen a micro + optimization. + + * The path.[ch] API takes an explicit repository parameter passed + throughout the callchain, instead of relying on the_repository + singleton instance. + + * Large-object promisor protocol extension has been introduced. + + * The editorconfig file is updated to tell us that bash scripts are + similar to general Bourne shell scripts. + + * Meson-based build procedure forgot to build some docs, which has + been corrected. + Fixes since v2.48 ----------------- @@ -204,6 +239,33 @@ Fixes since v2.48 * A thunderbird helper script lost its bashism. (merge 59d26bd961 bc/contrib-thunderbird-patch-inline-fix later to maint). + * The -G/-S options to the "diff" family of commands caused us to hit + a BUG() when they get no values; they have been corrected. + (merge a620046b29 bc/diff-reject-empty-arg-to-pickaxe later to maint). + + * "git merge-tree --stdin" has been improved (including a workaround + for a deadlock). + (merge 6a9ae81015 pw/merge-tree-stdin-deadlock-fix later to maint). + + * Correct the default target in Documentation/Makefile, and + future-proof all Makefiles from similar breakages by declaring the + default target (which happens to be "all") upfront. + (merge 5309c1e9fb ad/set-default-target-in-makefiles later to maint). + + * "git check-mailmap" used to segfault when queried without human + readable name. + (merge bb60c52131 jk/check-mailmap-wo-name-fix later to maint). + + * Support for renaming of symbolic links on Windows has been improved. + + * "git rebase -i" failed to allow rewording an empty commit that has + been fast-forwarded. + (merge af8fc7be10 pw/rebase-i-ff-empty-commit later to maint). + + * The use of "paste" command for aggregating the test results have + been corrected. + (merge ce98863204 dk/test-aggregate-results-paste-fix later to maint). + * Other code cleanup, docfix, build fix, etc. (merge ddb5287894 jk/t7407-use-test-grep later to maint). (merge 21e1b44865 aj/difftool-config-doc-fix later to maint). @@ -222,3 +284,5 @@ Fixes since v2.48 (merge 45761988ac en/doc-renormalize later to maint). (merge 832f56f06a jc/doc-boolean-synonyms later to maint). (merge 3eeed876a9 ac/doc-http-ssl-type-config later to maint). + (merge c268e3285d jc/breaking-changes-early-adopter-option later to maint). + (merge 0d03fda6a5 pb/doc-follow-remote-head later to maint). diff --git a/Documentation/RelNotes/2.50.0.adoc b/Documentation/RelNotes/2.50.0.adoc new file mode 100644 index 0000000000..50e3027984 --- /dev/null +++ b/Documentation/RelNotes/2.50.0.adoc @@ -0,0 +1,34 @@ +Git v2.50 Release Notes +======================= + +UI, Workflows & Features +------------------------ + + * A post-processing filter for "diff --raw" output has been + introduced. + + +Performance, Internal Implementation, Development Support etc. +-------------------------------------------------------------- + + * A handful of built-in command implementations have been rewritten + to use the repository instance supplied by git.c:run_builtin(), its + caller. + + * "git fsck" becomes more careful when checking the refs. + + +Fixes since v2.49 +----------------- + + * The refname exclusion logic in the packed-ref backend has been + broken for some time, which confused upload-pack to advertise + different set of refs. This has been corrected. + (merge 10e8a9352b tb/refs-exclude-fixes later to maint). + + * The merge-recursive and merge-ort machinery crashed in corner cases + when certain renames are involved. + (merge 3adba40858 en/merge-process-renames-crash-fix later to maint). + + * Other code cleanup, docfix, build fix, etc. + (merge 227c4f33a0 ja/doc-block-delimiter-markup-fix later to maint). diff --git a/Documentation/ToolsForGit.adoc b/Documentation/ToolsForGit.adoc index ae7690b45d..a842c13327 100644 --- a/Documentation/ToolsForGit.adoc +++ b/Documentation/ToolsForGit.adoc @@ -34,6 +34,7 @@ This is adapted from Linux's suggestion in its CodingStyle document: - To follow the rules in CodingGuidelines, it's useful to put the following in GIT_CHECKOUT/.dir-locals.el, assuming you use cperl-mode: + ---- ;; note the first part is useful for C editing, too ((nil . ((indent-tabs-mode . t) diff --git a/Documentation/build-docdep.perl b/Documentation/build-docdep.perl index 315efaa2fa..781da12b2e 100755 --- a/Documentation/build-docdep.perl +++ b/Documentation/build-docdep.perl @@ -4,15 +4,15 @@ my ($build_dir) = @ARGV; my %include = (); my %included = (); -for my $text (<*.txt>) { - open I, '<', $text || die "cannot read: $text"; +for my $adoc (<*.adoc>) { + open I, '<', $adoc || die "cannot read: $adoc"; while (<I>) { if (/^include::/) { chomp; s/^include::\s*//; s/\[\]//; s/{build_dir}/${build_dir}/; - $include{$text}{$_} = 1; + $include{$adoc}{$_} = 1; $included{$_} = 1; } } @@ -23,14 +23,14 @@ for my $text (<*.txt>) { my $changed = 1; while ($changed) { $changed = 0; - while (my ($text, $included) = each %include) { + while (my ($adoc, $included) = each %include) { for my $i (keys %$included) { - # $text has include::$i; if $i includes $j - # $text indirectly includes $j. + # $adoc has include::$i; if $i includes $j + # $adoc indirectly includes $j. if (exists $include{$i}) { for my $j (keys %{$include{$i}}) { - if (!exists $include{$text}{$j}) { - $include{$text}{$j} = 1; + if (!exists $include{$adoc}{$j}) { + $include{$adoc}{$j} = 1; $included{$j} = 1; $changed = 1; } @@ -40,10 +40,10 @@ while ($changed) { } } -foreach my $text (sort keys %include) { - my $included = $include{$text}; - if (! exists $included{$text} && - (my $base = $text) =~ s/\.txt$//) { +foreach my $adoc (sort keys %include) { + my $included = $include{$adoc}; + if (! exists $included{$adoc} && + (my $base = $adoc) =~ s/\.adoc$//) { print "$base.html $base.xml : ", join(" ", sort keys %$included), "\n"; } } diff --git a/Documentation/config/promisor.adoc b/Documentation/config/promisor.adoc index 98c5cb2ec2..9192acfd24 100644 --- a/Documentation/config/promisor.adoc +++ b/Documentation/config/promisor.adoc @@ -1,3 +1,30 @@ promisor.quiet:: If set to "true" assume `--quiet` when fetching additional objects for a partial clone. + +promisor.advertise:: + If set to "true", a server will use the "promisor-remote" + capability, see linkgit:gitprotocol-v2[5], to advertise the + promisor remotes it is using, if it uses some. Default is + "false", which means the "promisor-remote" capability is not + advertised. + +promisor.acceptFromServer:: + If set to "all", a client will accept all the promisor remotes + a server might advertise using the "promisor-remote" + capability. If set to "knownName" the client will accept + promisor remotes which are already configured on the client + and have the same name as those advertised by the client. This + is not very secure, but could be used in a corporate setup + where servers and clients are trusted to not switch name and + URLs. If set to "knownUrl", the client will accept promisor + remotes which have both the same name and the same URL + configured on the client as the name and URL advertised by the + server. This is more secure than "all" or "knownName", so it + should be used if possible instead of those options. Default + is "none", which means no promisor remote advertised by a + server will be accepted. By accepting a promisor remote, the + client agrees that the server might omit objects that are + lazily fetchable from this promisor remote from its responses + to "fetch" and "clone" requests from the client. See + linkgit:gitprotocol-v2[5]. diff --git a/Documentation/config/remote.adoc b/Documentation/config/remote.adoc index 4118c219c1..25fe219d10 100644 --- a/Documentation/config/remote.adoc +++ b/Documentation/config/remote.adoc @@ -101,21 +101,21 @@ remote.<name>.serverOption:: The default set of server options used when fetching from this remote. These server options can be overridden by the `--server-option=` command line arguments. ++ +This is a multi-valued variable, and an empty value can be used in a higher +priority configuration file (e.g. `.git/config` in a repository) to clear +the values inherited from a lower priority configuration files (e.g. +`$HOME/.gitconfig`). remote.<name>.followRemoteHEAD:: How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`. The default value is "create", which will create `remotes/<name>/HEAD` - if it exists on the remote, but not locally, but will not touch an - already existing local reference. Setting to "warn" will print - a message if the remote has a different value, than the local one and + if it exists on the remote, but not locally; this will not touch an + already existing local reference. Setting it to "warn" will print + a message if the remote has a different value than the local one; in case there is no local reference, it behaves like "create". A variant on "warn" is "warn-if-not-$branch", which behaves like "warn", but if `HEAD` on the remote is `$branch` it will be silent. - Setting to "always" will silently update it to the value on the remote. - Finally, setting it to "never" will never change or create the local - reference. -+ -This is a multi-valued variable, and an empty value can be used in a higher -priority configuration file (e.g. `.git/config` in a repository) to clear -the values inherited from a lower priority configuration files (e.g. -`$HOME/.gitconfig`). + Setting it to "always" will silently update `remotes/<name>/HEAD` to + the value on the remote. Finally, setting it to "never" will never + change or create the local reference. diff --git a/Documentation/fsck-msgids.adoc b/Documentation/fsck-msgids.adoc index b14bc44ca4..9601fff228 100644 --- a/Documentation/fsck-msgids.adoc +++ b/Documentation/fsck-msgids.adoc @@ -16,6 +16,13 @@ `badObjectSha1`:: (ERROR) An object has a bad sha1. +`badPackedRefEntry`:: + (ERROR) The "packed-refs" file contains an invalid entry. + +`badPackedRefHeader`:: + (ERROR) The "packed-refs" file contains an invalid + header. + `badParentSha1`:: (ERROR) A commit object has a bad parent sha1. @@ -176,6 +183,13 @@ `nullSha1`:: (WARN) Tree contains entries pointing to a null sha1. +`packedRefEntryNotTerminated`:: + (ERROR) The "packed-refs" file contains an entry that is + not terminated by a newline. + +`packedRefUnsorted`:: + (ERROR) The "packed-refs" file is not sorted. + `refMissingNewline`:: (INFO) A loose ref that does not end with newline(LF). As valid implementations of Git never created such a loose ref diff --git a/Documentation/git-bisect.adoc b/Documentation/git-bisect.adoc index 82f944dc03..58dbb74a15 100644 --- a/Documentation/git-bisect.adoc +++ b/Documentation/git-bisect.adoc @@ -495,6 +495,7 @@ $ git bisect old HEAD~10 # the tenth commit from now is marked as old ------------ + or: ++ ------------ $ git bisect start --term-old broken --term-new fixed $ git bisect fixed diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc index d5890ae368..30359f5dbd 100644 --- a/Documentation/git-cat-file.adoc +++ b/Documentation/git-cat-file.adoc @@ -322,10 +322,10 @@ of `%(objectsize)` bytes), followed by a newline. For example, `--batch` without a custom format would produce: ------------- +----------- <oid> SP <type> SP <size> LF <contents> LF ------------- +----------- Whereas `--batch-check='%(objectname) %(objecttype)'` would produce: diff --git a/Documentation/git-check-attr.adoc b/Documentation/git-check-attr.adoc index cb5a6c8f33..503b644657 100644 --- a/Documentation/git-check-attr.adoc +++ b/Documentation/git-check-attr.adoc @@ -76,6 +76,7 @@ EXAMPLES -------- In the examples, the following '.gitattributes' file is used: + --------------- *.java diff=java -crlf myAttr NoMyAttr.java !myAttr @@ -83,12 +84,14 @@ README caveat=unspecified --------------- * Listing a single attribute: ++ --------------- $ git check-attr diff org/example/MyClass.java org/example/MyClass.java: diff: java --------------- * Listing multiple attributes for a file: ++ --------------- $ git check-attr crlf diff myAttr -- org/example/MyClass.java org/example/MyClass.java: crlf: unset @@ -97,6 +100,7 @@ org/example/MyClass.java: myAttr: set --------------- * Listing all attributes for a file: ++ --------------- $ git check-attr --all -- org/example/MyClass.java org/example/MyClass.java: diff: java @@ -104,6 +108,7 @@ org/example/MyClass.java: myAttr: set --------------- * Listing an attribute for multiple files: ++ --------------- $ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java org/example/MyClass.java: myAttr: set @@ -111,6 +116,7 @@ org/example/NoMyAttr.java: myAttr: unspecified --------------- * Not all values are equally unambiguous: ++ --------------- $ git check-attr caveat README README: caveat: unspecified diff --git a/Documentation/git-clone.adoc b/Documentation/git-clone.adoc index 510b91b5c0..222d558290 100644 --- a/Documentation/git-clone.adoc +++ b/Documentation/git-clone.adoc @@ -288,9 +288,9 @@ corresponding `--mirror` and `--no-tags` options instead. `remote.<remote>.tagOpt=--no-tags` configuration. This ensures that future `git pull` and `git fetch` won't follow any tags. Subsequent explicit tag fetches will still work (see linkgit:git-fetch[1]). - - By default, tags are cloned and passing `--tags` is thus typically a - no-op, unless it cancels out a previous `--no-tags`. ++ +By default, tags are cloned and passing `--tags` is thus typically a +no-op, unless it cancels out a previous `--no-tags`. + Can be used in conjunction with `--single-branch` to clone and maintain a branch with no references other than a single cloned diff --git a/Documentation/git-column.adoc b/Documentation/git-column.adoc index 85fb87c94a..5a4f2b6fde 100644 --- a/Documentation/git-column.adoc +++ b/Documentation/git-column.adoc @@ -50,6 +50,7 @@ EXAMPLES -------- Format data by columns: ++ ------------ $ seq 1 24 | git column --mode=column --padding=5 1 4 7 10 13 16 19 22 @@ -58,6 +59,7 @@ $ seq 1 24 | git column --mode=column --padding=5 ------------ Format data by rows: ++ ------------ $ seq 1 21 | git column --mode=row --padding=5 1 2 3 4 5 6 7 @@ -66,6 +68,7 @@ $ seq 1 21 | git column --mode=row --padding=5 ------------ List some tags in a table with unequal column widths: ++ ------------ $ git tag --list 'v2.4.*' --column=row,dense v2.4.0 v2.4.0-rc0 v2.4.0-rc1 v2.4.0-rc2 v2.4.0-rc3 diff --git a/Documentation/git-commit.adoc b/Documentation/git-commit.adoc index dfb78169cb..dc219025f1 100644 --- a/Documentation/git-commit.adoc +++ b/Documentation/git-commit.adoc @@ -98,8 +98,8 @@ OPTIONS replaces the log message of _<commit>_ with its own log message but makes no changes to the content of _<commit>_. + -The commit created by plain `--fixup=<commit>` has a subject -composed of "fixup!" followed by the subject line from _<commit>_, +The commit created by plain `--fixup=<commit>` has a title +composed of "fixup!" followed by the title of _<commit>_, and is recognized specially by `git rebase --autosquash`. The `-m` option may be used to supplement the log message of the created commit, but the additional commentary will be thrown away once the @@ -107,7 +107,7 @@ commit, but the additional commentary will be thrown away once the `git rebase --autosquash`. + The commit created by `--fixup=amend:<commit>` is similar but its -subject is instead prefixed with "amend!". The log message of +title is instead prefixed with "amend!". The log message of _<commit>_ is copied into the log message of the "amend!" commit and opened in an editor so it can be refined. When `git rebase --autosquash` squashes the "amend!" commit into _<commit>_, the @@ -128,7 +128,7 @@ See linkgit:git-rebase[1] for details. `--squash=<commit>`:: Construct a commit message for use with `git rebase --autosquash`. - The commit message subject line is taken from the specified + The commit message title is taken from the specified commit with a prefix of "squash! ". Can be used with additional commit message options (`-m`/`-c`/`-C`/`-F`). See linkgit:git-rebase[1] for details. diff --git a/Documentation/git-cvsserver.adoc b/Documentation/git-cvsserver.adoc index 4c475efeab..fe822f571d 100644 --- a/Documentation/git-cvsserver.adoc +++ b/Documentation/git-cvsserver.adoc @@ -125,9 +125,11 @@ creation in your platform (e.g. mkpasswd in Linux, encrypt in OpenBSD or pwhash in NetBSD) and paste it in the right location. Then provide your password via the pserver method, for example: + ------ cvs -d:pserver:someuser:somepassword@server:/path/repo.git co <HEAD_name> ------ + No special setup is needed for SSH access, other than having Git tools in the PATH. If you have clients that do not accept the CVS_SERVER environment variable, you can rename 'git-cvsserver' to `cvs`. @@ -138,6 +140,7 @@ CVS_SERVER directly in CVSROOT like ------ cvs -d ":ext;CVS_SERVER=git cvsserver:user@server/path/repo.git" co <HEAD_name> ------ + This has the advantage that it will be saved in your 'CVS/Root' files and you don't need to worry about always setting the correct environment variable. SSH users restricted to 'git-shell' don't need to override the default @@ -168,6 +171,7 @@ All configuration variables can also be overridden for a specific method of access. Valid method names are "ext" (for SSH access) and "pserver". The following example configuration would disable pserver access while still allowing access over SSH. + ------ [gitcvs] enabled=0 diff --git a/Documentation/git-diff-pairs.adoc b/Documentation/git-diff-pairs.adoc new file mode 100644 index 0000000000..f99fcd1ead --- /dev/null +++ b/Documentation/git-diff-pairs.adoc @@ -0,0 +1,60 @@ +git-diff-pairs(1) +================= + +NAME +---- +git-diff-pairs - Compare the content and mode of provided blob pairs + +SYNOPSIS +-------- +[synopsis] +git diff-pairs -z [<diff-options>] + +DESCRIPTION +----------- +Show changes for file pairs provided on stdin. Input for this command must be +in the NUL-terminated raw output format as generated by commands such as `git +diff-tree -z -r --raw`. By default, the outputted diffs are computed and shown +in the patch format when stdin closes. + +A single NUL byte may be written to stdin between raw input lines to compute +file pair diffs up to that point instead of waiting for stdin to close. A NUL +byte is also written to the output to delimit between these batches of diffs. + +Usage of this command enables the traditional diff pipeline to be broken up +into separate stages where `diff-pairs` acts as the output phase. Other +commands, such as `diff-tree`, may serve as a frontend to compute the raw +diff format used as input. + +Instead of computing diffs via `git diff-tree -p -M` in one step, `diff-tree` +can compute the file pairs and rename information without the blob diffs. This +output can be fed to `diff-pairs` to generate the underlying blob diffs as done +in the following example: + +----------------------------- +git diff-tree -z -r -M $a $b | +git diff-pairs -z +----------------------------- + +Computing the tree diff upfront with rename information allows patch output +from `diff-pairs` to be progressively computed over the course of potentially +multiple invocations. + +Pathspecs are not currently supported by `diff-pairs`. Pathspec limiting should +be performed by the upstream command generating the raw diffs used as input. + +Tree objects are not currently supported as input and are rejected. + +Abbreviated object IDs in the `diff-pairs` input are not supported. Outputted +object IDs can be abbreviated using the `--abbrev` option. + +OPTIONS +------- + +include::diff-options.adoc[] + +include::diff-generate-patch.adoc[] + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Documentation/git-for-each-ref.adoc b/Documentation/git-for-each-ref.adoc index ffb97e62c2..5ef89fc0fe 100644 --- a/Documentation/git-for-each-ref.adoc +++ b/Documentation/git-for-each-ref.adoc @@ -441,6 +441,7 @@ Ref: %(*refname) A simple example showing the use of shell eval on the output, demonstrating the use of --shell. List the prefixes of all heads: + ------------ #!/bin/sh @@ -455,6 +456,7 @@ done A bit more elaborate report on tags, demonstrating that the format may be an entire script: + ------------ #!/bin/sh diff --git a/Documentation/git-fsck.adoc b/Documentation/git-fsck.adoc index 8f32800a83..11203ba925 100644 --- a/Documentation/git-fsck.adoc +++ b/Documentation/git-fsck.adoc @@ -12,7 +12,7 @@ SYNOPSIS 'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs] [--[no-]full] [--strict] [--verbose] [--lost-found] [--[no-]dangling] [--[no-]progress] [--connectivity-only] - [--[no-]name-objects] [<object>...] + [--[no-]name-objects] [--[no-]references] [<object>...] DESCRIPTION ----------- @@ -104,6 +104,11 @@ care about this output and want to speed it up further. progress status even if the standard error stream is not directed to a terminal. +--[no-]references:: + Control whether to check the references database consistency + via 'git refs verify'. See linkgit:git-refs[1] for details. + The default is to check the references database. + CONFIGURATION ------------- diff --git a/Documentation/git-merge-tree.adoc b/Documentation/git-merge-tree.adoc index 0b6a8a19b1..cf0578f9b5 100644 --- a/Documentation/git-merge-tree.adoc +++ b/Documentation/git-merge-tree.adoc @@ -40,11 +40,17 @@ After the merge completes, a new toplevel tree object is created. See OPTIONS ------- +--stdin:: + Read the commits to merge from the standard input rather than + the command-line. See <<INPUT,INPUT FORMAT>> below for more + information. Implies `-z`. + -z:: Do not quote filenames in the <Conflicted file info> section, and end each filename with a NUL character rather than newline. Also begin the messages section with a NUL character - instead of a newline. See <<OUTPUT>> below for more information. + instead of a newline. See <<OUTPUT,OUTPUT>> below for more + information. --name-only:: In the Conflicted file info section, instead of writing a list @@ -116,8 +122,6 @@ This is an integer status followed by a NUL character. The integer status is: 0: merge had conflicts 1: merge was clean - <0: something prevented the merge from running (e.g. access to repository - objects denied by filesystem) [[OIDTLT]] OID of toplevel tree @@ -235,6 +239,7 @@ with linkgit:git-merge[1]: * any messages that would have been printed to stdout (the <<IM,Informational messages>>) +[[INPUT]] INPUT FORMAT ------------ 'git merge-tree --stdin' input format is fully text based. Each line diff --git a/Documentation/git-p4.adoc b/Documentation/git-p4.adoc index de5ee6748e..f97b786bf9 100644 --- a/Documentation/git-p4.adoc +++ b/Documentation/git-p4.adoc @@ -80,6 +80,7 @@ This: To reproduce the entire p4 history in Git, use the '@all' modifier on the depot path: + ------------ $ git p4 clone //depot/path/project@all ------------ @@ -89,19 +90,23 @@ Sync ~~~~ As development continues in the p4 repository, those changes can be included in the Git repository using: + ------------ $ git p4 sync ------------ + This command finds new changes in p4 and imports them as Git commits. P4 repositories can be added to an existing Git repository using 'git p4 sync' too: + ------------ $ mkdir repo-git $ cd repo-git $ git init $ git p4 sync //path/in/your/perforce/depot ------------ + This imports the specified depot into 'refs/remotes/p4/master' in an existing Git repository. The `--branch` option can be used to specify a different branch to @@ -125,6 +130,7 @@ and merge them with local uncommitted changes. Often, the p4 repository is the ultimate location for all code, thus a rebase workflow makes sense. This command does 'git p4 sync' followed by 'git rebase' to move local commits on top of updated p4 changes. + ------------ $ git p4 rebase ------------ @@ -140,16 +146,19 @@ will be created and populated if it does not already exist. To submit all changes that are in the current Git branch but not in the 'p4/master' branch, use: + ------------ $ git p4 submit ------------ To specify a branch other than the current one, use: + ------------ $ git p4 submit topicbranch ------------ To specify a single commit or a range of commits, use: + ------------ $ git p4 submit --commit <sha1> $ git p4 submit --commit <sha1..sha1> @@ -510,20 +519,24 @@ when cloning or syncing to have 'git p4' automatically find subdirectories in p4, and to generate these as branches in Git. For example, if the P4 repository structure is: + ---- //depot/main/... //depot/branch1/... ---- And "p4 branch -o branch1" shows a View line that looks like: + ---- //depot/main/... //depot/branch1/... ---- Then this 'git p4 clone' command: + ---- git p4 clone --detect-branches //depot@all ---- + produces a separate branch in 'refs/remotes/p4/' for //depot/main, called 'master', and one for //depot/branch1 called 'depot/branch1'. @@ -536,6 +549,7 @@ simple p4 branch specification, where the "source" and "destination" are the path elements in the p4 repository. The example above relied on the presence of the p4 branch. Without p4 branches, the same result will occur with: + ---- git init depot cd depot diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc index 133fe8c5e6..956d3048f5 100644 --- a/Documentation/git-rebase.adoc +++ b/Documentation/git-rebase.adoc @@ -599,11 +599,11 @@ See also INCOMPATIBLE OPTIONS below. --no-autosquash:: Automatically squash commits with specially formatted messages into previous commits being rebased. If a commit message starts with - "squash! ", "fixup! " or "amend! ", the remainder of the subject line + "squash! ", "fixup! " or "amend! ", the remainder of the title is taken as a commit specifier, which matches a previous commit if it - matches the subject line or the hash of that commit. If no commit + matches the title or the hash of that commit. If no commit matches fully, matches of the specifier with the start of commit - subjects are considered. + titles are considered. + In the rebase todo list, the actions of squash, fixup and amend commits are changed from `pick` to `squash`, `fixup` or `fixup -C`, respectively, and they @@ -613,7 +613,7 @@ be used to review and edit the todo list before proceeding. The recommended way to create commits with squash markers is by using the `--squash`, `--fixup`, `--fixup=amend:` or `--fixup=reword:` options of linkgit:git-commit[1], which take the target commit as an argument and -automatically fill in the subject line of the new commit from that. +automatically fill in the title of the new commit from that. + Setting configuration variable `rebase.autoSquash` to true enables auto-squashing by default for interactive rebase. The `--no-autosquash` @@ -1107,10 +1107,12 @@ In that case, the fix is easy because 'git rebase' knows to skip changes that are already present in the new upstream (unless `--reapply-cherry-picks` is given). So if you say (assuming you're on 'topic') + ------------ $ git rebase subsystem ------------ you will end up with the fixed history + ------------ o---o---o---o---o---o---o---o master \ @@ -1145,6 +1147,7 @@ of the old 'subsystem', for example: You can then transplant the old `subsystem..topic` to the new tip by saying (for the reflog case, and assuming you are on 'topic' already): + ------------ $ git rebase --onto subsystem subsystem@{1} ------------ diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc index 95f25776aa..4d6dc994f9 100644 --- a/Documentation/git-refs.adoc +++ b/Documentation/git-refs.adoc @@ -8,9 +8,9 @@ git-refs - Low-level access to refs SYNOPSIS -------- -[verse] -'git refs migrate' --ref-format=<format> [--dry-run] -'git refs verify' [--strict] [--verbose] +[synopsis] +git refs migrate --ref-format=<format> [--no-reflog] [--dry-run] +git refs verify [--strict] [--verbose] DESCRIPTION ----------- @@ -43,6 +43,11 @@ include::ref-storage-format.adoc[] can be used to double check that the migration works as expected before performing the actual migration. +--reflog:: +--no-reflog:: + Choose between migrating the reflog data to the new backend, + and discarding them. The default is "--reflog", to migrate. + The following options are specific to 'git refs verify': --strict:: diff --git a/Documentation/gitattributes.adoc b/Documentation/gitattributes.adoc index 7eaca89972..f20041a323 100644 --- a/Documentation/gitattributes.adoc +++ b/Documentation/gitattributes.adoc @@ -513,7 +513,7 @@ If the filter command (a string value) is defined via `filter.<driver>.process` then Git can process all blobs with a single filter invocation for the entire life of a single Git command. This is achieved by using the long-running process protocol -(described in technical/long-running-process-protocol.txt). +(described in Documentation/technical/long-running-process-protocol.adoc). When Git encounters the first file that needs to be cleaned or smudged, it starts the filter and performs the handshake. In the handshake, the @@ -531,13 +531,14 @@ must not send any response before it received the content and the final flush packet. Also note that the "value" of a "key=value" pair can contain the "=" character whereas the key would never contain that character. ------------------------- + +----------------------- packet: git> command=smudge packet: git> pathname=path/testfile.dat packet: git> 0000 packet: git> CONTENT packet: git> 0000 ------------------------- +----------------------- The filter is expected to respond with a list of "key=value" pairs terminated with a flush packet. If the filter does not experience @@ -559,6 +560,7 @@ packet: git< 0000 # empty list, keep "status=success" unchanged! If the result content is empty then the filter is expected to respond with a "success" status and a flush packet to signal the empty content. + ------------------------ packet: git< status=success packet: git< 0000 @@ -568,14 +570,16 @@ packet: git< 0000 # empty list, keep "status=success" unchanged! In case the filter cannot or does not want to process the content, it is expected to respond with an "error" status. ------------------------- + +----------------------- packet: git< status=error packet: git< 0000 ------------------------- +----------------------- If the filter experiences an error during processing, then it can send the status "error" after the content was (partially or completely) sent. + ------------------------ packet: git< status=success packet: git< 0000 @@ -589,10 +593,11 @@ In case the filter cannot or does not want to process the content as well as any future content for the lifetime of the Git process, then it is expected to respond with an "abort" status at any point in the protocol. ------------------------- + +----------------------- packet: git< status=abort packet: git< 0000 ------------------------- +----------------------- Git neither stops nor restarts the filter process in case the "error"/"abort" status is set. However, Git sets its exit code @@ -613,7 +618,8 @@ flag "can-delay" after the filter command and pathname. This flag denotes that the filter can delay filtering the current blob (e.g. to compensate network latencies) by responding with no content but with the status "delayed" and a flush packet. ------------------------- + +----------------------- packet: git> command=smudge packet: git> pathname=path/testfile.dat packet: git> can-delay=1 @@ -622,7 +628,7 @@ packet: git> CONTENT packet: git> 0000 packet: git< status=delayed packet: git< 0000 ------------------------- +----------------------- If the filter supports the "delay" capability then it must support the "list_available_blobs" command. If Git sends this command, then the @@ -647,10 +653,12 @@ packet: git< status=success packet: git< 0000 ------------------------ + After Git received the pathnames, it will request the corresponding blobs again. These requests contain a pathname and an empty content section. The filter is expected to respond with the smudged content in the usual way as explained above. + ------------------------ packet: git> command=smudge packet: git> pathname=path/testfile.dat @@ -1177,11 +1185,11 @@ integer has a meaningful effect. For example, this line in `.gitattributes` can be used to tell the merge machinery to leave much longer (instead of the usual 7-character-long) -conflict markers when merging the file `Documentation/git-merge.txt` +conflict markers when merging the file `Documentation/git-merge.adoc` results in a conflict. ------------------------ -Documentation/git-merge.txt conflict-marker-size=32 +Documentation/git-merge.adoc conflict-marker-size=32 ------------------------ diff --git a/Documentation/gitcli.adoc b/Documentation/gitcli.adoc index 04193ec907..1ea681b59d 100644 --- a/Documentation/gitcli.adoc +++ b/Documentation/gitcli.adoc @@ -209,13 +209,13 @@ $ git foo -o Arg However, this is *NOT* allowed for switches with an optional value, where the 'stuck' form must be used: + ---------------------------- $ git describe --abbrev HEAD # correct $ git describe --abbrev=10 HEAD # correct $ git describe --abbrev 10 HEAD # NOT WHAT YOU MEANT ---------------------------- - NOTES ON FREQUENTLY CONFUSED OPTIONS ------------------------------------ diff --git a/Documentation/gitprotocol-common.adoc b/Documentation/gitprotocol-common.adoc index cdc9d6e707..b4a5316ca4 100644 --- a/Documentation/gitprotocol-common.adoc +++ b/Documentation/gitprotocol-common.adoc @@ -21,11 +21,13 @@ ABNF Notation ABNF notation as described by RFC 5234 is used within the protocol documents, except the following replacement core rules are used: + ---- HEXDIG = DIGIT / "a" / "b" / "c" / "d" / "e" / "f" ---- We also define the following common rules: + ---- NUL = %x00 zero-id = 40*"0" diff --git a/Documentation/gitprotocol-v2.adoc b/Documentation/gitprotocol-v2.adoc index 1652fef3ae..5598c93e67 100644 --- a/Documentation/gitprotocol-v2.adoc +++ b/Documentation/gitprotocol-v2.adoc @@ -184,9 +184,13 @@ form `agent=X`) to notify the client that the server is running version the `agent` capability with a value `Y` (in the form `agent=Y`) in its request to the server (but it MUST NOT do so if the server did not advertise the agent capability). The `X` and `Y` strings may contain any -printable ASCII characters except space (i.e., the byte range 32 < x < -127), and are typically of the form "package/version" (e.g., -"git/1.8.3.1"). The agent strings are purely informative for statistics +printable ASCII characters except space (i.e., the byte range 33 <= x <= +126), and are typically of the form "package/version-os" (e.g., +"git/1.8.3.1-Linux") where `os` is the operating system name (e.g., +"Linux"). `X` and `Y` can be configured using the GIT_USER_AGENT +environment variable and it takes priority. The `os` is +retrieved using the 'sysname' field of the `uname(2)` system call +or its equivalent. The agent strings are purely informative for statistics and debugging purposes, and MUST NOT be used to programmatically assume the presence or absence of particular features. @@ -781,6 +785,60 @@ retrieving the header from a bundle at the indicated URI, and thus save themselves and the server(s) the request(s) needed to inspect the headers of that bundle or bundles. +promisor-remote=<pr-infos> +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The server may advertise some promisor remotes it is using or knows +about to a client which may want to use them as its promisor remotes, +instead of this repository. In this case <pr-infos> should be of the +form: + + pr-infos = pr-info | pr-infos ";" pr-info + + pr-info = "name=" pr-name | "name=" pr-name "," "url=" pr-url + +where `pr-name` is the urlencoded name of a promisor remote, and +`pr-url` the urlencoded URL of that promisor remote. + +In this case, if the client decides to use one or more promisor +remotes the server advertised, it can reply with +"promisor-remote=<pr-names>" where <pr-names> should be of the form: + + pr-names = pr-name | pr-names ";" pr-name + +where `pr-name` is the urlencoded name of a promisor remote the server +advertised and the client accepts. + +Note that, everywhere in this document, `pr-name` MUST be a valid +remote name, and the ';' and ',' characters MUST be encoded if they +appear in `pr-name` or `pr-url`. + +If the server doesn't know any promisor remote that could be good for +a client to use, or prefers a client not to use any promisor remote it +uses or knows about, it shouldn't advertise the "promisor-remote" +capability at all. + +In this case, or if the client doesn't want to use any promisor remote +the server advertised, the client shouldn't advertise the +"promisor-remote" capability at all in its reply. + +The "promisor.advertise" and "promisor.acceptFromServer" configuration +options can be used on the server and client side to control what they +advertise or accept respectively. See the documentation of these +configuration options for more information. + +Note that in the future it would be nice if the "promisor-remote" +protocol capability could be used by the server, when responding to +`git fetch` or `git clone`, to advertise better-connected remotes that +the client can use as promisor remotes, instead of this repository, so +that the client can lazily fetch objects from these other +better-connected remotes. This would require the server to omit in its +response the objects available on the better-connected remotes that +the client has accepted. This hasn't been implemented yet though. So +for now this "promisor-remote" capability is useful only when the +server advertises some promisor remotes it already uses to borrow +objects from. + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/gitrepository-layout.adoc b/Documentation/gitrepository-layout.adoc index 6348ef1dcd..7421ef956d 100644 --- a/Documentation/gitrepository-layout.adoc +++ b/Documentation/gitrepository-layout.adoc @@ -152,6 +152,7 @@ config.worktree:: working directory in multiple working directory setup (see linkgit:git-worktree[1]). +ifndef::with-breaking-changes[] branches:: A deprecated way to store shorthands to be used to specify a URL to 'git fetch', 'git pull' and 'git push'. @@ -164,6 +165,7 @@ branches:: "$GIT_COMMON_DIR/branches" will be used instead. + Git will stop reading remotes from this directory in Git 3.0. +endif::with-breaking-changes[] hooks:: Hooks are customization scripts used by various Git @@ -231,6 +233,7 @@ info/sparse-checkout:: This file stores sparse checkout patterns. See also: linkgit:git-read-tree[1]. +ifndef::with-breaking-changes[] remotes:: Stores shorthands for URL and default refnames for use when interacting with remote repositories via 'git fetch', @@ -241,6 +244,7 @@ remotes:: "$GIT_COMMON_DIR/remotes" will be used instead. + Git will stop reading remotes from this directory in Git 3.0. +endif::with-breaking-changes[] logs:: Records of changes made to refs are stored in this directory. diff --git a/Documentation/gitweb.adoc b/Documentation/gitweb.adoc index 5e2b491ec2..4261f9e235 100644 --- a/Documentation/gitweb.adoc +++ b/Documentation/gitweb.adoc @@ -103,6 +103,7 @@ You can generate the projects list index file using the project_index action "Generating projects list using gitweb" section below. Example contents: + ----------------------------------------------------------------------- foo.git Joe+R+Hacker+<joe@example.com> foo/bar.git O+W+Ner+<owner@example.org> @@ -124,6 +125,7 @@ Generating projects list using gitweb We assume that GITWEB_CONFIG has its default Makefile value, namely 'gitweb_config.perl'. Put the following in 'gitweb_make_index.perl' file: + ---------------------------------------------------------------------------- read_config_file("gitweb_config.perl"); $projects_list = $projectroot; @@ -518,12 +520,14 @@ rules. If you use the rewrite rules from the example you *might* also need something like the following in your gitweb configuration file (`/etc/gitweb.conf` following example): + ---------------------------------------------------------------------------- @stylesheets = ("/some/absolute/path/gitweb.css"); $my_uri = "/"; $home_link = "/"; $per_request_config = 1; ---------------------------------------------------------------------------- + Nowadays though gitweb should create HTML base tag when needed (to set base URI for relative links), so it should work automatically. @@ -535,6 +539,7 @@ Apache virtual host and gitweb configuration files in the following way. The virtual host configuration (in Apache configuration file) should look like this: + -------------------------------------------------------------------------- <VirtualHost *:80> ServerName git.example.org @@ -575,9 +580,11 @@ like this: Here actual project root is passed to gitweb via `GITWEB_PROJECT_ROOT` environment variable from a web server, so you need to put the following line in gitweb configuration file (`/etc/gitweb.conf` in above example): + -------------------------------------------------------------------------- $projectroot = $ENV{'GITWEB_PROJECTROOT'} || "/pub/git"; -------------------------------------------------------------------------- + *Note* that this requires to be set for each request, so either `$per_request_config` must be false, or the above must be put in code referenced by `$per_request_config`; @@ -604,9 +611,11 @@ the third and the fourth. PATH_INFO usage ~~~~~~~~~~~~~~~ If you enable PATH_INFO usage in gitweb by putting + ---------------------------------------------------------------------------- $feature{'pathinfo'}{'default'} = [1]; ---------------------------------------------------------------------------- + in your gitweb configuration file, it is possible to set up your server so that it consumes and produces URLs in the form @@ -636,6 +645,7 @@ complementary static files (stylesheet, favicon, JavaScript): </Directory> </VirtualHost> ---------------------------------------------------------------------------- + The rewrite rule guarantees that existing static files will be properly served, whereas any other URL will be passed to gitweb as PATH_INFO parameter. @@ -647,6 +657,7 @@ for fetching" section). A possible workaround for the latter is the following: in your project root dir (e.g. `/pub/git`) have the projects named *without* a .git extension (e.g. `/pub/git/project` instead of `/pub/git/project.git`) and configure Apache as follows: + ---------------------------------------------------------------------------- <VirtualHost *:80> ServerAlias git.example.com diff --git a/Documentation/gitweb.conf.adoc b/Documentation/gitweb.conf.adoc index 85983587fc..1348e9b125 100644 --- a/Documentation/gitweb.conf.adoc +++ b/Documentation/gitweb.conf.adoc @@ -603,6 +603,7 @@ Many gitweb features can be enabled (or disabled) and configured using the Each `%feature` hash element is a hash reference and has the following structure: + ---------------------------------------------------------------------- "<feature-name>" => { "sub" => <feature-sub-(subroutine)>, @@ -613,6 +614,7 @@ structure: Some features cannot be overridden per project. For those features the structure of appropriate `%feature` hash element has a simpler form: + ---------------------------------------------------------------------- "<feature-name>" => { "override" => 0, diff --git a/Documentation/howto/howto-index.sh b/Documentation/howto/howto-index.sh index eecd123a93..ace49830a8 100755 --- a/Documentation/howto/howto-index.sh +++ b/Documentation/howto/howto-index.sh @@ -9,9 +9,9 @@ people describing how they use Git in their workflow. EOF -for txt +for adoc do - title=$(expr "$txt" : '.*/\(.*\)\.txt$') + title=$(expr "$adoc" : '.*/\(.*\)\.adoc$') from=$(sed -ne ' /^$/q /^From:[ ]/{ @@ -21,7 +21,7 @@ do s/^/by / p } - ' "$txt") + ' "$adoc") abstract=$(sed -ne ' /^Abstract:[ ]/{ @@ -39,13 +39,13 @@ do x p q - }' "$txt") + }' "$adoc") - if grep 'Content-type: text/asciidoc' >/dev/null $txt + if grep 'Content-type: text/asciidoc' >/dev/null $adoc then - file=$(expr "$txt" : '\(.*\)\.txt$').html + file=$(expr "$adoc" : '\(.*\)\.adoc$').html else - file="$txt" + file="$adoc" fi echo "* link:howto/$(basename "$file")[$title] $from diff --git a/Documentation/howto/meson.build b/Documentation/howto/meson.build index c023c10416..81000028c0 100644 --- a/Documentation/howto/meson.build +++ b/Documentation/howto/meson.build @@ -1,20 +1,20 @@ howto_sources = [ - 'coordinate-embargoed-releases.txt', - 'keep-canonical-history-correct.txt', - 'maintain-git.txt', - 'new-command.txt', - 'rebase-from-internal-branch.txt', - 'rebuild-from-update-hook.txt', - 'recover-corrupted-blob-object.txt', - 'recover-corrupted-object-harder.txt', - 'revert-a-faulty-merge.txt', - 'revert-branch-rebase.txt', - 'separating-topic-branches.txt', - 'setup-git-server-over-http.txt', - 'update-hook-example.txt', - 'use-git-daemon.txt', - 'using-merge-subtree.txt', - 'using-signed-tag-in-pull-request.txt', + 'coordinate-embargoed-releases.adoc', + 'keep-canonical-history-correct.adoc', + 'maintain-git.adoc', + 'new-command.adoc', + 'rebase-from-internal-branch.adoc', + 'rebuild-from-update-hook.adoc', + 'recover-corrupted-blob-object.adoc', + 'recover-corrupted-object-harder.adoc', + 'revert-a-faulty-merge.adoc', + 'revert-branch-rebase.adoc', + 'separating-topic-branches.adoc', + 'setup-git-server-over-http.adoc', + 'update-hook-example.adoc', + 'use-git-daemon.adoc', + 'using-merge-subtree.adoc', + 'using-signed-tag-in-pull-request.adoc', ] howto_index = custom_target( @@ -26,7 +26,7 @@ howto_index = custom_target( env: script_environment, capture: true, input: howto_sources, - output: 'howto-index.txt', + output: 'howto-index.adoc', ) custom_target( @@ -41,7 +41,7 @@ custom_target( foreach howto : howto_sources howto_stripped = custom_target( command: [ - find_program('sed'), + sed, '-e', '1,/^$/d', '@INPUT@', diff --git a/Documentation/howto/new-command.adoc b/Documentation/howto/new-command.adoc index 880c51112b..ac73c98be7 100644 --- a/Documentation/howto/new-command.adoc +++ b/Documentation/howto/new-command.adoc @@ -48,7 +48,7 @@ binary); this organization makes it easy for people reading the code to find things. See the CodingGuidelines document for other guidance on what we consider -good practice in C and shell, and api-builtin.txt for the support +good practice in C and shell, and builtin.h for the support functions available to built-in commands written in C. What every extension command needs diff --git a/Documentation/merge-strategies.adoc b/Documentation/merge-strategies.adoc index a5dc95a378..93822ebc4e 100644 --- a/Documentation/merge-strategies.adoc +++ b/Documentation/merge-strategies.adoc @@ -22,6 +22,13 @@ ort:: was written as a replacement for the previous default algorithm, `recursive`. + +In the case where the path is a submodule, if the submodule commit used on +one side of the merge is a descendant of the submodule commit used on the +other side of the merge, Git attempts to fast-forward to the +descendant. Otherwise, Git will treat this case as a conflict, suggesting +as a resolution a submodule commit that is descendant of the conflicting +ones, if one exists. ++ The 'ort' strategy can take the following options: ours;; @@ -96,6 +103,9 @@ recursive:: the default strategy for resolving two heads from Git v0.99.9k until v2.33.0. + +For a path that is a submodule, the same caution as 'ort' applies to this +strategy. ++ The 'recursive' strategy takes the same options as 'ort'. However, there are three additional options that 'ort' ignores (not documented above) that are potentially useful with the 'recursive' strategy: diff --git a/Documentation/meson.build b/Documentation/meson.build index 1129ce4c85..b7cdc68bc8 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -42,6 +42,7 @@ manpages = { 'git-diagnose.adoc' : 1, 'git-diff-files.adoc' : 1, 'git-diff-index.adoc' : 1, + 'git-diff-pairs.adoc' : 1, 'git-difftool.adoc' : 1, 'git-diff-tree.adoc' : 1, 'git-diff.adoc' : 1, @@ -207,9 +208,9 @@ manpages = { docs_backend = get_option('docs_backend') if docs_backend == 'auto' - if find_program('asciidoc', required: false).found() + if find_program('asciidoc', dirs: program_path, required: false).found() docs_backend = 'asciidoc' - elif find_program('asciidoctor', required: false).found() + elif find_program('asciidoctor', dirs: program_path, required: false).found() docs_backend = 'asciidoctor' else error('Neither asciidoc nor asciidoctor were found.') @@ -217,7 +218,7 @@ if docs_backend == 'auto' endif if docs_backend == 'asciidoc' - asciidoc = find_program('asciidoc', required: true) + asciidoc = find_program('asciidoc', dirs: program_path) asciidoc_html = 'xhtml11' asciidoc_docbook = 'docbook' xmlto_extra = [ ] @@ -246,7 +247,7 @@ if docs_backend == 'asciidoc' asciidoc_conf, ] elif docs_backend == 'asciidoctor' - asciidoctor = find_program('asciidoctor', required: true) + asciidoctor = find_program('asciidoctor', dirs: program_path) asciidoc_html = 'xhtml5' asciidoc_docbook = 'docbook5' xmlto_extra = [ @@ -284,8 +285,11 @@ elif docs_backend == 'asciidoctor' ] endif -git = find_program('git', required: false) -xmlto = find_program('xmlto') +if get_option('breaking_changes') + asciidoc_common_options += ['--attribute', 'with-breaking-changes'] +endif + +xmlto = find_program('xmlto', dirs: program_path) cmd_lists = [ 'cmds-ancillaryinterrogators.adoc', @@ -406,7 +410,7 @@ if get_option('docs').contains('html') pointing_to: 'git.html', ) - xsltproc = find_program('xsltproc') + xsltproc = find_program('xsltproc', dirs: program_path) user_manual_xml = custom_target( command: asciidoc_common_options + [ diff --git a/Documentation/rev-list-options.adoc b/Documentation/rev-list-options.adoc index 785c0786e0..9d020e305a 100644 --- a/Documentation/rev-list-options.adoc +++ b/Documentation/rev-list-options.adoc @@ -429,6 +429,7 @@ filtered for `foo`, they look different and equal, respectively.) In the following, we will always refer to the same example history to illustrate the differences between simplification settings. We assume that you are filtering for a file `foo` in this commit graph: + ----------------------------------------------------------------------- .-A---M---N---O---P---Q / / / / / / @@ -436,6 +437,7 @@ that you are filtering for a file `foo` in this commit graph: \ / / / / / `-------------' X ----------------------------------------------------------------------- + The horizontal line of history A---Q is taken to be the first parent of each merge. The commits are: diff --git a/Documentation/technical/api-simple-ipc.adoc b/Documentation/technical/api-simple-ipc.adoc index c4fb152b23..972178b042 100644 --- a/Documentation/technical/api-simple-ipc.adoc +++ b/Documentation/technical/api-simple-ipc.adoc @@ -36,7 +36,7 @@ Comparison with sub-process model --------------------------------- The Simple-IPC mechanism differs from the existing `sub-process.c` -model (Documentation/technical/long-running-process-protocol.txt) and +model (Documentation/technical/long-running-process-protocol.adoc) and used by applications like Git-LFS. In the LFS-style sub-process model, the helper is started by the foreground process, communication happens via a pair of file descriptors bound to the stdin/stdout of the diff --git a/Documentation/technical/hash-function-transition.adoc b/Documentation/technical/hash-function-transition.adoc index 7102c7c8f5..f047fd80ca 100644 --- a/Documentation/technical/hash-function-transition.adoc +++ b/Documentation/technical/hash-function-transition.adoc @@ -394,7 +394,7 @@ inflated again in step 3, for a total of two inflations. Step 4 is probably necessary for good read-time performance. "git pack-objects" on the server optimizes the pack file for good data -locality (see Documentation/technical/pack-heuristics.txt). +locality (see Documentation/technical/pack-heuristics.adoc). Details of this process are likely to change. It will take some experimenting to get this to perform well. diff --git a/Documentation/technical/large-object-promisors.adoc b/Documentation/technical/large-object-promisors.adoc new file mode 100644 index 0000000000..dea8dafa66 --- /dev/null +++ b/Documentation/technical/large-object-promisors.adoc @@ -0,0 +1,656 @@ +Large Object Promisors +====================== + +Since Git has been created, users have been complaining about issues +with storing large files in Git. Some solutions have been created to +help, but they haven't helped much with some issues. + +Git currently supports multiple promisor remotes, which could help +with some of these remaining issues, but it's very hard to use them to +help, because a number of important features are missing. + +The goal of the effort described in this document is to add these +important features. + +We will call a "Large Object Promisor", or "LOP" in short, a promisor +remote which is used to store only large blobs and which is separate +from the main remote that should store the other Git objects and the +rest of the repos. + +By extension, we will also call "Large Object Promisor", or LOP, the +effort described in this document to add a set of features to make it +easier to handle large blobs/files in Git by using LOPs. + +This effort aims to especially improve things on the server side, and +especially for large blobs that are already compressed in a binary +format. + +This effort aims to provide an alternative to Git LFS +(https://git-lfs.com/) and similar tools like git-annex +(https://git-annex.branchable.com/) for handling large files, even +though a complete alternative would very likely require other efforts +especially on the client side, where it would likely help to implement +a new object representation for large blobs as discussed in: + +https://lore.kernel.org/git/xmqqbkdometi.fsf@gitster.g/ + +0) Non goals +------------ + +- We will not discuss those client side improvements here, as they + would require changes in different parts of Git than this effort. ++ +So we don't pretend to fully replace Git LFS with only this effort, +but we nevertheless believe that it can significantly improve the +current situation on the server side, and that other separate +efforts could also improve the situation on the client side. + +- In the same way, we are not going to discuss all the possible ways + to implement a LOP or their underlying object storage, or to + optimize how LOP works. ++ +Our opinion is that the simplest solution for now is for LOPs to use +object storage through a remote helper (see section II.2 below for +more details) to store their objects. So we consider that this is the +default implementation. If there are improvements on top of this, +that's great, but our opinion is that such improvements are not +necessary for LOPs to already be useful. Such improvements are likely +a different technical topic, and can be taken care of separately +anyway. ++ +So in particular we are not going to discuss pluggable ODBs or other +object database backends that could chunk large blobs, dedup the +chunks and store them efficiently. Sure, that would be a nice +improvement to store large blobs on the server side, but we believe +it can just be a separate effort as it's also not technically very +related to this effort. ++ +We are also not going to discuss data transfer improvements between +LOPs and clients or servers. Sure, there might be some easy and very +effective optimizations there (as we know that objects on LOPs are +very likely incompressible and not deltifying well), but this can be +dealt with separately in a separate effort. + +In other words, the goal of this document is not to talk about all the +possible ways to optimize how Git could handle large blobs, but to +describe how a LOP based solution can already work well and alleviate +a number of current issues in the context of Git clients and servers +sharing Git objects. + +Even if LOPs are used not very efficiently, they can still be useful +and worth using in some cases, as we will see in more details +later in this document: + + - they can make it simpler for clients to use promisor remotes and + therefore avoid fetching a lot of large blobs they might not need + locally, + + - they can make it significantly cheaper or easier for servers to + host a significant part of the current repository content, and + even more to host content with larger blobs or more large blobs + than currently. + +I) Issues with the current situation +------------------------------------ + +- Some statistics made on GitLab repos have shown that more than 75% + of the disk space is used by blobs that are larger than 1MB and + often in a binary format. + +- So even if users could use Git LFS or similar tools to store a lot + of large blobs out of their repos, it's a fact that in practice they + don't do it as much as they probably should. + +- On the server side ideally, the server should be able to decide for + itself how it stores things. It should not depend on users deciding + to use tools like Git LFS on some blobs or not. + +- It's much more expensive to store large blobs that don't delta + compress well on regular fast seeking drives (like SSDs) than on + object storage (like Amazon S3 or GCP Buckets). Using fast drives + for regular Git repos makes sense though, as serving regular Git + content (blobs containing text or code) needs drives where seeking + is fast, but the content is relatively small. On the other hand, + object storage for Git LFS blobs makes sense as seeking speed is not + as important when dealing with large files, while costs are more + important. So the fact that users don't use Git LFS or similar tools + for a significant number of large blobs has likely some bad + consequences on the cost of repo storage for most Git hosting + platforms. + +- Having large blobs handled in the same way as other blobs and Git + objects in Git repos instead of on object storage also has a cost in + increased memory and CPU usage, and therefore decreased performance, + when creating packfiles. (This is because Git tries to use delta + compression or zlib compression which is unlikely to work well on + already compressed binary content.) So it's not just a storage cost + increase. + +- When a large blob has been committed into a repo, it might not be + possible to remove this blob from the repo without rewriting + history, even if the user then decides to use Git LFS or a similar + tool to handle it. + +- In fact Git LFS and similar tools are not very flexible in letting + users change their minds about the blobs they should handle or not. + +- Even when users are using Git LFS or similar tools, they are often + complaining that these tools require significant effort to set up, + learn and use correctly. + +II) Main features of the "Large Object Promisors" solution +---------------------------------------------------------- + +The main features below should give a rough overview of how the +solution may work. Details about needed elements can be found in +following sections. + +Even if each feature below is very useful for the full solution, it is +very likely to be also useful on its own in some cases where the full +solution is not required. However, we'll focus primarily on the big +picture here. + +Also each feature doesn't need to be implemented entirely in Git +itself. Some could be scripts, hooks or helpers that are not part of +the Git repo. It would be helpful if those could be shared and +improved on collaboratively though. So we want to encourage sharing +them. + +1) Large blobs are stored on LOPs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Large blobs should be stored on special promisor remotes that we will +call "Large Object Promisors" or LOPs. These LOPs should be additional +remotes dedicated to contain large blobs especially those in binary +format. They should be used along with main remotes that contain the +other objects. + +Note 1 +++++++ + +To clarify, a LOP is a normal promisor remote, except that: + +- it should store only large blobs, + +- it should be separate from the main remote, so that the main remote + can focus on serving other objects and the rest of the repos (see + feature 4) below) and can use the LOP as a promisor remote for + itself. + +Note 2 +++++++ + +Git already makes it possible for a main remote to also be a promisor +remote storing both regular objects and large blobs for a client that +clones from it with a filter on blob size. But here we explicitly want +to avoid that. + +Rationale ++++++++++ + +LOPs aim to be good at handling large blobs while main remotes are +already good at handling other objects. + +Implementation +++++++++++++++ + +Git already has support for multiple promisor remotes, see +link:partial-clone.html#using-many-promisor-remotes[the partial clone documentation]. + +Also, Git already has support for partial clone using a filter on the +size of the blobs (with `git clone --filter=blob:limit=<size>`). Most +of the other main features below are based on these existing features +and are about making them easy and efficient to use for the purpose of +better handling large blobs. + +2) LOPs can use object storage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +LOPs can be implemented using object storage, like an Amazon S3 or GCP +Bucket or MinIO (which is open source under the GNU AGPLv3 license) to +actually store the large blobs, and can be accessed through a Git +remote helper (see linkgit:gitremote-helpers[7]) which makes the +underlying object storage appear like a remote to Git. + +Note +++++ + +A LOP can be a promisor remote accessed using a remote helper by +both some clients and the main remote. + +Rationale ++++++++++ + +This looks like the simplest way to create LOPs that can cheaply +handle many large blobs. + +Implementation +++++++++++++++ + +Remote helpers are quite easy to write as shell scripts, but it might +be more efficient and maintainable to write them using other languages +like Go. + +Some already exist under open source licenses, for example: + + - https://github.com/awslabs/git-remote-s3 + - https://gitlab.com/eric.p.ju/git-remote-gs + +Other ways to implement LOPs are certainly possible, but the goal of +this document is not to discuss how to best implement a LOP or its +underlying object storage (see the "0) Non goals" section above). + +3) LOP object storage can be Git LFS storage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The underlying object storage that a LOP uses could also serve as +storage for large files handled by Git LFS. + +Rationale ++++++++++ + +This would simplify the server side if it wants to both use a LOP and +act as a Git LFS server. + +4) A main remote can offload to a LOP with a configurable threshold +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On the server side, a main remote should have a way to offload to a +LOP all its blobs with a size over a configurable threshold. + +Rationale ++++++++++ + +This makes it easy to set things up and to clean things up. For +example, an admin could use this to manually convert a repo not using +LOPs to a repo using a LOP. On a repo already using a LOP but where +some users would sometimes push large blobs, a cron job could use this +to regularly make sure the large blobs are moved to the LOP. + +Implementation +++++++++++++++ + +Using something based on `git repack --filter=...` to separate the +blobs we want to offload from the other Git objects could be a good +idea. The missing part is to connect to the LOP, check if the blobs we +want to offload are already there and if not send them. + +5) A main remote should try to remain clean from large blobs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A main remote should try to avoid containing a lot of oversize +blobs. For that purpose, it should offload as needed to a LOP and it +should have ways to prevent oversize blobs to be fetched, and also +perhaps pushed, into it. + +Rationale ++++++++++ + +A main remote containing many oversize blobs would defeat the purpose +of LOPs. + +Implementation +++++++++++++++ + +The way to offload to a LOP discussed in 4) above can be used to +regularly offload oversize blobs. About preventing oversize blobs from +being fetched into the repo see 6) below. About preventing oversize +blob pushes, a pre-receive hook could be used. + +Also there are different scenarios in which large blobs could get +fetched into the main remote, for example: + +- A client that doesn't implement the "promisor-remote" protocol + (described in 6) below) clones from the main remote. + +- The main remote gets a request for information about a large blob + and is not able to get that information without fetching the blob + from the LOP. + +It might not be possible to completely prevent all these scenarios +from happening. So the goal here should be to implement features that +make the fetching of large blobs less likely. For example adding a +`remote-object-info` command in the `git cat-file --batch` protocol +and its variants might make it possible for a main repo to respond to +some requests about large blobs without fetching them. + +6) A protocol negotiation should happen when a client clones +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When a client clones from a main repo, there should be a protocol +negotiation so that the server can advertise one or more LOPs and so +that the client and the server can discuss if the client could +directly use a LOP the server is advertising. If the client and the +server can agree on that, then the client would be able to get the +large blobs directly from the LOP and the server would not need to +fetch those blobs from the LOP to be able to serve the client. + +Note +++++ + +For fetches instead of clones, a protocol negotiation might not always +happen, see the "What about fetches?" FAQ entry below for details. + +Rationale ++++++++++ + +Security, configurability and efficiency of setting things up. + +Implementation +++++++++++++++ + +A "promisor-remote" protocol v2 capability looks like a good way to +implement this. The way the client and server use this capability +could be controlled by configuration variables. + +Information that the server could send to the client through that +protocol could be things like: LOP name, LOP URL, filter-spec (for +example `blob:limit=<size>`) or just size limit that should be used as +a filter when cloning, token to be used with the LOP, etc. + +7) A client can offload to a LOP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When a client is using a LOP that is also a LOP of its main remote, +the client should be able to offload some large blobs it has fetched, +but might not need anymore, to the LOP. + +Note +++++ + +It might depend on the context if it should be OK or not for clients +to offload large blobs they have created, instead of fetched, directly +to the LOP without the main remote checking them in some ways +(possibly using hooks or other tools). + +This should be discussed and refined when we get closer to +implementing this feature. + +Rationale ++++++++++ + +On the client, the easiest way to deal with unneeded large blobs is to +offload them. + +Implementation +++++++++++++++ + +This is very similar to what 4) above is about, except on the client +side instead of the server side. So a good solution to 4) could likely +be adapted to work on the client side too. + +There might be some security issues here, as there is no negotiation, +but they might be mitigated if the client can reuse a token it got +when cloning (see 6) above). Also if the large blobs were fetched from +a LOP, it is likely, and can easily be confirmed, that the LOP still +has them, so that they can just be removed from the client. + +III) Benefits of using LOPs +--------------------------- + +Many benefits are related to the issues discussed in "I) Issues with +the current situation" above: + +- No need to rewrite history when deciding which blobs are worth + handling separately than other objects, or when moving or removing + the threshold. + +- If the protocol between client and server is developed and secured + enough, then many details might be setup on the server side only and + all the clients could then easily get all the configuration + information and use it to set themselves up mostly automatically. + +- Storage costs benefits on the server side. + +- Reduced memory and CPU needs on main remotes on the server side. + +- Reduced storage needs on the client side. + +IV) FAQ +------- + +What about using multiple LOPs on the server and client side? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +That could perhaps be useful in some cases, but for now it's more +likely that in most cases a single LOP will be advertised by the +server and should be used by the client. + +A case where it could be useful for a server to advertise multiple +LOPs is if a LOP is better for some users while a different LOP is +better for other users. For example some clients might have a better +connection to a LOP than others. + +In those cases it's the responsibility of the server to have some +documentation to help clients. It could say for example something like +"Users in this part of the world might want to pick only LOP A as it +is likely to be better connected to them, while users in other parts +of the world should pick only LOP B for the same reason." + +When should we trust or not trust the LOPs advertised by the server? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In some contexts, like in corporate setup where the server and all the +clients are parts of an internal network in a company where admins +have all the rights on every system, it's OK, and perhaps even a good +thing, if the clients fully trust the server, as it can help ensure +that all the clients are on the same page. + +There are also contexts in which clients trust a code hosting platform +serving them some repos, but might not fully trust other users +managing or contributing to some of these repos. For example, the code +hosting platform could have hooks in place to check that any object it +receives doesn't contain malware or otherwise bad content. In this +case it might be OK for the client to use a main remote and its LOP if +they are both hosted by the code hosting platform, but not if the LOP +is hosted elsewhere (where the content is not checked). + +In other contexts, a client should just not trust a server. + +So there should be different ways to configure how the client should +behave when a server advertises a LOP to it at clone time. + +As the basic elements that a server can advertise about a LOP are a +LOP name and a LOP URL, the client should base its decision about +accepting a LOP on these elements. + +One simple way to be very strict in the LOP it accepts is for example +for the client to check that the LOP is already configured on the +client with the same name and URL as what the server advertises. + +In general default and "safe" settings should require that the LOP are +configured on the client separately from the "promisor-remote" +protocol and that the client accepts a LOP only when information about +it from the protocol matches what has been already configured +separately. + +What about LOP names? +~~~~~~~~~~~~~~~~~~~~~ + +In some contexts, for example if the clients sometimes fetch from each +other, it can be a good idea for all the clients to use the same names +for all the remotes they use, including LOPs. + +In other contexts, each client might want to be able to give the name +it wants to each remote, including each LOP, it interacts with. + +So there should be different ways to configure how the client accepts +or not the LOP name the server advertises. + +If a default or "safe" setting is used, then as such a setting should +require that the LOP be configured separately, then the name would be +configured separately and there is no risk that the server could +dictate a name to a client. + +Could the main remote be bogged down by old or paranoid clients? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Yes, it could happen if there are too many clients that are either +unwilling to trust the main remote or that just don't implement the +"promisor-remote" protocol because they are too old or not fully +compatible with the 'git' client. + +When serving such a client, the main remote has no other choice than +to first fetch from its LOP, to then be able to provide to the client +everything it requested. So the main remote, even if it has cleanup +mechanisms (see section II.4 above), would be burdened at least +temporarily with the large blobs it had to fetch from its LOP. + +Not behaving like this would be breaking backward compatibility, and +could be seen as segregating clients. For example, it might be +possible to implement a special mode that allows the server to just +reject clients that don't implement the "promisor-remote" protocol or +aren't willing to trust the main remote. This mode might be useful in +a special context like a corporate environment. There is no plan to +implement such a mode though, and this should be discussed separately +later anyway. + +A better way to proceed is probably for the main remote to show a +message telling clients that don't implement the protocol or are +unwilling to accept the advertised LOP(s) that they would get faster +clone and fetches by upgrading client software or properly setting +them up to accept LOP(s). + +Waiting for clients to upgrade, monitoring these upgrades and limiting +the use of LOPs to repos that are not very frequently accessed might +be other good ways to make sure that some benefits are still reaped +from LOPs. Over time, as more and more clients upgrade and benefit +from LOPs, using them in more and more frequently accessed repos will +become worth it. + +Corporate environments, where it might be easier to make sure that all +the clients are up-to-date and properly configured, could hopefully +benefit more and earlier from using LOPs. + +What about fetches? +~~~~~~~~~~~~~~~~~~~ + +There are different kinds of fetches. A regular fetch happens when +some refs have been updated on the server and the client wants the ref +updates and possibly the new objects added with them. A "backfill" or +"lazy" fetch, on the contrary, happens when the client needs to use +some objects it already knows about but doesn't have because they are +on a promisor remote. + +Regular fetch ++++++++++++++ + +In a regular fetch, the client will contact the main remote and a +protocol negotiation will happen between them. It's a good thing that +a protocol negotiation happens every time, as the configuration on the +client or the main remote could have changed since the previous +protocol negotiation. In this case, the new protocol negotiation +should ensure that the new fetch will happen in a way that satisfies +the new configuration of both the client and the server. + +In most cases though, the configurations on the client and the main +remote will not have changed between 2 fetches or between the initial +clone and a subsequent fetch. This means that the result of a new +protocol negotiation will be the same as the previous result, so the +new fetch will happen in the same way as the previous clone or fetch, +using, or not using, the same LOP(s) as last time. + +"Backfill" or "lazy" fetch +++++++++++++++++++++++++++ + +When there is a backfill fetch, the client doesn't necessarily contact +the main remote first. It will try to fetch from its promisor remotes +in the order they appear in the config file, except that a remote +configured using the `extensions.partialClone` config variable will be +tried last. See +link:partial-clone.html#using-many-promisor-remotes[the partial clone documentation]. + +This is not new with this effort. In fact this is how multiple remotes +have already been working for around 5 years. + +When using LOPs, having the main remote configured using +`extensions.partialClone`, so it's tried last, makes sense, as missing +objects should only be large blobs that are on LOPs. + +This means that a protocol negotiation will likely not happen as the +missing objects will be fetched from the LOPs, and then there will be +nothing left to fetch from the main remote. + +To secure that, it could be a good idea for LOPs to require a token +from the client when it fetches from them. The client could get the +token when performing a protocol negotiation with the main remote (see +section II.6 above). + +V) Future improvements +---------------------- + +It is expected that at the beginning using LOPs will be mostly worth +it either in a corporate context where the Git version that clients +use can easily be controlled, or on repos that are infrequently +accessed. (See the "Could the main remote be bogged down by old or +paranoid clients?" section in the FAQ above.) + +Over time, as more and more clients upgrade to a version that +implements the "promisor-remote" protocol v2 capability described +above in section II.6), it will be worth it to use LOPs more widely. + +A lot of improvements may also help using LOPs more widely. Some of +these improvements are part of the scope of this document like the +following: + + - Implementing a "remote-object-info" command in the + `git cat-file --batch` protocol and its variants to allow main + remotes to respond to requests about large blobs without fetching + them. (Eric Ju has started working on this based on previous work + by Calvin Wan.) + + - Creating better cleanup and offload mechanisms for main remotes + and clients to prevent accumulation of large blobs. + + - Developing more sophisticated protocol negotiation capabilities + between clients and servers for handling LOPs, for example adding + a filter-spec (e.g., blob:limit=<size>) or size limit for + filtering when cloning, or adding a token for LOP authentication. + + - Improving security measures for LOP access, particularly around + token handling and authentication. + + - Developing standardized ways to configure and manage multiple LOPs + across different environments. Especially in the case where + different LOPs serve the same content to clients in different + geographical locations, there is a need for replication or + synchronization between LOPs. + +Some improvements, including some that have been mentioned in the "0) +Non Goals" section of this document, are out of the scope of this +document: + + - Implementing a new object representation for large blobs on the + client side. + + - Developing pluggable ODBs or other object database backends that + could chunk large blobs, dedup the chunks and store them + efficiently. + + - Optimizing data transfer between LOPs and clients/servers, + particularly for incompressible and non-deltifying content. + + - Creating improved client side tools for managing large objects + more effectively, for example tools for migrating from Git LFS or + git-annex, or tools to find which objects could be offloaded and + how much disk space could be reclaimed by offloading them. + +Some improvements could be seen as part of the scope of this document, +but might already have their own separate projects from the Git +project, like: + + - Improving existing remote helpers to access object storage or + developing new ones. + + - Improving existing object storage solutions or developing new + ones. + +Even though all the above improvements may help, this document and the +LOP effort should try to focus, at least first, on a relatively small +number of improvements mostly those that are in its current scope. + +For example introducing pluggable ODBs and a new object database +backend is likely a multi-year effort on its own that can happen +separately in parallel. It has different technical requirements, +touches other part of the Git code base and should have its own design +document(s). diff --git a/Documentation/technical/meson.build b/Documentation/technical/meson.build index 3a65ee59b3..a13aafcfbb 100644 --- a/Documentation/technical/meson.build +++ b/Documentation/technical/meson.build @@ -1,37 +1,37 @@ api_docs = [ - 'api-error-handling.txt', - 'api-merge.txt', - 'api-parse-options.txt', - 'api-simple-ipc.txt', - 'api-trace2.txt', + 'api-error-handling.adoc', + 'api-merge.adoc', + 'api-parse-options.adoc', + 'api-simple-ipc.adoc', + 'api-trace2.adoc', ] articles = [ - 'bitmap-format.txt', - 'build-systems.txt', - 'bundle-uri.txt', - 'commit-graph.txt', - 'directory-rename-detection.txt', - 'hash-function-transition.txt', - 'long-running-process-protocol.txt', - 'multi-pack-index.txt', - 'packfile-uri.txt', - 'pack-heuristics.txt', - 'parallel-checkout.txt', - 'partial-clone.txt', - 'platform-support.txt', - 'racy-git.txt', - 'reftable.txt', - 'remembering-renames.txt', - 'repository-version.txt', - 'rerere.txt', - 'scalar.txt', - 'send-pack-pipeline.txt', - 'shallow.txt', - 'sparse-checkout.txt', - 'sparse-index.txt', - 'trivial-merge.txt', - 'unit-tests.txt', + 'bitmap-format.adoc', + 'build-systems.adoc', + 'bundle-uri.adoc', + 'commit-graph.adoc', + 'directory-rename-detection.adoc', + 'hash-function-transition.adoc', + 'long-running-process-protocol.adoc', + 'multi-pack-index.adoc', + 'packfile-uri.adoc', + 'pack-heuristics.adoc', + 'parallel-checkout.adoc', + 'partial-clone.adoc', + 'platform-support.adoc', + 'racy-git.adoc', + 'reftable.adoc', + 'remembering-renames.adoc', + 'repository-version.adoc', + 'rerere.adoc', + 'scalar.adoc', + 'send-pack-pipeline.adoc', + 'shallow.adoc', + 'sparse-checkout.adoc', + 'sparse-index.adoc', + 'trivial-merge.adoc', + 'unit-tests.adoc', ] api_index = custom_target( @@ -43,7 +43,7 @@ api_index = custom_target( ], env: script_environment, input: api_docs, - output: 'api-index.txt', + output: 'api-index.adoc', ) custom_target( diff --git a/Documentation/technical/partial-clone.adoc b/Documentation/technical/partial-clone.adoc index bf5ec5c82d..e513e391ea 100644 --- a/Documentation/technical/partial-clone.adoc +++ b/Documentation/technical/partial-clone.adoc @@ -85,7 +85,7 @@ See "filter" in linkgit:gitprotocol-pack[5]. server to request filtering during packfile construction. + There are various filters available to accommodate different situations. -See "--filter=<filter-spec>" in Documentation/rev-list-options.txt. +See "--filter=<filter-spec>" in Documentation/rev-list-options.adoc. - On the server pack-objects applies the requested filter-spec as it creates "filtered" packfiles for the client. diff --git a/GIT-BUILD-OPTIONS.in b/GIT-BUILD-OPTIONS.in index ada575fbcb..0a9884e0ad 100644 --- a/GIT-BUILD-OPTIONS.in +++ b/GIT-BUILD-OPTIONS.in @@ -9,14 +9,13 @@ GIT_PERF_MAKE_COMMAND=@GIT_PERF_MAKE_COMMAND@ GIT_PERF_MAKE_OPTS=@GIT_PERF_MAKE_OPTS@ GIT_PERF_REPEAT_COUNT=@GIT_PERF_REPEAT_COUNT@ GIT_PERF_REPO=@GIT_PERF_REPO@ +GIT_SOURCE_DIR=@GIT_SOURCE_DIR@ GIT_TEST_CMP=@GIT_TEST_CMP@ GIT_TEST_CMP_USE_COPIED_CONTEXT=@GIT_TEST_CMP_USE_COPIED_CONTEXT@ GIT_TEST_GITPERLLIB=@GIT_TEST_GITPERLLIB@ GIT_TEST_INDEX_VERSION=@GIT_TEST_INDEX_VERSION@ -GIT_TEST_MERGE_TOOLS_DIR=@GIT_TEST_MERGE_TOOLS_DIR@ GIT_TEST_OPTS=@GIT_TEST_OPTS@ GIT_TEST_PERL_FATAL_WARNINGS=@GIT_TEST_PERL_FATAL_WARNINGS@ -GIT_TEST_POPATH=@GIT_TEST_POPATH@ GIT_TEST_TEMPLATE_DIR=@GIT_TEST_TEMPLATE_DIR@ GIT_TEST_TEXTDOMAINDIR=@GIT_TEST_TEXTDOMAINDIR@ GIT_TEST_UTF8_LOCALE=@GIT_TEST_UTF8_LOCALE@ diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 56b45333c1..b981598298 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,6 +1,6 @@ #!/bin/sh -DEF_VER=v2.48.GIT +DEF_VER=v2.49.GIT LF=' ' @@ -194,7 +194,7 @@ include shared.mak # Linux, kernel 2.6.11 or newer is required for reliable sub-second file times # on file systems with exactly 1 ns or 1 s resolution. If you intend to use Git # on other file systems (e.g. CEPH, CIFS, NTFS, UDF), don't enable USE_NSEC. See -# Documentation/technical/racy-git.txt for details. +# Documentation/technical/racy-git.adoc for details. # # Define USE_ST_TIMESPEC if your "struct stat" uses "st_ctimespec" instead of # "st_ctim" @@ -1242,6 +1242,7 @@ BUILTIN_OBJS += builtin/describe.o BUILTIN_OBJS += builtin/diagnose.o BUILTIN_OBJS += builtin/diff-files.o BUILTIN_OBJS += builtin/diff-index.o +BUILTIN_OBJS += builtin/diff-pairs.o BUILTIN_OBJS += builtin/diff-tree.o BUILTIN_OBJS += builtin/diff.o BUILTIN_OBJS += builtin/difftool.o @@ -1356,6 +1357,9 @@ CLAR_TEST_SUITES += u-example-decorate CLAR_TEST_SUITES += u-hash CLAR_TEST_SUITES += u-hashmap CLAR_TEST_SUITES += u-mem-pool +CLAR_TEST_SUITES += u-oid-array +CLAR_TEST_SUITES += u-oidmap +CLAR_TEST_SUITES += u-oidtree CLAR_TEST_SUITES += u-prio-queue CLAR_TEST_SUITES += u-reftable-tree CLAR_TEST_SUITES += u-strbuf @@ -1365,10 +1369,8 @@ CLAR_TEST_PROG = $(UNIT_TEST_BIN)/unit-tests$(X) CLAR_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(CLAR_TEST_SUITES)) CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/clar/clar.o CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o +CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/lib-oid.o -UNIT_TEST_PROGRAMS += t-oid-array -UNIT_TEST_PROGRAMS += t-oidmap -UNIT_TEST_PROGRAMS += t-oidtree UNIT_TEST_PROGRAMS += t-reftable-basics UNIT_TEST_PROGRAMS += t-reftable-block UNIT_TEST_PROGRAMS += t-reftable-merged @@ -1381,7 +1383,6 @@ UNIT_TEST_PROGRAMS += t-trailer UNIT_TEST_PROGRAMS += t-urlmatch-normalization UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS)) UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o -UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-oid.o UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-reftable.o # xdiff and reftable libs may in turn depend on what is in libgit.a @@ -1704,16 +1705,16 @@ IMAP_SEND_LDFLAGS += $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO) ifdef ZLIB_NG BASIC_CFLAGS += -DHAVE_ZLIB_NG - ifdef ZLIB_NG_PATH + ifdef ZLIB_NG_PATH BASIC_CFLAGS += -I$(ZLIB_NG_PATH)/include EXTLIBS += $(call libpath_template,$(ZLIB_NG_PATH)/$(lib)) - endif + endif EXTLIBS += -lz-ng else - ifdef ZLIB_PATH + ifdef ZLIB_PATH BASIC_CFLAGS += -I$(ZLIB_PATH)/include EXTLIBS += $(call libpath_template,$(ZLIB_PATH)/$(lib)) - endif + endif EXTLIBS += -lz endif @@ -3193,14 +3194,13 @@ GIT-BUILD-OPTIONS: FORCE -e "s|@GIT_PERF_MAKE_OPTS@|\'$(GIT_PERF_MAKE_OPTS)\'|" \ -e "s|@GIT_PERF_REPEAT_COUNT@|\'$(GIT_PERF_REPEAT_COUNT)\'|" \ -e "s|@GIT_PERF_REPO@|\'$(GIT_PERF_REPO)\'|" \ + -e "s|@GIT_SOURCE_DIR@|\'$(shell pwd)\'|" \ -e "s|@GIT_TEST_CMP@|\'$(GIT_TEST_CMP)\'|" \ -e "s|@GIT_TEST_CMP_USE_COPIED_CONTEXT@|\'$(GIT_TEST_CMP_USE_COPIED_CONTEXT)\'|" \ -e "s|@GIT_TEST_GITPERLLIB@|\'$(shell pwd)/perl/build/lib\'|" \ -e "s|@GIT_TEST_INDEX_VERSION@|\'$(GIT_TEST_INDEX_VERSION)\'|" \ - -e "s|@GIT_TEST_MERGE_TOOLS_DIR@|\'$(shell pwd)/mergetools\'|" \ -e "s|@GIT_TEST_OPTS@|\'$(GIT_TEST_OPTS)\'|" \ -e "s|@GIT_TEST_PERL_FATAL_WARNINGS@|\'$(GIT_TEST_PERL_FATAL_WARNINGS)\'|" \ - -e "s|@GIT_TEST_POPATH@|\'$(shell pwd)/po\'|" \ -e "s|@GIT_TEST_TEMPLATE_DIR@|\'$(shell pwd)/templates/blt\'|" \ -e "s|@GIT_TEST_TEXTDOMAINDIR@|\'$(shell pwd)/po/build/locale\'|" \ -e "s|@GIT_TEST_UTF8_LOCALE@|\'$(GIT_TEST_UTF8_LOCALE)\'|" \ @@ -17,15 +17,15 @@ Please read the file [INSTALL][] for installation instructions. Many Git online resources are accessible from <https://git-scm.com/> including full documentation and Git related tools. -See [Documentation/gittutorial.txt][] to get started, then see -[Documentation/giteveryday.txt][] for a useful minimum set of commands, and -`Documentation/git-<commandname>.txt` for documentation of each command. +See [Documentation/gittutorial.adoc][] to get started, then see +[Documentation/giteveryday.adoc][] for a useful minimum set of commands, and +`Documentation/git-<commandname>.adoc` for documentation of each command. If git has been correctly installed, then the tutorial can also be read with `man gittutorial` or `git help tutorial`, and the documentation of each command with `man git-<commandname>` or `git help <commandname>`. -CVS users may also want to read [Documentation/gitcvs-migration.txt][] +CVS users may also want to read [Documentation/gitcvs-migration.adoc][] (`man gitcvs-migration` or `git help cvs-migration` if git is installed). @@ -66,9 +66,9 @@ and the name as (depending on your mood): - "goddamn idiotic truckload of sh*t": when it breaks [INSTALL]: INSTALL -[Documentation/gittutorial.txt]: Documentation/gittutorial.txt -[Documentation/giteveryday.txt]: Documentation/giteveryday.txt -[Documentation/gitcvs-migration.txt]: Documentation/gitcvs-migration.txt +[Documentation/gittutorial.adoc]: Documentation/gittutorial.adoc +[Documentation/giteveryday.adoc]: Documentation/giteveryday.adoc +[Documentation/gitcvs-migration.adoc]: Documentation/gitcvs-migration.adoc [Documentation/SubmittingPatches]: Documentation/SubmittingPatches [Documentation/CodingGuidelines]: Documentation/CodingGuidelines [po/README.md]: po/README.md @@ -1 +1 @@ -Documentation/RelNotes/2.49.0.adoc
\ No newline at end of file +Documentation/RelNotes/2.50.0.adoc
\ No newline at end of file @@ -7,7 +7,7 @@ struct string_list; * To add a new advice, you need to: * Define a new advice_type. * Add a new entry to advice_setting array. - * Add the new config variable to Documentation/config/advice.txt. + * Add the new config variable to Documentation/config/advice.adoc. * Call advise_if_enabled to print your advice. */ enum advice_type { @@ -82,7 +82,7 @@ static int parse_whitespace_option(struct apply_state *state, const char *option } /* * Please update $__git_whitespacelist in git-completion.bash, - * Documentation/git-apply.txt, and Documentation/git-am.txt + * Documentation/git-apply.adoc, and Documentation/git-am.adoc * when you add new options. */ return error(_("unrecognized whitespace option '%s'"), option); @@ -930,7 +930,7 @@ static enum bisect_error check_good_are_ancestors_of_bad(struct repository *r, if (!current_bad_oid) return error(_("a %s revision is needed"), term_bad); - filename = git_pathdup("BISECT_ANCESTORS_OK"); + filename = repo_git_path(the_repository, "BISECT_ANCESTORS_OK"); /* Check if file BISECT_ANCESTORS_OK exists. */ if (!stat(filename, &st) && S_ISREG(st.st_mode)) @@ -397,7 +397,7 @@ static void prepare_checked_out_branches(void) worktrees = get_worktrees(); while (worktrees[i]) { - char *old; + char *old, *wt_gitdir; struct wt_status_state state = { 0 }; struct worktree *wt = worktrees[i++]; struct string_list update_refs = STRING_LIST_INIT_DUP; @@ -437,7 +437,8 @@ static void prepare_checked_out_branches(void) } wt_status_state_free_buffers(&state); - if (!sequencer_get_update_refs_state(get_worktree_git_dir(wt), + wt_gitdir = get_worktree_git_dir(wt); + if (!sequencer_get_update_refs_state(wt_gitdir, &update_refs)) { struct string_list_item *item; for_each_string_list_item(item, &update_refs) { @@ -448,6 +449,8 @@ static void prepare_checked_out_branches(void) } string_list_clear(&update_refs, 1); } + + free(wt_gitdir); } free_worktrees(worktrees); @@ -63,7 +63,7 @@ * * . Add tests to `t/` directory. * - * . Write documentation in `Documentation/git-foo.txt`. + * . Write documentation in `Documentation/git-foo.adoc`. * * . Add an entry for `git-foo` to `command-list.txt`. * @@ -153,6 +153,7 @@ int cmd_diagnose(int argc, const char **argv, const char *prefix, struct reposit int cmd_diff_files(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_diff_index(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_diff(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_diff_pairs(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_diff_tree(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_difftool(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_env__helper(int argc, const char **argv, const char *prefix, struct repository *repo); diff --git a/builtin/am.c b/builtin/am.c index 390b463144..2921bb89ef 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -158,7 +158,7 @@ static void am_state_init(struct am_state *state) memset(state, 0, sizeof(*state)); - state->dir = git_pathdup("rebase-apply"); + state->dir = repo_git_path(the_repository, "rebase-apply"); state->prec = 4; diff --git a/builtin/bugreport.c b/builtin/bugreport.c index 0ac59cc8dc..66d64bfd5a 100644 --- a/builtin/bugreport.c +++ b/builtin/bugreport.c @@ -12,10 +12,10 @@ #include "diagnose.h" #include "object-file.h" #include "setup.h" +#include "version.h" static void get_system_info(struct strbuf *sys_info) { - struct utsname uname_info; char *shell = NULL; /* get git version from native cmd */ @@ -24,16 +24,7 @@ static void get_system_info(struct strbuf *sys_info) /* system call for other version info */ strbuf_addstr(sys_info, "uname: "); - if (uname(&uname_info)) - strbuf_addf(sys_info, _("uname() failed with error '%s' (%d)\n"), - strerror(errno), - errno); - else - strbuf_addf(sys_info, "%s %s %s %s\n", - uname_info.sysname, - uname_info.release, - uname_info.version, - uname_info.machine); + get_uname_info(sys_info, 1); strbuf_addstr(sys_info, _("compiler info: ")); get_compiler_info(sys_info); diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c index df00b5ee13..be2cebe121 100644 --- a/builtin/check-mailmap.c +++ b/builtin/check-mailmap.c @@ -35,7 +35,7 @@ static void check_mailmap(struct string_list *mailmap, const char *contact) mail = ident.mail_begin; maillen = ident.mail_end - ident.mail_begin; } else { - name = NULL; + name = ""; namelen = 0; mail = contact; maillen = strlen(contact); diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index e30086c7d4..7f74bc702f 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -5,7 +5,6 @@ * */ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" @@ -68,10 +67,10 @@ static void write_tempfile_record(const char *name, const char *prefix) } } -static int checkout_file(const char *name, const char *prefix) +static int checkout_file(struct index_state *index, const char *name, const char *prefix) { int namelen = strlen(name); - int pos = index_name_pos(the_repository->index, name, namelen); + int pos = index_name_pos(index, name, namelen); int has_same_name = 0; int is_file = 0; int is_skipped = 1; @@ -81,8 +80,8 @@ static int checkout_file(const char *name, const char *prefix) if (pos < 0) pos = -pos - 1; - while (pos <the_repository->index->cache_nr) { - struct cache_entry *ce =the_repository->index->cache[pos]; + while (pos < index->cache_nr) { + struct cache_entry *ce = index->cache[pos]; if (ce_namelen(ce) != namelen || memcmp(ce->name, name, namelen)) break; @@ -137,13 +136,13 @@ static int checkout_file(const char *name, const char *prefix) return -1; } -static int checkout_all(const char *prefix, int prefix_length) +static int checkout_all(struct index_state *index, const char *prefix, int prefix_length) { int i, errs = 0; struct cache_entry *last_ce = NULL; - for (i = 0; i < the_repository->index->cache_nr ; i++) { - struct cache_entry *ce = the_repository->index->cache[i]; + for (i = 0; i < index->cache_nr ; i++) { + struct cache_entry *ce = index->cache[i]; if (S_ISSPARSEDIR(ce->ce_mode)) { if (!ce_skip_worktree(ce)) @@ -156,8 +155,8 @@ static int checkout_all(const char *prefix, int prefix_length) * first entry inside the expanded sparse directory). */ if (ignore_skip_worktree) { - ensure_full_index(the_repository->index); - ce = the_repository->index->cache[i]; + ensure_full_index(index); + ce = index->cache[i]; } } @@ -213,7 +212,7 @@ static int option_parse_stage(const struct option *opt, int cmd_checkout_index(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i; struct lock_file lock_file = LOCK_INIT; @@ -253,19 +252,19 @@ int cmd_checkout_index(int argc, show_usage_with_options_if_asked(argc, argv, builtin_checkout_index_usage, builtin_checkout_index_options); - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); prefix_length = prefix ? strlen(prefix) : 0; - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; - if (repo_read_index(the_repository) < 0) { + if (repo_read_index(repo) < 0) { die("invalid cache"); } argc = parse_options(argc, argv, prefix, builtin_checkout_index_options, builtin_checkout_index_usage, 0); - state.istate = the_repository->index; + state.istate = repo->index; state.force = force; state.quiet = quiet; state.not_new = not_new; @@ -285,8 +284,8 @@ int cmd_checkout_index(int argc, */ if (index_opt && !state.base_dir_len && !to_tempfile) { state.refresh_cache = 1; - state.istate = the_repository->index; - repo_hold_locked_index(the_repository, &lock_file, + state.istate = repo->index; + repo_hold_locked_index(repo, &lock_file, LOCK_DIE_ON_ERROR); } @@ -304,7 +303,7 @@ int cmd_checkout_index(int argc, if (read_from_stdin) die("git checkout-index: don't mix '--stdin' and explicit filenames"); p = prefix_path(prefix, prefix_length, arg); - err |= checkout_file(p, prefix); + err |= checkout_file(repo->index, p, prefix); free(p); } @@ -326,7 +325,7 @@ int cmd_checkout_index(int argc, strbuf_swap(&buf, &unquoted); } p = prefix_path(prefix, prefix_length, buf.buf); - err |= checkout_file(p, prefix); + err |= checkout_file(repo->index, p, prefix); free(p); } strbuf_release(&unquoted); @@ -334,7 +333,7 @@ int cmd_checkout_index(int argc, } if (all) - err |= checkout_all(prefix, prefix_length); + err |= checkout_all(repo->index, prefix, prefix_length); if (pc_workers > 1) err |= run_parallel_checkout(&state, pc_workers, pc_threshold, @@ -344,7 +343,7 @@ int cmd_checkout_index(int argc, return 1; if (is_lock_file_locked(&lock_file) && - write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK)) + write_locked_index(repo->index, &lock_file, COMMIT_LOCK)) die("Unable to write new index file"); return 0; } diff --git a/builtin/clone.c b/builtin/clone.c index f9a2ecbe9c..f14229abf4 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -835,7 +835,7 @@ static void write_refspec_config(const char *src_ref_prefix, static void dissociate_from_references(void) { - char *alternates = git_pathdup("objects/info/alternates"); + char *alternates = repo_git_path(the_repository, "objects/info/alternates"); if (!access(alternates, F_OK)) { struct child_process cmd = CHILD_PROCESS_INIT; @@ -1219,7 +1219,7 @@ int cmd_clone(int argc, strbuf_reset(&buf); strbuf_addf(&buf, "%s/refs", git_dir); - safe_create_dir(buf.buf, 1); + safe_create_dir(the_repository, buf.buf, 1); /* * additional config can be injected with -c, make sure it's included diff --git a/builtin/commit.c b/builtin/commit.c index 9fb405dd4a..2f45968222 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -352,6 +352,7 @@ static const char *prepare_index(const char **argv, const char *prefix, struct pathspec pathspec; int refresh_flags = REFRESH_QUIET; const char *ret; + char *path = NULL; if (is_status) refresh_flags |= REFRESH_UNMERGED; @@ -524,9 +525,9 @@ static const char *prepare_index(const char **argv, const char *prefix, if (write_locked_index(the_repository->index, &index_lock, 0)) die(_("unable to write new index file")); - hold_lock_file_for_update(&false_lock, - git_path("next-index-%"PRIuMAX, - (uintmax_t) getpid()), + path = repo_git_path(the_repository, "next-index-%"PRIuMAX, + (uintmax_t) getpid()); + hold_lock_file_for_update(&false_lock, path, LOCK_DIE_ON_ERROR); create_base_index(current_head); @@ -542,6 +543,7 @@ static const char *prepare_index(const char **argv, const char *prefix, out: string_list_clear(&partial, 0); clear_pathspec(&pathspec); + free(path); return ret; } diff --git a/builtin/config.c b/builtin/config.c index 16e6e30555..53a90094e3 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -775,13 +775,13 @@ static void location_options_init(struct config_location_options *opts, opts->source.file = opts->file_to_free = git_system_config(); opts->source.scope = CONFIG_SCOPE_SYSTEM; } else if (opts->use_local_config) { - opts->source.file = opts->file_to_free = git_pathdup("config"); + opts->source.file = opts->file_to_free = repo_git_path(the_repository, "config"); opts->source.scope = CONFIG_SCOPE_LOCAL; } else if (opts->use_worktree_config) { struct worktree **worktrees = get_worktrees(); if (the_repository->repository_format_worktree_config) opts->source.file = opts->file_to_free = - git_pathdup("config.worktree"); + repo_git_path(the_repository, "config.worktree"); else if (worktrees[0] && worktrees[1]) die(_("--worktree cannot be used with multiple " "working trees unless the config\n" @@ -790,7 +790,7 @@ static void location_options_init(struct config_location_options *opts, "section in \"git help worktree\" for details")); else opts->source.file = opts->file_to_free = - git_pathdup("config"); + repo_git_path(the_repository, "config"); opts->source.scope = CONFIG_SCOPE_LOCAL; free_worktrees(worktrees); } else if (opts->source.file) { @@ -1087,7 +1087,7 @@ static int show_editor(struct config_location_options *opts) git_config(git_default_config, NULL); config_file = opts->source.file ? xstrdup(opts->source.file) : - git_pathdup("config"); + repo_git_path(the_repository, "config"); if (opts->use_global_config) { int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666); if (fd >= 0) { diff --git a/builtin/diff-pairs.c b/builtin/diff-pairs.c new file mode 100644 index 0000000000..71c045331a --- /dev/null +++ b/builtin/diff-pairs.c @@ -0,0 +1,207 @@ +#include "builtin.h" +#include "config.h" +#include "diff.h" +#include "diffcore.h" +#include "gettext.h" +#include "hash.h" +#include "hex.h" +#include "object.h" +#include "parse-options.h" +#include "revision.h" +#include "strbuf.h" + +static unsigned parse_mode_or_die(const char *mode, const char **end) +{ + uint16_t ret; + + *end = parse_mode(mode, &ret); + if (!*end) + die(_("unable to parse mode: %s"), mode); + return ret; +} + +static void parse_oid_or_die(const char *hex, struct object_id *oid, + const char **end, const struct git_hash_algo *algop) +{ + if (parse_oid_hex_algop(hex, oid, end, algop) || *(*end)++ != ' ') + die(_("unable to parse object id: %s"), hex); +} + +int cmd_diff_pairs(int argc, const char **argv, const char *prefix, + struct repository *repo) +{ + struct strbuf path_dst = STRBUF_INIT; + struct strbuf path = STRBUF_INIT; + struct strbuf meta = STRBUF_INIT; + struct option *parseopts; + struct rev_info revs; + int line_term = '\0'; + int ret; + + const char * const builtin_diff_pairs_usage[] = { + N_("git diff-pairs -z [<diff-options>]"), + NULL + }; + struct option builtin_diff_pairs_options[] = { + OPT_END() + }; + + repo_init_revisions(repo, &revs, prefix); + + /* + * Diff options are usually parsed implicitly as part of + * setup_revisions(). Explicitly handle parsing to ensure options are + * printed in the usage message. + */ + parseopts = add_diff_options(builtin_diff_pairs_options, &revs.diffopt); + show_usage_with_options_if_asked(argc, argv, builtin_diff_pairs_usage, parseopts); + + repo_config(repo, git_diff_basic_config, NULL); + revs.diffopt.no_free = 1; + revs.disable_stdin = 1; + revs.abbrev = 0; + revs.diff = 1; + + argc = parse_options(argc, argv, prefix, parseopts, builtin_diff_pairs_usage, + PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_DASHDASH); + + if (setup_revisions(argc, argv, &revs, NULL) > 1) + usagef(_("unrecognized argument: %s"), argv[0]); + + /* + * With the -z option, both command input and raw output are + * NUL-delimited (this mode does not affect patch output). At present + * only NUL-delimited raw diff formatted input is supported. + */ + if (revs.diffopt.line_termination) + usage(_("working without -z is not supported")); + + if (revs.prune_data.nr) + usage(_("pathspec arguments not supported")); + + if (revs.pending.nr || revs.max_count != -1 || + revs.min_age != (timestamp_t)-1 || + revs.max_age != (timestamp_t)-1) + usage(_("revision arguments not allowed")); + + if (!revs.diffopt.output_format) + revs.diffopt.output_format = DIFF_FORMAT_PATCH; + + /* + * If rename detection is not requested, use rename information from the + * raw diff formatted input. Setting skip_resolving_statuses ensures + * diffcore_std() does not mess with rename information already present + * in queued filepairs. + */ + if (!revs.diffopt.detect_rename) + revs.diffopt.skip_resolving_statuses = 1; + + while (1) { + struct object_id oid_a, oid_b; + struct diff_filepair *pair; + unsigned mode_a, mode_b; + const char *p; + char status; + + if (strbuf_getwholeline(&meta, stdin, line_term) == EOF) + break; + + p = meta.buf; + if (!*p) { + diffcore_std(&revs.diffopt); + diff_flush(&revs.diffopt); + /* + * When the diff queue is explicitly flushed, append a + * NUL byte to separate batches of diffs. + */ + fputc('\0', revs.diffopt.file); + fflush(revs.diffopt.file); + continue; + } + + if (*p != ':') + die(_("invalid raw diff input")); + p++; + + mode_a = parse_mode_or_die(p, &p); + mode_b = parse_mode_or_die(p, &p); + + if (S_ISDIR(mode_a) || S_ISDIR(mode_b)) + die(_("tree objects not supported")); + + parse_oid_or_die(p, &oid_a, &p, repo->hash_algo); + parse_oid_or_die(p, &oid_b, &p, repo->hash_algo); + + status = *p++; + + if (strbuf_getwholeline(&path, stdin, line_term) == EOF) + die(_("got EOF while reading path")); + + switch (status) { + case DIFF_STATUS_ADDED: + pair = diff_queue_addremove(&diff_queued_diff, + &revs.diffopt, '+', mode_b, + &oid_b, 1, path.buf, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_DELETED: + pair = diff_queue_addremove(&diff_queued_diff, + &revs.diffopt, '-', mode_a, + &oid_a, 1, path.buf, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_TYPE_CHANGED: + case DIFF_STATUS_MODIFIED: + pair = diff_queue_change(&diff_queued_diff, &revs.diffopt, + mode_a, mode_b, &oid_a, &oid_b, + 1, 1, path.buf, 0, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_RENAMED: + case DIFF_STATUS_COPIED: { + struct diff_filespec *a, *b; + unsigned int score; + + if (strbuf_getwholeline(&path_dst, stdin, line_term) == EOF) + die(_("got EOF while reading destination path")); + + a = alloc_filespec(path.buf); + b = alloc_filespec(path_dst.buf); + fill_filespec(a, &oid_a, 1, mode_a); + fill_filespec(b, &oid_b, 1, mode_b); + + pair = diff_queue(&diff_queued_diff, a, b); + + if (strtoul_ui(p, 10, &score)) + die(_("unable to parse rename/copy score: %s"), p); + + pair->score = score * MAX_SCORE / 100; + pair->status = status; + pair->renamed_pair = 1; + } + break; + + default: + die(_("unknown diff status: %c"), status); + } + } + + revs.diffopt.no_free = 0; + diffcore_std(&revs.diffopt); + diff_flush(&revs.diffopt); + ret = diff_result_code(&revs); + + strbuf_release(&path_dst); + strbuf_release(&path); + strbuf_release(&meta); + release_revisions(&revs); + FREE_AND_NULL(parseopts); + + return ret; +} diff --git a/builtin/fast-import.c b/builtin/fast-import.c index a5b33eb91e..e432e8d5a1 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -328,7 +328,7 @@ static void write_branch_report(FILE *rpt, struct branch *b) static void write_crash_report(const char *err) { - char *loc = git_pathdup("fast_import_crash_%"PRIuMAX, (uintmax_t) getpid()); + char *loc = repo_git_path(the_repository, "fast_import_crash_%"PRIuMAX, (uintmax_t) getpid()); FILE *rpt = fopen(loc, "w"); struct branch *b; unsigned long lu; @@ -3303,7 +3303,7 @@ static char* make_fast_import_path(const char *path) { if (!relative_marks_paths || is_absolute_path(path)) return prefix_filename(global_prefix, path); - return git_pathdup("info/fast-import/%s", path); + return repo_git_path(the_repository, "info/fast-import/%s", path); } static void option_import_marks(const char *marks, diff --git a/builtin/fetch.c b/builtin/fetch.c index 1c740d5aac..95fd0018b9 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1777,7 +1777,9 @@ static int do_fetch(struct transport *transport, if (uses_remote_tracking(transport, rs)) { must_list_refs = 1; - strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD"); + if (transport_ls_refs_options.ref_prefixes.nr) + strvec_push(&transport_ls_refs_options.ref_prefixes, + "HEAD"); } if (must_list_refs) { diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 8085ebd8fe..3d2207ec77 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "commit.h" #include "config.h" @@ -20,7 +19,7 @@ static char const * const for_each_ref_usage[] = { int cmd_for_each_ref(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; @@ -63,7 +62,7 @@ int cmd_for_each_ref(int argc, format.format = "%(objectname) %(objecttype)\t%(refname)"; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); /* Set default (refname) sorting */ string_list_append(&sorting_options, "refname"); diff --git a/builtin/fsck.c b/builtin/fsck.c index 7a4dcb0716..8fbd1d6334 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -50,6 +50,7 @@ static int verbose; static int show_progress = -1; static int show_dangling = 1; static int name_objects; +static int check_references = 1; #define ERROR_OBJECT 01 #define ERROR_REACHABLE 02 #define ERROR_PACK 04 @@ -326,7 +327,7 @@ static void check_unreachable_object(struct object *obj) printable_type(&obj->oid, obj->type), describe_object(&obj->oid)); if (write_lost_and_found) { - char *filename = git_pathdup("lost-found/%s/%s", + char *filename = repo_git_path(the_repository, "lost-found/%s/%s", obj->type == OBJ_COMMIT ? "commit" : "other", describe_object(&obj->oid)); FILE *f; @@ -905,11 +906,37 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress) return res; } +static void fsck_refs(struct repository *r) +{ + struct child_process refs_verify = CHILD_PROCESS_INIT; + struct progress *progress = NULL; + + if (show_progress) + progress = start_progress(r, _("Checking ref database"), 1); + + if (verbose) + fprintf_ln(stderr, _("Checking ref database")); + + child_process_init(&refs_verify); + refs_verify.git_cmd = 1; + strvec_pushl(&refs_verify.args, "refs", "verify", NULL); + if (verbose) + strvec_push(&refs_verify.args, "--verbose"); + if (check_strict) + strvec_push(&refs_verify.args, "--strict"); + + if (run_command(&refs_verify)) + errors_found |= ERROR_REFS; + + display_progress(progress, 1); + stop_progress(&progress); +} + static char const * const fsck_usage[] = { N_("git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" - " [--[no-]name-objects] [<object>...]"), + " [--[no-]name-objects] [--[no-]references] [<object>...]"), NULL }; @@ -928,6 +955,7 @@ static struct option fsck_opts[] = { N_("write dangling objects in .git/lost-found")), OPT_BOOL(0, "progress", &show_progress, N_("show progress")), OPT_BOOL(0, "name-objects", &name_objects, N_("show verbose names for reachable objects")), + OPT_BOOL(0, "references", &check_references, N_("check reference database consistency")), OPT_END(), }; @@ -970,6 +998,9 @@ int cmd_fsck(int argc, git_config(git_fsck_config, &fsck_obj_options); prepare_repo_settings(the_repository); + if (check_references) + fsck_refs(the_repository); + if (connectivity_only) { for_each_loose_object(mark_loose_for_connectivity, NULL, 0); for_each_packed_object(the_repository, @@ -1057,7 +1088,7 @@ int cmd_fsck(int argc, struct worktree *wt = *p; struct index_state istate = INDEX_STATE_INIT(the_repository); - char *path; + char *path, *wt_gitdir; /* * Make a copy since the buffer is reusable @@ -1065,9 +1096,13 @@ int cmd_fsck(int argc, * while we're examining the index. */ path = xstrdup(worktree_git_path(the_repository, wt, "index")); - read_index_from(&istate, path, get_worktree_git_dir(wt)); + wt_gitdir = get_worktree_git_dir(wt); + + read_index_from(&istate, path, wt_gitdir); fsck_index(&istate, path, wt->is_current); + discard_index(&istate); + free(wt_gitdir); free(path); } free_worktrees(worktrees); diff --git a/builtin/gc.c b/builtin/gc.c index 409d454a4b..99431fd467 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -99,9 +99,11 @@ static void process_log_file(void) /* There was some error recorded in the lock file */ commit_lock_file(&log_lock); } else { + char *path = repo_git_path(the_repository, "gc.log"); /* No error, clean up any old gc.log */ - unlink(git_path("gc.log")); + unlink(path); rollback_lock_file(&log_lock); + free(path); } } @@ -300,8 +302,11 @@ static int too_many_loose_objects(struct gc_config *cfg) int num_loose = 0; int needed = 0; const unsigned hexsz_loose = the_hash_algo->hexsz - 2; + char *path; - dir = opendir(git_path("objects/17")); + path = repo_git_path(the_repository, "objects/17"); + dir = opendir(path); + free(path); if (!dir) return 0; @@ -550,7 +555,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) if (xgethostname(my_host, sizeof(my_host))) xsnprintf(my_host, sizeof(my_host), "unknown"); - pidfile_path = git_pathdup("gc.pid"); + pidfile_path = repo_git_path(the_repository, "gc.pid"); fd = hold_lock_file_for_update(&lock, pidfile_path, LOCK_DIE_ON_ERROR); if (!force) { @@ -611,7 +616,7 @@ static int report_last_gc_error(void) int ret = 0; ssize_t len; struct stat st; - char *gc_log_path = git_pathdup("gc.log"); + char *gc_log_path = repo_git_path(the_repository, "gc.log"); if (stat(gc_log_path, &st)) { if (errno == ENOENT) @@ -826,11 +831,12 @@ struct repository *repo UNUSED) } if (daemonized) { - hold_lock_file_for_update(&log_lock, - git_path("gc.log"), + char *path = repo_git_path(the_repository, "gc.log"); + hold_lock_file_for_update(&log_lock, path, LOCK_DIE_ON_ERROR); dup2(get_lock_file_fd(&log_lock), 2); atexit(process_log_file_at_exit); + free(path); } gc_before_repack(&opts, &cfg); @@ -892,8 +898,11 @@ struct repository *repo UNUSED) warning(_("There are too many unreachable loose objects; " "run 'git prune' to remove them.")); - if (!daemonized) - unlink(git_path("gc.log")); + if (!daemonized) { + char *path = repo_git_path(the_repository, "gc.log"); + unlink(path); + free(path); + } out: gc_config_release(&cfg); diff --git a/builtin/init-db.c b/builtin/init-db.c index 096f96b9c4..196dccdd77 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -132,8 +132,8 @@ int cmd_init_db(int argc, * and we know shared_repository should always be 0; * but just in case we play safe. */ - saved = get_shared_repository(); - set_shared_repository(0); + saved = repo_settings_get_shared_repository(the_repository); + repo_settings_set_shared_repository(the_repository, 0); switch (safe_create_leading_directories_const(argv[0])) { case SCLD_OK: case SCLD_PERMS: @@ -145,7 +145,7 @@ int cmd_init_db(int argc, die_errno(_("cannot mkdir %s"), argv[0]); break; } - set_shared_repository(saved); + repo_settings_set_shared_repository(the_repository, saved); if (mkdir(argv[0], 0777) < 0) die_errno(_("cannot mkdir %s"), argv[0]); mkdir_tried = 1; @@ -175,7 +175,7 @@ int cmd_init_db(int argc, } if (init_shared_repository != -1) - set_shared_repository(init_shared_repository); + repo_settings_set_shared_repository(the_repository, init_shared_repository); /* * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR diff --git a/builtin/log.c b/builtin/log.c index e41f88945e..04a6ef97bc 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -2309,8 +2309,8 @@ int cmd_format_patch(int argc, * We consider <outdir> as 'outside of gitdir', therefore avoid * applying adjust_shared_perm in s-c-l-d. */ - saved = get_shared_repository(); - set_shared_repository(0); + saved = repo_settings_get_shared_repository(the_repository); + repo_settings_set_shared_repository(the_repository, 0); switch (safe_create_leading_directories_const(output_directory)) { case SCLD_OK: case SCLD_EXISTS: @@ -2319,7 +2319,7 @@ int cmd_format_patch(int argc, die(_("could not create leading directories " "of '%s'"), output_directory); } - set_shared_repository(saved); + repo_settings_set_shared_repository(the_repository, saved); if (mkdir(output_directory, 0777) < 0 && errno != EEXIST) die_errno(_("could not create directory '%s'"), output_directory); diff --git a/builtin/ls-files.c b/builtin/ls-files.c index a4431429b7..70a377e9c0 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -6,7 +6,6 @@ * Copyright (C) Linus Torvalds, 2005 */ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" @@ -245,12 +244,13 @@ static void show_submodule(struct repository *superproject, repo_clear(&subrepo); } -static void expand_objectsize(struct strbuf *line, const struct object_id *oid, +static void expand_objectsize(struct repository *repo, struct strbuf *line, + const struct object_id *oid, const enum object_type type, unsigned int padded) { if (type == OBJ_BLOB) { unsigned long size; - if (oid_object_info(the_repository, oid, &size) < 0) + if (oid_object_info(repo, oid, &size) < 0) die(_("could not get object info about '%s'"), oid_to_hex(oid)); if (padded) @@ -283,10 +283,10 @@ static void show_ce_fmt(struct repository *repo, const struct cache_entry *ce, else if (skip_prefix(format, "(objecttype)", &format)) strbuf_addstr(&sb, type_name(object_type(ce->ce_mode))); else if (skip_prefix(format, "(objectsize:padded)", &format)) - expand_objectsize(&sb, &ce->oid, + expand_objectsize(repo, &sb, &ce->oid, object_type(ce->ce_mode), 1); else if (skip_prefix(format, "(objectsize)", &format)) - expand_objectsize(&sb, &ce->oid, + expand_objectsize(repo, &sb, &ce->oid, object_type(ce->ce_mode), 0); else if (skip_prefix(format, "(stage)", &format)) strbuf_addf(&sb, "%d", ce_stage(ce)); @@ -348,7 +348,7 @@ static void show_ce(struct repository *repo, struct dir_struct *dir, } } -static void show_ru_info(struct index_state *istate) +static void show_ru_info(struct repository *repo, struct index_state *istate) { struct string_list_item *item; @@ -370,7 +370,7 @@ static void show_ru_info(struct index_state *istate) if (!ui->mode[i]) continue; printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i], - repo_find_unique_abbrev(the_repository, &ui->oid[i], abbrev), + repo_find_unique_abbrev(repo, &ui->oid[i], abbrev), i + 1); write_name(path); } @@ -567,7 +567,7 @@ static int option_parse_exclude_standard(const struct option *opt, int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix, - struct repository *repo UNUSED) + struct repository *repo) { int require_work_tree = 0, show_tag = 0, i; char *max_prefix; @@ -647,15 +647,15 @@ int cmd_ls_files(int argc, show_usage_with_options_if_asked(argc, argv, ls_files_usage, builtin_ls_files_options); - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; prefix = cmd_prefix; if (prefix) prefix_len = strlen(prefix); - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); - if (repo_read_index(the_repository) < 0) + if (repo_read_index(repo) < 0) die("index file corrupt"); argc = parse_options(argc, argv, prefix, builtin_ls_files_options, @@ -724,7 +724,7 @@ int cmd_ls_files(int argc, max_prefix = common_prefix(&pathspec); max_prefix_len = get_common_prefix_len(max_prefix); - prune_index(the_repository->index, max_prefix, max_prefix_len); + prune_index(repo->index, max_prefix, max_prefix_len); /* Treat unmatching pathspec elements as errors */ if (pathspec.nr && error_unmatch) @@ -748,13 +748,13 @@ int cmd_ls_files(int argc, */ if (show_stage || show_unmerged) die(_("options '%s' and '%s' cannot be used together"), "ls-files --with-tree", "-s/-u"); - overlay_tree_on_index(the_repository->index, with_tree, max_prefix); + overlay_tree_on_index(repo->index, with_tree, max_prefix); } - show_files(the_repository, &dir); + show_files(repo, &dir); if (show_resolve_undo) - show_ru_info(the_repository->index); + show_ru_info(repo, repo->index); if (ps_matched && report_path_error(ps_matched, &pathspec)) { fprintf(stderr, "Did you forget to 'git add'?\n"); diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 9a6c8b4e4c..3ec7127b3a 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -18,6 +18,7 @@ #include "tree.h" #include "config.h" #include "strvec.h" +#include "write-or-die.h" static int line_termination = '\n'; @@ -575,7 +576,7 @@ int cmd_merge_tree(int argc, }; /* Init merge options */ - init_ui_merge_options(&o.merge_options, the_repository); + init_basic_merge_options(&o.merge_options, the_repository); /* Parse arguments */ original_argc = argc - 1; /* ignoring argv[0] */ @@ -600,7 +601,6 @@ int cmd_merge_tree(int argc, line_termination = '\0'; while (strbuf_getline_lf(&buf, stdin) != EOF) { struct strbuf **split; - int result; const char *input_merge_base = NULL; split = strbuf_split(&buf, ' '); @@ -617,15 +617,14 @@ int cmd_merge_tree(int argc, if (input_merge_base && split[2] && split[3] && !split[4]) { strbuf_rtrim(split[2]); strbuf_rtrim(split[3]); - result = real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix); + real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix); } else if (!input_merge_base && !split[2]) { - result = real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix); + real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix); } else { die(_("malformed input line: '%s'."), buf.buf); } + maybe_flush_or_die(stdout, "stdout"); - if (result < 0) - die(_("merging cannot continue; got unclean result of %d"), result); strbuf_list_free(split); } strbuf_release(&buf); diff --git a/builtin/notes.c b/builtin/notes.c index d051abf6df..ff61ec5f2d 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -197,7 +197,7 @@ static void prepare_note_data(const struct object_id *object, struct note_data * struct strbuf buf = STRBUF_INIT; /* write the template message before editing: */ - d->edit_path = git_pathdup("NOTES_EDITMSG"); + d->edit_path = repo_git_path(the_repository, "NOTES_EDITMSG"); fd = xopen(d->edit_path, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (d->msg_nr) @@ -979,6 +979,8 @@ static int merge(int argc, const char **argv, const char *prefix, else { /* Merge has unresolved conflicts */ struct worktree **worktrees; const struct worktree *wt; + char *path; + /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ refs_update_ref(get_main_ref_store(the_repository), msg.buf, "NOTES_MERGE_PARTIAL", &result_oid, NULL, @@ -994,10 +996,13 @@ static int merge(int argc, const char **argv, const char *prefix, if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", notes_ref, NULL)) die(_("failed to store link to current notes ref (%s)"), notes_ref); + + path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE); fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s " "and commit the result with 'git notes merge --commit', " "or abort the merge with 'git notes merge --abort'.\n"), - git_path(NOTES_MERGE_WORKTREE)); + path); + free(path); } free_notes(t); diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index 4fdd68880e..e47bae1c80 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "builtin.h" #include "config.h" #include "gettext.h" @@ -15,7 +13,7 @@ static char const * const pack_refs_usage[] = { int cmd_pack_refs(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; struct string_list included_refs = STRING_LIST_INIT_NODUP; @@ -39,7 +37,7 @@ int cmd_pack_refs(int argc, N_("references to exclude")), OPT_END(), }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0)) usage_with_options(pack_refs_usage, opts); @@ -52,7 +50,7 @@ int cmd_pack_refs(int argc, if (!pack_refs_opts.includes->nr) string_list_append(pack_refs_opts.includes, "refs/tags/*"); - ret = refs_pack_refs(get_main_ref_store(the_repository), &pack_refs_opts); + ret = refs_pack_refs(get_main_ref_store(repo), &pack_refs_opts); clear_ref_exclusions(&excludes); string_list_clear(&included_refs, 0); diff --git a/builtin/rebase.c b/builtin/rebase.c index 6c9eaf3788..d4715ed35d 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -644,7 +644,7 @@ static int run_am(struct rebase_options *opts) return run_command(&am); } - rebased_patches = xstrdup(git_path("rebased-patches")); + rebased_patches = repo_git_path(the_repository, "rebased-patches"); format_patch.out = open(rebased_patches, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (format_patch.out < 0) { diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 129305700c..7b28fc9df6 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1435,7 +1435,8 @@ static const char *push_to_checkout(unsigned char *hash, static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree) { - const char *retval, *git_dir; + const char *retval; + char *git_dir; struct strvec env = STRVEC_INIT; int invoked_hook; @@ -1453,6 +1454,7 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w retval = push_to_deploy(sha1, &env, worktree->path); strvec_clear(&env); + free(git_dir); return retval; } diff --git a/builtin/refs.c b/builtin/refs.c index a29f195834..998d2a2c1c 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -8,7 +8,7 @@ #include "worktree.h" #define REFS_MIGRATE_USAGE \ - N_("git refs migrate --ref-format=<format> [--dry-run]") + N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]") #define REFS_VERIFY_USAGE \ N_("git refs verify [--strict] [--verbose]") @@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix, OPT_BIT(0, "dry-run", &flags, N_("perform a non-destructive dry-run"), REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN), + OPT_BIT(0, "no-reflog", &flags, + N_("drop reflogs entirely during the migration"), + REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG), OPT_END(), }; struct strbuf errbuf = STRBUF_INIT; @@ -88,7 +91,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix, git_config(git_fsck_config, &fsck_refs_options); prepare_repo_settings(the_repository); - worktrees = get_worktrees(); + worktrees = get_worktrees_without_reading_head(); for (size_t i = 0; worktrees[i]; i++) ret |= refs_fsck(get_worktree_ref_store(worktrees[i]), &fsck_refs_options, worktrees[i]); diff --git a/builtin/remote.c b/builtin/remote.c index 816d482340..1b7aad8838 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -644,9 +644,11 @@ static int migrate_file(struct remote *remote) git_config_set_multivar(buf.buf, remote->fetch.items[i].raw, "^$", 0); #ifndef WITH_BREAKING_CHANGES if (remote->origin == REMOTE_REMOTES) - unlink_or_warn(git_path("remotes/%s", remote->name)); + unlink_or_warn(repo_git_path_replace(the_repository, &buf, + "remotes/%s", remote->name)); else if (remote->origin == REMOTE_BRANCHES) - unlink_or_warn(git_path("branches/%s", remote->name)); + unlink_or_warn(repo_git_path_replace(the_repository, &buf, + "branches/%s", remote->name)); #endif /* WITH_BREAKING_CHANGES */ strbuf_release(&buf); diff --git a/builtin/replace.c b/builtin/replace.c index a4eaadff91..15ec0922ce 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -345,7 +345,7 @@ static int edit_and_replace(const char *object_ref, int force, int raw) } strbuf_release(&ref); - tmpfile = git_pathdup("REPLACE_EDITOBJ"); + tmpfile = repo_git_path(the_repository, "REPLACE_EDITOBJ"); if (export_object(&old_oid, type, raw, tmpfile)) { free(tmpfile); return -1; diff --git a/builtin/rerere.c b/builtin/rerere.c index 41127e24e5..1312e79d89 100644 --- a/builtin/rerere.c +++ b/builtin/rerere.c @@ -4,9 +4,9 @@ #include "config.h" #include "gettext.h" #include "parse-options.h" - -#include "string-list.h" #include "rerere.h" +#include "strbuf.h" +#include "string-list.h" #include "xdiff/xdiff.h" #include "xdiff-interface.h" #include "pathspec.h" @@ -112,15 +112,18 @@ int cmd_rerere(int argc, merge_rr.items[i].util = NULL; } } else if (!strcmp(argv[0], "diff")) { + struct strbuf buf = STRBUF_INIT; if (setup_rerere(the_repository, &merge_rr, flags | RERERE_READONLY) < 0) return 0; for (size_t i = 0; i < merge_rr.nr; i++) { const char *path = merge_rr.items[i].string; const struct rerere_id *id = merge_rr.items[i].util; - if (diff_two(rerere_path(id, "preimage"), path, path, path)) - die(_("unable to generate diff for '%s'"), rerere_path(id, NULL)); + if (diff_two(rerere_path(&buf, id, "preimage"), path, path, path)) + die(_("unable to generate diff for '%s'"), rerere_path(&buf, id, NULL)); } + + strbuf_release(&buf); } else usage_with_options(rerere_usage, options); diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 428c866c05..490da33bec 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -789,8 +789,8 @@ int cmd_rev_parse(int argc, if (!strcmp(arg, "--git-path")) { if (!argv[i + 1]) die(_("--git-path requires an argument")); - strbuf_reset(&buf); - print_path(git_path("%s", argv[i + 1]), prefix, + print_path(repo_git_path_replace(the_repository, &buf, + "%s", argv[i + 1]), prefix, format, DEFAULT_RELATIVE_IF_SHARED); i++; @@ -1083,7 +1083,7 @@ int cmd_rev_parse(int argc, die(_("Could not read the index")); if (the_repository->index->split_index) { const struct object_id *oid = &the_repository->index->split_index->base_oid; - const char *path = git_path("sharedindex.%s", oid_to_hex(oid)); + const char *path = repo_git_path_replace(the_repository, &buf, "sharedindex.%s", oid_to_hex(oid)); print_path(path, prefix, format, DEFAULT_RELATIVE); } continue; diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 8d461008e2..c6e0e9d051 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "hex.h" @@ -151,7 +150,7 @@ static int send_pack_config(const char *k, const char *v, int cmd_send_pack(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct refspec rs = REFSPEC_INIT_PUSH; const char *remote_name = NULL; @@ -212,7 +211,7 @@ int cmd_send_pack(int argc, OPT_END() }; - git_config(send_pack_config, NULL); + repo_config(repo, send_pack_config, NULL); argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0); if (argc > 0) { dest = argv[0]; @@ -317,7 +316,7 @@ int cmd_send_pack(int argc, set_ref_status_for_push(remote_refs, args.send_mirror, args.force_update); - ret = send_pack(the_repository, &args, fd, conn, remote_refs, &extra_have); + ret = send_pack(repo, &args, fd, conn, remote_refs, &extra_have); if (helper_status) print_helper_status(remote_refs); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index f9b970f8a6..c1a8029714 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1301,7 +1301,7 @@ static void sync_submodule(const char *path, const char *prefix, remote_key = xstrfmt("remote.%s.url", default_remote); free(default_remote); - submodule_to_gitdir(&sb, path); + submodule_to_gitdir(the_repository, &sb, path); strbuf_addstr(&sb, "/config"); if (git_config_set_in_file_gently(sb.buf, remote_key, NULL, sub_origin_url)) @@ -1826,7 +1826,7 @@ static int clone_submodule(const struct module_clone_data *clone_data, connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0); - p = git_pathdup_submodule(clone_data_path, "config"); + p = repo_submodule_path(the_repository, clone_data_path, "config"); if (!p) die(_("could not get submodule directory for '%s'"), clone_data_path); diff --git a/builtin/tag.c b/builtin/tag.c index e8a344b926..d3e0943b73 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -667,7 +667,7 @@ int cmd_tag(int argc, if (create_tag_object) { if (force_sign_annotate && !annotate) opt.sign = 1; - path = git_pathdup("TAG_EDITMSG"); + path = repo_git_path(the_repository, "TAG_EDITMSG"); create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object, &trailer_args, path); } diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c index 779b7988ca..5f749a30da 100644 --- a/builtin/verify-commit.c +++ b/builtin/verify-commit.c @@ -5,7 +5,6 @@ * * Based on git-verify-tag */ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -33,15 +32,15 @@ static int run_gpg_verify(struct commit *commit, unsigned flags) return ret; } -static int verify_commit(const char *name, unsigned flags) +static int verify_commit(struct repository *repo, const char *name, unsigned flags) { struct object_id oid; struct object *obj; - if (repo_get_oid(the_repository, name, &oid)) + if (repo_get_oid(repo, name, &oid)) return error("commit '%s' not found.", name); - obj = parse_object(the_repository, &oid); + obj = parse_object(repo, &oid); if (!obj) return error("%s: unable to read file.", name); if (obj->type != OBJ_COMMIT) @@ -54,7 +53,7 @@ static int verify_commit(const char *name, unsigned flags) int cmd_verify_commit(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ -64,7 +63,7 @@ int cmd_verify_commit(int argc, OPT_END() }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); argc = parse_options(argc, argv, prefix, verify_commit_options, verify_commit_usage, PARSE_OPT_KEEP_ARGV0); @@ -78,7 +77,7 @@ int cmd_verify_commit(int argc, * was received in the process of writing the gpg input: */ signal(SIGPIPE, SIG_IGN); while (i < argc) - if (verify_commit(argv[i++], flags)) + if (verify_commit(repo, argv[i++], flags)) had_error = 1; return had_error; } diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index f6b97048a5..ed1c40338f 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -5,7 +5,6 @@ * * Based on git-verify-tag.sh */ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -23,7 +22,7 @@ static const char * const verify_tag_usage[] = { int cmd_verify_tag(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ -35,7 +34,7 @@ int cmd_verify_tag(int argc, OPT_END() }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); argc = parse_options(argc, argv, prefix, verify_tag_options, verify_tag_usage, PARSE_OPT_KEEP_ARGV0); @@ -56,7 +55,7 @@ int cmd_verify_tag(int argc, struct object_id oid; const char *name = argv[i++]; - if (repo_get_oid(the_repository, name, &oid)) { + if (repo_get_oid(repo, name, &oid)) { had_error = !!error("tag '%s' not found.", name); continue; } diff --git a/builtin/worktree.c b/builtin/worktree.c index c043d4d523..48448a8355 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -151,7 +151,7 @@ static int delete_git_dir(const char *id) struct strbuf sb = STRBUF_INIT; int ret; - strbuf_addstr(&sb, git_common_path("worktrees/%s", id)); + repo_common_path_append(the_repository, &sb, "worktrees/%s", id); ret = remove_dir_recursively(&sb, 0); if (ret < 0 && errno == ENOTDIR) ret = unlink(sb.buf); @@ -163,7 +163,9 @@ static int delete_git_dir(const char *id) static void delete_worktrees_dir_if_empty(void) { - rmdir(git_path("worktrees")); /* ignore failed removal */ + char *path = repo_git_path(the_repository, "worktrees"); + rmdir(path); /* ignore failed removal */ + free(path); } static void prune_worktree(const char *id, const char *reason) @@ -212,8 +214,13 @@ static void prune_worktrees(void) struct strbuf reason = STRBUF_INIT; struct strbuf main_path = STRBUF_INIT; struct string_list kept = STRING_LIST_INIT_DUP; - DIR *dir = opendir(git_path("worktrees")); + char *path; + DIR *dir; struct dirent *d; + + path = repo_git_path(the_repository, "worktrees"); + dir = opendir(path); + free(path); if (!dir) return; while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { @@ -337,7 +344,7 @@ static void check_candidate_path(const char *path, static void copy_sparse_checkout(const char *worktree_git_dir) { - char *from_file = git_pathdup("info/sparse-checkout"); + char *from_file = repo_git_path(the_repository, "info/sparse-checkout"); char *to_file = xstrfmt("%s/info/sparse-checkout", worktree_git_dir); if (file_exists(from_file)) { @@ -353,7 +360,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir) static void copy_filtered_worktree_config(const char *worktree_git_dir) { - char *from_file = git_pathdup("config.worktree"); + char *from_file = repo_git_path(the_repository, "config.worktree"); char *to_file = xstrfmt("%s/config.worktree", worktree_git_dir); if (file_exists(from_file)) { @@ -457,7 +464,7 @@ static int add_worktree(const char *path, const char *refname, BUG("How come '%s' becomes empty after sanitization?", sb.buf); strbuf_reset(&sb); name = sb_name.buf; - git_path_buf(&sb_repo, "worktrees/%s", name); + repo_git_path_replace(the_repository, &sb_repo, "worktrees/%s", name); len = sb_repo.len; if (safe_create_leading_directories_const(sb_repo.buf)) die_errno(_("could not create leading directories of '%s'"), @@ -657,8 +664,9 @@ static int can_use_local_refs(const struct add_opts *opts) if (!opts->quiet) { struct strbuf path = STRBUF_INIT; struct strbuf contents = STRBUF_INIT; + char *wt_gitdir = get_worktree_git_dir(NULL); - strbuf_add_real_path(&path, get_worktree_git_dir(NULL)); + strbuf_add_real_path(&path, wt_gitdir); strbuf_addstr(&path, "/HEAD"); strbuf_read_file(&contents, path.buf, 64); strbuf_stripspace(&contents, NULL); @@ -670,6 +678,7 @@ static int can_use_local_refs(const struct add_opts *opts) path.buf, contents.buf); strbuf_release(&path); strbuf_release(&contents); + free(wt_gitdir); } return 1; } @@ -1100,6 +1109,7 @@ static int lock_worktree(int ac, const char **av, const char *prefix, OPT_END() }; struct worktree **worktrees, *wt; + char *path; ac = parse_options(ac, av, prefix, options, git_worktree_lock_usage, 0); if (ac != 1) @@ -1120,9 +1130,11 @@ static int lock_worktree(int ac, const char **av, const char *prefix, die(_("'%s' is already locked"), av[0]); } - write_file(git_common_path("worktrees/%s/locked", wt->id), - "%s", reason); + path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id); + write_file(path, "%s", reason); + free_worktrees(worktrees); + free(path); return 0; } @@ -1133,6 +1145,7 @@ static int unlock_worktree(int ac, const char **av, const char *prefix, OPT_END() }; struct worktree **worktrees, *wt; + char *path; int ret; ac = parse_options(ac, av, prefix, options, git_worktree_unlock_usage, 0); @@ -1147,8 +1160,12 @@ static int unlock_worktree(int ac, const char **av, const char *prefix, die(_("The main working tree cannot be locked or unlocked")); if (!worktree_lock_reason(wt)) die(_("'%s' is not locked"), av[0]); - ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id)); + + path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id); + ret = unlink_or_warn(path); + free_worktrees(worktrees); + free(path); return ret; } @@ -1157,6 +1174,9 @@ static void validate_no_submodules(const struct worktree *wt) struct index_state istate = INDEX_STATE_INIT(the_repository); struct strbuf path = STRBUF_INIT; int i, found_submodules = 0; + char *wt_gitdir; + + wt_gitdir = get_worktree_git_dir(wt); if (is_directory(worktree_git_path(the_repository, wt, "modules"))) { /* @@ -1166,7 +1186,7 @@ static void validate_no_submodules(const struct worktree *wt) */ found_submodules = 1; } else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"), - get_worktree_git_dir(wt)) > 0) { + wt_gitdir) > 0) { for (i = 0; i < istate.cache_nr; i++) { struct cache_entry *ce = istate.cache[i]; int err; @@ -1185,6 +1205,7 @@ static void validate_no_submodules(const struct worktree *wt) } discard_index(&istate); strbuf_release(&path); + free(wt_gitdir); if (found_submodules) die(_("working trees containing submodules cannot be moved or removed")); diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh index 332ba96003..0df74610d0 100755 --- a/ci/install-dependencies.sh +++ b/ci/install-dependencies.sh @@ -58,7 +58,7 @@ ubuntu-*|i386/ubuntu-*|debian-*) make libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \ tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \ libemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \ - libpcre2-dev meson ninja-build pkg-config \ + libsecret-1-dev libpcre2-dev meson ninja-build pkg-config \ ${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE case "$distro" in @@ -348,8 +348,11 @@ case "$jobname" in linux32) CC=gcc ;; -linux-musl) - MESONFLAGS="$MESONFLAGS -DGIT_TEST_UTF8_LOCALE=C.UTF-8" +linux-meson) + MESONFLAGS="$MESONFLAGS -Dcredential_helpers=libsecret,netrc" + ;; +linux-musl-meson) + MESONFLAGS="$MESONFLAGS -Dtest_utf8_locale=C.UTF-8" ;; linux-leaks|linux-reftable-leaks) export SANITIZE=leak @@ -359,6 +362,9 @@ linux-asan-ubsan) export NO_SVN_TESTS=LetsSaveSomeTime MAKEFLAGS="$MAKEFLAGS NO_PYTHON=YepBecauseP4FlakesTooOften" ;; +osx-meson) + MESONFLAGS="$MESONFLAGS -Dcredential_helpers=osxkeychain" + ;; esac MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}" diff --git a/command-list.txt b/command-list.txt index c537114b46..b7ade3ab9f 100644 --- a/command-list.txt +++ b/command-list.txt @@ -96,6 +96,7 @@ git-diagnose ancillaryinterrogators git-diff mainporcelain info git-diff-files plumbinginterrogators git-diff-index plumbinginterrogators +git-diff-pairs plumbinginterrogators git-diff-tree plumbinginterrogators git-difftool ancillaryinterrogators complete git-fast-export ancillarymanipulators diff --git a/commit-graph.c b/commit-graph.c index 2a2999a6b8..1021ccb983 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -2084,7 +2084,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) return -1; } - if (adjust_shared_perm(get_tempfile_path(graph_layer))) { + if (adjust_shared_perm(the_repository, get_tempfile_path(graph_layer))) { error(_("unable to adjust shared permissions for '%s'"), get_tempfile_path(graph_layer)); return -1; @@ -780,14 +780,14 @@ static void clear_commit_marks_1(struct commit_list **plist, void clear_commit_marks_many(size_t nr, struct commit **commit, unsigned int mark) { - struct commit_list *list = NULL; - for (size_t i = 0; i < nr; i++) { + struct commit_list *list = NULL; + clear_commit_marks_1(&list, *commit, mark); + while (list) + clear_commit_marks_1(&list, pop_commit(&list), mark); commit++; } - while (list) - clear_commit_marks_1(&list, pop_commit(&list), mark); } void clear_commit_marks(struct commit *commit, unsigned int mark) diff --git a/compat/mingw.c b/compat/mingw.c index 1d5b211b54..f524c54d06 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2278,7 +2278,9 @@ repeat: old_handle = CreateFileW(wpold, DELETE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, + NULL); if (old_handle == INVALID_HANDLE_VALUE) { errno = err_win_to_posix(GetLastError()); return -1; diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c index f7cc7b3be5..12e38e0ea3 100644 --- a/compat/precompose_utf8.c +++ b/compat/precompose_utf8.c @@ -50,15 +50,15 @@ void probe_utf8_pathname_composition(void) int output_fd; if (precomposed_unicode != -1) return; /* We found it defined in the global config, respect it */ - git_path_buf(&path, "%s", auml_nfc); + repo_git_path_replace(the_repository, &path, "%s", auml_nfc); output_fd = open(path.buf, O_CREAT|O_EXCL|O_RDWR, 0600); if (output_fd >= 0) { close(output_fd); - git_path_buf(&path, "%s", auml_nfd); + repo_git_path_replace(the_repository, &path, "%s", auml_nfd); precomposed_unicode = access(path.buf, R_OK) ? 0 : 1; git_config_set("core.precomposeunicode", precomposed_unicode ? "true" : "false"); - git_path_buf(&path, "%s", auml_nfc); + repo_git_path_replace(the_repository, &path, "%s", auml_nfc); if (unlink(path.buf)) die_errno(_("failed to unlink '%s'"), path.buf); } @@ -1437,11 +1437,6 @@ static int git_default_core_config(const char *var, const char *value, return git_config_pathname(&git_attributes_file, var, value); } - if (!strcmp(var, "core.hookspath")) { - FREE_AND_NULL(git_hooks_path); - return git_config_pathname(&git_hooks_path, var, value); - } - if (!strcmp(var, "core.bare")) { is_bare_repository_cfg = git_config_bool(var, value); return 0; @@ -1652,7 +1647,7 @@ static int git_default_core_config(const char *var, const char *value, return 0; } - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return platform_core_config(var, value, ctx, cb); } @@ -1663,7 +1658,7 @@ static int git_default_sparse_config(const char *var, const char *value) return 0; } - /* Add other config variables here and to Documentation/config/sparse.txt. */ + /* Add other config variables here and to Documentation/config/sparse.adoc. */ return 0; } @@ -1679,7 +1674,7 @@ static int git_default_i18n_config(const char *var, const char *value) return git_config_string(&git_log_output_encoding, var, value); } - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -1715,7 +1710,7 @@ static int git_default_branch_config(const char *var, const char *value) return 0; } - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -1744,7 +1739,7 @@ static int git_default_push_config(const char *var, const char *value) return 0; } - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -1760,7 +1755,7 @@ static int git_default_mailmap_config(const char *var, const char *value) return git_config_string(&git_mailmap_blob, var, value); } - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -1773,7 +1768,7 @@ static int git_default_attr_config(const char *var, const char *value) /* * Add other attribute related config variables here and to - * Documentation/config/attr.txt. + * Documentation/config/attr.adoc. */ return 0; } @@ -1831,7 +1826,7 @@ int git_default_config(const char *var, const char *value, if (starts_with(var, "sparse.")) return git_default_sparse_config(var, value); - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -2526,6 +2521,10 @@ void repo_config_clear(struct repository *repo) void repo_config(struct repository *repo, config_fn_t fn, void *data) { + if (!repo) { + read_very_early_config(fn, data); + return; + } git_config_check_init(repo); configset_iter(repo->config, fn, data); } @@ -219,6 +219,15 @@ void read_very_early_config(config_fn_t cb, void *data); * repo-specific one; by overwriting, the higher-priority repo-specific * value is left at the end). * + * In cases where the repository variable is NULL, repo_config() will + * skip the per-repository config but retain system and global configs + * by calling read_very_early_config() which also ignores one-time + * overrides like "git -c var=val". This is to support handling "git foo -h" + * (which lets git.c:run_builtin() to pass NULL and have the cmd_foo() + * call repo_config() before calling parse_options() to notice "-h", give + * help and exit) for a command that ordinarily require a repository + * so this limitation may be OK (but if needed you are welcome to fix it). + * * Unlike git_config_from_file(), this function respects includes. */ void repo_config(struct repository *r, config_fn_t fn, void *); @@ -22,6 +22,7 @@ #include "protocol.h" #include "alias.h" #include "bundle-uri.h" +#include "promisor-remote.h" static char *server_capabilities_v1; static struct strvec server_capabilities_v2 = STRVEC_INIT; @@ -487,6 +488,7 @@ void check_stateless_delimiter(int stateless_rpc, static void send_capabilities(int fd_out, struct packet_reader *reader) { const char *hash_name; + const char *promisor_remote_info; if (server_supports_v2("agent")) packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized()); @@ -500,6 +502,13 @@ static void send_capabilities(int fd_out, struct packet_reader *reader) } else { reader->hash_algo = &hash_algos[GIT_HASH_SHA1]; } + if (server_feature_v2("promisor-remote", &promisor_remote_info)) { + char *reply = promisor_remote_reply(promisor_remote_info); + if (reply) { + packet_write_fmt(fd_out, "promisor-remote=%s", reply); + free(reply); + } + } } int get_remote_bundle_uri(int fd_out, struct packet_reader *reader, @@ -624,7 +633,7 @@ const char *parse_feature_value(const char *feature_list, const char *feature, s *offset = found + len - orig_start; return value; } - /* feature with a value (e.g., "agent=git/1.2.3") */ + /* feature with a value (e.g., "agent=git/1.2.3-Linux") */ else if (*value == '=') { size_t end; diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 3179e7ff7a..25b495fa73 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -1001,10 +1001,14 @@ parse_makefile_for_sources(unit-test_SOURCES ${CMAKE_SOURCE_DIR}/Makefile "UNIT_ list(TRANSFORM unit-test_SOURCES REPLACE "\\$\\(UNIT_TEST_DIR\\)/" "${CMAKE_SOURCE_DIR}/t/unit-tests/") add_library(unit-test-lib STATIC ${unit-test_SOURCES}) +parse_makefile_for_sources(clar-test_SOURCES ${CMAKE_SOURCE_DIR}/Makefile "CLAR_TEST_OBJS") +list(TRANSFORM clar-test_SOURCES REPLACE "\\$\\(UNIT_TEST_DIR\\)/" "${CMAKE_SOURCE_DIR}/t/unit-tests/") +add_library(clar-test-lib STATIC ${clar-test_SOURCES}) + parse_makefile_for_scripts(unit_test_PROGRAMS "UNIT_TEST_PROGRAMS" "") foreach(unit_test ${unit_test_PROGRAMS}) add_executable("${unit_test}" "${CMAKE_SOURCE_DIR}/t/unit-tests/${unit_test}.c") - target_link_libraries("${unit_test}" unit-test-lib common-main) + target_link_libraries("${unit_test}" unit-test-lib clar-test-lib common-main) set_target_properties("${unit_test}" PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/unit-tests/bin) if(MSVC) @@ -1046,13 +1050,13 @@ add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/t/unit-tests/clar.suite" VERBATIM) add_library(unit-tests-lib ${clar_test_SUITES} - "${CMAKE_SOURCE_DIR}/t/unit-tests/clar/clar.c" "${CMAKE_BINARY_DIR}/t/unit-tests/clar-decls.h" "${CMAKE_BINARY_DIR}/t/unit-tests/clar.suite" ) +target_include_directories(clar-test-lib PUBLIC "${CMAKE_BINARY_DIR}/t/unit-tests") target_include_directories(unit-tests-lib PUBLIC "${CMAKE_BINARY_DIR}/t/unit-tests") -add_executable(unit-tests "${CMAKE_SOURCE_DIR}/t/unit-tests/unit-test.c") -target_link_libraries(unit-tests unit-tests-lib common-main) +add_executable(unit-tests) +target_link_libraries(unit-tests unit-tests-lib clar-test-lib common-main) set_target_properties(unit-tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/unit-tests/bin) if(MSVC) @@ -1169,14 +1173,13 @@ string(REPLACE "@GIT_PERF_MAKE_COMMAND@" "" git_build_options "${git_build_optio string(REPLACE "@GIT_PERF_MAKE_OPTS@" "" git_build_options "${git_build_options}") string(REPLACE "@GIT_PERF_REPEAT_COUNT@" "" git_build_options "${git_build_options}") string(REPLACE "@GIT_PERF_REPO@" "" git_build_options "${git_build_options}") +string(REPLACE "@GIT_SOURCE_DIR@" "${CMAKE_SOURCE_DIR}" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_CMP@" "" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_CMP_USE_COPIED_CONTEXT@" "" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_GITPERLLIB@" "'${CMAKE_BINARY_DIR}/perl/build/lib'" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_INDEX_VERSION@" "" git_build_options "${git_build_options}") -string(REPLACE "@GIT_TEST_MERGE_TOOLS_DIR@" "'${CMAKE_BINARY_DIR}/mergetools'" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_OPTS@" "" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_PERL_FATAL_WARNINGS@" "" git_build_options "${git_build_options}") -string(REPLACE "@GIT_TEST_POPATH@" "'${CMAKE_BINARY_DIR}/po'" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_TEMPLATE_DIR@" "'${CMAKE_BINARY_DIR}/templates/blt'" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_TEXTDOMAINDIR@" "'${CMAKE_BINARY_DIR}/po/build/locale'" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_UTF8_LOCALE@" "" git_build_options "${git_build_options}") diff --git a/contrib/coccinelle/meson.build b/contrib/coccinelle/meson.build new file mode 100644 index 0000000000..5d76a7fee6 --- /dev/null +++ b/contrib/coccinelle/meson.build @@ -0,0 +1,89 @@ +spatch = find_program('spatch', required: get_option('coccinelle')) +if not spatch.found() + subdir_done() +endif + +third_party_sources = [ + ':!contrib', + ':!compat/inet_ntop.c', + ':!compat/inet_pton.c', + ':!compat/nedmalloc', + ':!compat/obstack.*', + ':!compat/poll', + ':!compat/regex', + ':!sha1collisiondetection', + ':!sha1dc', + ':!t/unit-tests/clar', + ':!t/unit-tests/clar', + ':!t/t[0-9][0-9][0-9][0-9]*', +] + +rules = [ + 'array.cocci', + 'commit.cocci', + 'config_fn_ctx.pending.cocci', + 'equals-null.cocci', + 'flex_alloc.cocci', + 'free.cocci', + 'git_config_number.cocci', + 'hashmap.cocci', + 'index-compatibility.cocci', + 'object_id.cocci', + 'preincr.cocci', + 'qsort.cocci', + 'refs.cocci', + 'strbuf.cocci', + 'swap.cocci', + 'the_repository.cocci', + 'xcalloc.cocci', + 'xopen.cocci', + 'xstrdup_or_null.cocci', + 'xstrncmpz.cocci', +] + +concatenated_rules = custom_target( + command: [ + 'cat', '@INPUT@', + ], + input: rules, + output: 'rules.cocci', + capture: true, +) + +sources = [ ] +foreach source : run_command(git, '-C', meson.project_source_root(), 'ls-files', '--deduplicate', '*.c', third_party_sources, check: true).stdout().split() + sources += source +endforeach + +headers = [ ] +foreach header : run_command(git, '-C', meson.project_source_root(), 'ls-files', '--deduplicate', '*.h', third_party_sources, check: true).stdout().split() + headers += meson.project_source_root() / header +endforeach + +patches = [ ] +foreach source : sources + patches += custom_target( + command: [ + spatch, + '--all-includes', + '--sp-file', concatenated_rules, + '--patch', meson.project_source_root(), + '@INPUT@', + ], + input: meson.project_source_root() / source, + output: source.underscorify() + '.patch', + capture: true, + depend_files: headers, + ) +endforeach + +concatenated_patch = custom_target( + command: [ + 'cat', '@INPUT@', + ], + input: patches, + output: 'cocci.patch', + capture: true, +) + +alias_target('coccicheck', concatenated_patch) diff --git a/contrib/contacts/Makefile b/contrib/contacts/Makefile index a2990f0dcb..9c4ca4f3bc 100644 --- a/contrib/contacts/Makefile +++ b/contrib/contacts/Makefile @@ -34,7 +34,7 @@ GIT_CONTACTS := git-contacts GIT_CONTACTS_DOC := git-contacts.1 GIT_CONTACTS_XML := git-contacts.xml -GIT_CONTACTS_TXT := git-contacts.txt +GIT_CONTACTS_TXT := git-contacts.adoc GIT_CONTACTS_HTML := git-contacts.html doc: $(GIT_CONTACTS_DOC) $(GIT_CONTACTS_HTML) diff --git a/contrib/contacts/git-contacts.txt b/contrib/contacts/git-contacts.adoc index dd914d1261..dd914d1261 100644 --- a/contrib/contacts/git-contacts.txt +++ b/contrib/contacts/git-contacts.adoc diff --git a/contrib/contacts/meson.build b/contrib/contacts/meson.build new file mode 100644 index 0000000000..73d82dfe52 --- /dev/null +++ b/contrib/contacts/meson.build @@ -0,0 +1,55 @@ +custom_target( + input: 'git-contacts', + output: 'git-contacts', + command: generate_perl_command, + depends: [git_version_file], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +if get_option('docs').contains('man') + contacts_xml = custom_target( + command: asciidoc_common_options + [ + '--backend=' + asciidoc_docbook, + '--doctype=manpage', + '--out-file=@OUTPUT@', + '@INPUT@', + ], + depends: documentation_deps, + input: 'git-contacts.adoc', + output: 'git-contacts.xml', + ) + + custom_target( + command: [ + xmlto, + '-m', '@INPUT@', + 'man', + contacts_xml, + '-o', + meson.current_build_dir(), + ] + xmlto_extra, + input: [ + '../../Documentation/manpage-normal.xsl', + ], + output: 'git-contacts.1', + install: true, + install_dir: get_option('mandir') / 'man1', + ) +endif + +if get_option('docs').contains('html') + custom_target( + command: asciidoc_common_options + [ + '--backend=' + asciidoc_html, + '--doctype=manpage', + '--out-file=@OUTPUT@', + '@INPUT@', + ], + depends: documentation_deps, + input: 'git-contacts.adoc', + output: 'git-contacts.html', + install: true, + install_dir: get_option('datadir') / 'doc/git-doc', + ) +endif diff --git a/contrib/credential/libsecret/Makefile b/contrib/credential/libsecret/Makefile index 3e67552cc5..97ce9c92fb 100644 --- a/contrib/credential/libsecret/Makefile +++ b/contrib/credential/libsecret/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +all:: + MAIN:=git-credential-libsecret all:: $(MAIN) diff --git a/contrib/credential/libsecret/git-credential-libsecret.c b/contrib/credential/libsecret/git-credential-libsecret.c index 90034d0cf1..941b2afd5e 100644 --- a/contrib/credential/libsecret/git-credential-libsecret.c +++ b/contrib/credential/libsecret/git-credential-libsecret.c @@ -59,10 +59,10 @@ static void credential_clear(struct credential *c); /* ----------------- Secret Service functions ----------------- */ static const SecretSchema schema = { - "org.git.Password", + .name = "org.git.Password", /* Ignore schema name during search for backwards compatibility */ - SECRET_SCHEMA_DONT_MATCH_NAME, - { + .flags = SECRET_SCHEMA_DONT_MATCH_NAME, + .attributes = { /* * libsecret assumes attribute values are non-confidential and * unchanging, so we can't include oauth_refresh_token or @@ -168,7 +168,7 @@ static int keyring_get(struct credential *c) g_free(c->password); c->password = g_strdup(""); } - for (int i = 1; i < g_strv_length(parts); i++) { + for (guint i = 1; i < g_strv_length(parts); i++) { if (g_str_has_prefix(parts[i], "password_expiry_utc=")) { g_free(c->password_expiry_utc); c->password_expiry_utc = g_strdup(&parts[i][20]); @@ -424,7 +424,7 @@ int main(int argc, char *argv[]) struct credential_operation const *try_op = credential_helper_ops; struct credential cred = CREDENTIAL_INIT; - if (!argv[1]) { + if (argc < 2 || !*argv[1]) { usage(argv[0]); exit(EXIT_FAILURE); } diff --git a/contrib/credential/libsecret/meson.build b/contrib/credential/libsecret/meson.build new file mode 100644 index 0000000000..0137660fe0 --- /dev/null +++ b/contrib/credential/libsecret/meson.build @@ -0,0 +1,9 @@ +executable('git-credential-libsecret', + sources: 'git-credential-libsecret.c', + dependencies: [ + dependency('glib-2.0'), + dependency('libsecret-1'), + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) diff --git a/contrib/credential/meson.build b/contrib/credential/meson.build new file mode 100644 index 0000000000..4216296ae0 --- /dev/null +++ b/contrib/credential/meson.build @@ -0,0 +1,3 @@ +foreach helper : get_option('credential_helpers') + subdir(helper) +endforeach diff --git a/contrib/credential/netrc/meson.build b/contrib/credential/netrc/meson.build new file mode 100644 index 0000000000..a990dbb86d --- /dev/null +++ b/contrib/credential/netrc/meson.build @@ -0,0 +1,20 @@ +credential_netrc = custom_target( + input: 'git-credential-netrc.perl', + output: 'git-credential-netrc', + command: generate_perl_command, + depends: [git_version_file], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +credential_netrc_testenv = test_environment +credential_netrc_testenv.set('CREDENTIAL_NETRC_PATH', credential_netrc.full_path()) + +test('t-git-credential-netrc', + shell, + args: [ meson.current_source_dir() / 't-git-credential-netrc.sh' ], + workdir: meson.current_source_dir(), + env: credential_netrc_testenv, + depends: test_dependencies + bin_wrappers + [credential_netrc], + timeout: 0, +) diff --git a/contrib/credential/netrc/t-git-credential-netrc.sh b/contrib/credential/netrc/t-git-credential-netrc.sh index bf2777308a..1b7b8b3a9a 100755 --- a/contrib/credential/netrc/t-git-credential-netrc.sh +++ b/contrib/credential/netrc/t-git-credential-netrc.sh @@ -15,7 +15,7 @@ export PERL5LIB="$GITPERLLIB" test_expect_success 'git-credential-netrc' ' - perl "$GIT_BUILD_DIR"/contrib/credential/netrc/test.pl + perl "$GIT_SOURCE_DIR"/contrib/credential/netrc/test.pl ' test_done diff --git a/contrib/credential/netrc/test.pl b/contrib/credential/netrc/test.pl index c0fb3718b2..67a0ede564 100755 --- a/contrib/credential/netrc/test.pl +++ b/contrib/credential/netrc/test.pl @@ -15,10 +15,11 @@ BEGIN { my @global_credential_args = @ARGV; my $scriptDir = dirname rel2abs $0; -my ($netrc, $netrcGpg, $gcNetrc) = map { catfile $scriptDir, $_; } +my ($netrc, $netrcGpg) = map { catfile $scriptDir, $_; } qw(test.netrc - test.netrc.gpg - git-credential-netrc); + test.netrc.gpg); +my $gcNetrc = $ENV{CREDENTIAL_NETRC_PATH} || catfile $scriptDir, qw(git-credential-netrc); + local $ENV{PATH} = join ':' , $scriptDir , $ENV{PATH} diff --git a/contrib/credential/osxkeychain/Makefile b/contrib/credential/osxkeychain/Makefile index 238f5f8c36..0948297e20 100644 --- a/contrib/credential/osxkeychain/Makefile +++ b/contrib/credential/osxkeychain/Makefile @@ -1,3 +1,4 @@ +# The default target of this Makefile is... all:: git-credential-osxkeychain CC = gcc diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c index 1c8310d7fe..611c9798b3 100644 --- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c +++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c @@ -422,7 +422,7 @@ int main(int argc, const char **argv) const char *usage = "usage: git credential-osxkeychain <get|store|erase>"; - if (!argv[1]) + if (argc < 2 || !*argv[1]) die("%s", usage); if (open(argv[0], O_RDONLY | O_EXLOCK) == -1) diff --git a/contrib/credential/osxkeychain/meson.build b/contrib/credential/osxkeychain/meson.build new file mode 100644 index 0000000000..3c7677f736 --- /dev/null +++ b/contrib/credential/osxkeychain/meson.build @@ -0,0 +1,9 @@ +executable('git-credential-osxkeychain', + sources: 'git-credential-osxkeychain.c', + dependencies: [ + dependency('CoreFoundation'), + dependency('Security'), + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) diff --git a/contrib/credential/wincred/Makefile b/contrib/credential/wincred/Makefile index 6e992c0866..5b795fc9fe 100644 --- a/contrib/credential/wincred/Makefile +++ b/contrib/credential/wincred/Makefile @@ -1,4 +1,5 @@ -all: git-credential-wincred.exe +# The default target of this Makefile is... +all:: git-credential-wincred.exe -include ../../../config.mak.autogen -include ../../../config.mak diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c index 4be0d58cd8..04145b5118 100644 --- a/contrib/credential/wincred/git-credential-wincred.c +++ b/contrib/credential/wincred/git-credential-wincred.c @@ -12,7 +12,9 @@ #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) +#ifndef _MSC_VER __attribute__((format (printf, 1, 2))) +#endif static void die(const char *err, ...) { char msg[4096]; diff --git a/contrib/credential/wincred/meson.build b/contrib/credential/wincred/meson.build new file mode 100644 index 0000000000..6de23ca17d --- /dev/null +++ b/contrib/credential/wincred/meson.build @@ -0,0 +1,5 @@ +executable('git-credential-wincred', + sources: 'git-credential-wincred.c', + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) diff --git a/contrib/diff-highlight/Makefile b/contrib/diff-highlight/Makefile index f2be7cc924..33c2ccc9f7 100644 --- a/contrib/diff-highlight/Makefile +++ b/contrib/diff-highlight/Makefile @@ -1,4 +1,5 @@ -all: diff-highlight +# The default target of this Makefile is... +all:: diff-highlight PERL_PATH = /usr/bin/perl -include ../../config.mak diff --git a/contrib/diff-highlight/t/Makefile b/contrib/diff-highlight/t/Makefile index 5ff5275496..2a98541477 100644 --- a/contrib/diff-highlight/t/Makefile +++ b/contrib/diff-highlight/t/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +all:: + -include ../../../config.mak.autogen -include ../../../config.mak @@ -6,7 +9,7 @@ SHELL_PATH ?= $(SHELL) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh) -all: test +all:: test test: $(T) .PHONY: help clean all test $(T) diff --git a/contrib/long-running-filter/example.pl b/contrib/long-running-filter/example.pl index a677569ddd..4b83e4c5e8 100755 --- a/contrib/long-running-filter/example.pl +++ b/contrib/long-running-filter/example.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # # Example implementation for the Git filter protocol version 2 -# See Documentation/gitattributes.txt, section "Filter Protocol" +# See Documentation/gitattributes.adoc, section "Filter Protocol" # # Please note, this pass-thru filter is a minimal skeleton. No proper # error handling was implemented. diff --git a/contrib/meson.build b/contrib/meson.build index d74b64a518..a88c5dfe09 100644 --- a/contrib/meson.build +++ b/contrib/meson.build @@ -1,3 +1,6 @@ foreach feature : get_option('contrib') subdir(feature) endforeach + +subdir('coccinelle') +subdir('credential') diff --git a/contrib/mw-to-git/Makefile b/contrib/mw-to-git/Makefile index 4e603512a3..497ac434d6 100644 --- a/contrib/mw-to-git/Makefile +++ b/contrib/mw-to-git/Makefile @@ -12,6 +12,9 @@ # # make install +# The default target of this Makefile is... +all:: + GIT_MEDIAWIKI_PM=Git/Mediawiki.pm SCRIPT_PERL=git-remote-mediawiki.perl SCRIPT_PERL+=git-mw.perl @@ -27,7 +30,7 @@ INSTLIBDIR=$(shell $(MAKE) -C $(GIT_ROOT_DIR)/ \ DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) INSTLIBDIR_SQ = $(subst ','\'',$(INSTLIBDIR)) -all: build +all:: build test: all $(MAKE) -C t diff --git a/contrib/mw-to-git/t/Makefile b/contrib/mw-to-git/t/Makefile index f422203fa0..6c9f377caa 100644 --- a/contrib/mw-to-git/t/Makefile +++ b/contrib/mw-to-git/t/Makefile @@ -8,7 +8,8 @@ # ## Test git-remote-mediawiki -all: test +# The default target of this Makefile is... +all:: test -include ../../../config.mak.autogen -include ../../../config.mak diff --git a/contrib/persistent-https/Makefile b/contrib/persistent-https/Makefile index 52b84ba3d4..691737e76b 100644 --- a/contrib/persistent-https/Makefile +++ b/contrib/persistent-https/Makefile @@ -12,10 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# The default target of this Makefile is... +all:: + BUILD_LABEL=$(shell cut -d" " -f3 ../../GIT-VERSION-FILE) TAR_OUT=$(shell go env GOOS)_$(shell go env GOARCH).tar.gz -all: git-remote-persistent-https git-remote-persistent-https--proxy \ +all:: git-remote-persistent-https git-remote-persistent-https--proxy \ git-remote-persistent-http git-remote-persistent-https--proxy: git-remote-persistent-https diff --git a/contrib/subtree/Makefile b/contrib/subtree/Makefile index 8fe0bfd401..c0c9f21cb7 100644 --- a/contrib/subtree/Makefile +++ b/contrib/subtree/Makefile @@ -50,7 +50,7 @@ GIT_SUBTREE := git-subtree GIT_SUBTREE_DOC := git-subtree.1 GIT_SUBTREE_XML := git-subtree.xml -GIT_SUBTREE_TXT := git-subtree.txt +GIT_SUBTREE_TXT := git-subtree.adoc GIT_SUBTREE_HTML := git-subtree.html GIT_SUBTREE_TEST := ../../git-subtree diff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.adoc index 004abf415b..004abf415b 100644 --- a/contrib/subtree/git-subtree.txt +++ b/contrib/subtree/git-subtree.adoc diff --git a/contrib/subtree/meson.build b/contrib/subtree/meson.build index a752a188df..9c72b23625 100644 --- a/contrib/subtree/meson.build +++ b/contrib/subtree/meson.build @@ -32,7 +32,7 @@ if get_option('docs').contains('man') '@INPUT@', ], depends: documentation_deps, - input: 'git-subtree.txt', + input: 'git-subtree.adoc', output: 'git-subtree.xml', ) @@ -63,7 +63,7 @@ if get_option('docs').contains('html') '@INPUT@', ], depends: documentation_deps, - input: 'git-subtree.txt', + input: 'git-subtree.adoc', output: 'git-subtree.html', install: true, install_dir: get_option('datadir') / 'doc/git-doc', diff --git a/contrib/subtree/t/Makefile b/contrib/subtree/t/Makefile index 093399c788..2a85f5ee84 100644 --- a/contrib/subtree/t/Makefile +++ b/contrib/subtree/t/Makefile @@ -3,6 +3,9 @@ # Copyright (c) 2005 Junio C Hamano # +# The default target of this Makefile is... +all:: + -include ../../../config.mak.autogen -include ../../../config.mak @@ -31,7 +34,7 @@ TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh)) TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh)) THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh))) -all: $(DEFAULT_TEST_TARGET) +all:: $(DEFAULT_TEST_TARGET) test: pre-clean $(TEST_LINT) $(MAKE) aggregate-results-and-cleanup @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "copy.h" #include "path.h" @@ -57,7 +59,7 @@ int copy_file(const char *dst, const char *src, int mode) if (close(fdo) != 0) return error_errno("%s: close error", dst); - if (!status && adjust_shared_perm(dst)) + if (!status && adjust_shared_perm(the_repository, dst)) return -1; return status; @@ -5493,6 +5493,8 @@ static int diff_opt_pickaxe_regex(const struct option *opt, BUG_ON_OPT_NEG(unset); options->pickaxe = arg; options->pickaxe_opts |= DIFF_PICKAXE_KIND_G; + if (arg && !*arg) + return error(_("-G requires a non-empty argument")); return 0; } @@ -5504,6 +5506,8 @@ static int diff_opt_pickaxe_string(const struct option *opt, BUG_ON_OPT_NEG(unset); options->pickaxe = arg; options->pickaxe_opts |= DIFF_PICKAXE_KIND_S; + if (arg && !*arg) + return error(_("-S requires a non-empty argument")); return 0; } @@ -7081,7 +7085,7 @@ void diffcore_std(struct diff_options *options) diffcore_order(options->orderfile); if (options->rotate_to) diffcore_rotate(options); - if (!options->found_follow) + if (!options->found_follow && !options->skip_resolving_statuses) /* See try_to_follow_renames() in tree-diff.c */ diff_resolve_rename_copy(); diffcore_apply_filter(options); @@ -7157,16 +7161,19 @@ void compute_diffstat(struct diff_options *options, options->found_changes = !!diffstat->nr; } -void diff_addremove(struct diff_options *options, - int addremove, unsigned mode, - const struct object_id *oid, - int oid_valid, - const char *concatpath, unsigned dirty_submodule) +struct diff_filepair *diff_queue_addremove(struct diff_queue_struct *queue, + struct diff_options *options, + int addremove, unsigned mode, + const struct object_id *oid, + int oid_valid, + const char *concatpath, + unsigned dirty_submodule) { struct diff_filespec *one, *two; + struct diff_filepair *pair; if (S_ISGITLINK(mode) && is_submodule_ignored(concatpath, options)) - return; + return NULL; /* This may look odd, but it is a preparation for * feeding "there are unchanged files which should @@ -7186,7 +7193,7 @@ void diff_addremove(struct diff_options *options, if (options->prefix && strncmp(concatpath, options->prefix, options->prefix_length)) - return; + return NULL; one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); @@ -7198,25 +7205,29 @@ void diff_addremove(struct diff_options *options, two->dirty_submodule = dirty_submodule; } - diff_queue(&diff_queued_diff, one, two); + pair = diff_queue(queue, one, two); if (!options->flags.diff_from_contents) options->flags.has_changes = 1; + + return pair; } -void diff_change(struct diff_options *options, - unsigned old_mode, unsigned new_mode, - const struct object_id *old_oid, - const struct object_id *new_oid, - int old_oid_valid, int new_oid_valid, - const char *concatpath, - unsigned old_dirty_submodule, unsigned new_dirty_submodule) +struct diff_filepair *diff_queue_change(struct diff_queue_struct *queue, + struct diff_options *options, + unsigned old_mode, unsigned new_mode, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, int new_oid_valid, + const char *concatpath, + unsigned old_dirty_submodule, + unsigned new_dirty_submodule) { struct diff_filespec *one, *two; struct diff_filepair *p; if (S_ISGITLINK(old_mode) && S_ISGITLINK(new_mode) && is_submodule_ignored(concatpath, options)) - return; + return NULL; if (options->flags.reverse_diff) { SWAP(old_mode, new_mode); @@ -7227,7 +7238,7 @@ void diff_change(struct diff_options *options, if (options->prefix && strncmp(concatpath, options->prefix, options->prefix_length)) - return; + return NULL; one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); @@ -7235,19 +7246,42 @@ void diff_change(struct diff_options *options, fill_filespec(two, new_oid, new_oid_valid, new_mode); one->dirty_submodule = old_dirty_submodule; two->dirty_submodule = new_dirty_submodule; - p = diff_queue(&diff_queued_diff, one, two); + p = diff_queue(queue, one, two); if (options->flags.diff_from_contents) - return; + return p; if (options->flags.quick && options->skip_stat_unmatch && !diff_filespec_check_stat_unmatch(options->repo, p)) { diff_free_filespec_data(p->one); diff_free_filespec_data(p->two); - return; + return p; } options->flags.has_changes = 1; + + return p; +} + +void diff_addremove(struct diff_options *options, int addremove, unsigned mode, + const struct object_id *oid, int oid_valid, + const char *concatpath, unsigned dirty_submodule) +{ + diff_queue_addremove(&diff_queued_diff, options, addremove, mode, oid, + oid_valid, concatpath, dirty_submodule); +} + +void diff_change(struct diff_options *options, + unsigned old_mode, unsigned new_mode, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, int new_oid_valid, + const char *concatpath, + unsigned old_dirty_submodule, unsigned new_dirty_submodule) +{ + diff_queue_change(&diff_queued_diff, options, old_mode, new_mode, + old_oid, new_oid, old_oid_valid, new_oid_valid, + concatpath, old_dirty_submodule, new_dirty_submodule); } struct diff_filepair *diff_unmerge(struct diff_options *options, const char *path) @@ -333,7 +333,7 @@ struct diff_options { int xdl_opts; int ignore_driver_algorithm; - /* see Documentation/diff-options.txt */ + /* see Documentation/diff-options.adoc */ char **anchors; size_t anchors_nr, anchors_alloc; @@ -353,6 +353,14 @@ struct diff_options { /* to support internal diff recursion by --follow hack*/ int found_follow; + /* + * By default, diffcore_std() resolves the statuses for queued diff file + * pairs by calling diff_resolve_rename_copy(). If status information + * has already been manually set, this option prevents diffcore_std() + * from resetting statuses. + */ + int skip_resolving_statuses; + /* Callback which allows tweaking the options in diff_setup_done(). */ void (*set_default)(struct diff_options *); @@ -508,6 +516,31 @@ void diff_set_default_prefix(struct diff_options *options); int diff_can_quit_early(struct diff_options *); +/* + * Stages changes in the provided diff queue for file additions and deletions. + * If a file pair gets queued, it is returned. + */ +struct diff_filepair *diff_queue_addremove(struct diff_queue_struct *queue, + struct diff_options *, + int addremove, unsigned mode, + const struct object_id *oid, + int oid_valid, const char *fullpath, + unsigned dirty_submodule); + +/* + * Stages changes in the provided diff queue for file modifications. + * If a file pair gets queued, it is returned. + */ +struct diff_filepair *diff_queue_change(struct diff_queue_struct *queue, + struct diff_options *, + unsigned mode1, unsigned mode2, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, int new_oid_valid, + const char *fullpath, + unsigned dirty_submodule1, + unsigned dirty_submodule2); + void diff_addremove(struct diff_options *, int addremove, unsigned mode, diff --git a/diffcore.h b/diffcore.h index 2feb325031..9c0a0e7aaf 100644 --- a/diffcore.h +++ b/diffcore.h @@ -107,7 +107,7 @@ struct diff_filepair { struct diff_filespec *one; struct diff_filespec *two; unsigned short int score; - char status; /* M C R A D U etc. (see Documentation/diff-format.txt or DIFF_STATUS_* in diff.h) */ + char status; /* M C R A D U etc. (see Documentation/diff-format.adoc or DIFF_STATUS_* in diff.h) */ unsigned broken_pair : 1; unsigned renamed_pair : 1; unsigned is_unmerged : 1; @@ -3451,7 +3451,7 @@ void setup_standard_excludes(struct dir_struct *dir) char *get_sparse_checkout_filename(void) { - return git_pathdup("info/sparse-checkout"); + return repo_git_path(the_repository, "info/sparse-checkout"); } int get_sparse_checkout_patterns(struct pattern_list *pl) @@ -142,10 +142,8 @@ int strbuf_edit_interactively(struct repository *r, struct strbuf sb = STRBUF_INIT; int fd, res = 0; - if (!is_absolute_path(path)) { - strbuf_repo_git_path(&sb, r, "%s", path); - path = sb.buf; - } + if (!is_absolute_path(path)) + path = repo_git_path_append(r, &sb, "%s", path); fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) diff --git a/environment.c b/environment.c index e5b361bb5d..9e4c7781be 100644 --- a/environment.c +++ b/environment.c @@ -43,7 +43,6 @@ char *git_log_output_encoding; char *apply_default_whitespace; char *apply_default_ignorewhitespace; char *git_attributes_file; -char *git_hooks_path; int zlib_compression_level = Z_BEST_SPEED; int pack_compression_level = Z_DEFAULT_COMPRESSION; int fsync_object_files = -1; @@ -208,32 +207,6 @@ const char *get_commit_output_encoding(void) return git_commit_encoding ? git_commit_encoding : "UTF-8"; } -static int the_shared_repository = PERM_UMASK; -static int need_shared_repository_from_config = 1; - -void set_shared_repository(int value) -{ - the_shared_repository = value; - need_shared_repository_from_config = 0; -} - -int get_shared_repository(void) -{ - if (need_shared_repository_from_config) { - const char *var = "core.sharedrepository"; - const char *value; - if (!git_config_get_value(var, &value)) - the_shared_repository = git_config_perm(var, value); - need_shared_repository_from_config = 0; - } - return the_shared_repository; -} - -void reset_shared_repository(void) -{ - need_shared_repository_from_config = 1; -} - int use_optional_locks(void) { return git_env_bool(GIT_OPTIONAL_LOCKS_ENVIRONMENT, 1); diff --git a/environment.h b/environment.h index 2f43340f0b..45e690f203 100644 --- a/environment.h +++ b/environment.h @@ -134,16 +134,6 @@ void setup_git_env(const char *git_dir); */ int have_git_dir(void); -/* - * Accessors for the core.sharedrepository config which lazy-load the value - * from the config (if not already set). The "reset" function can be - * used to unset "set" or cached value, meaning that the value will be loaded - * fresh from the config file on the next call to get_shared_repository(). - */ -void set_shared_repository(int value); -int get_shared_repository(void); -void reset_shared_repository(void); - extern int is_bare_repository_cfg; int is_bare_repository(void); extern char *git_work_tree_cfg; @@ -160,7 +150,6 @@ extern int warn_on_object_refname_ambiguity; extern char *apply_default_whitespace; extern char *apply_default_ignorewhitespace; extern char *git_attributes_file; -extern char *git_hooks_path; extern int zlib_compression_level; extern int pack_compression_level; extern size_t packed_git_window_size; @@ -15,7 +15,7 @@ enum fsck_msg_type { }; /* - * Documentation/fsck-msgids.txt documents these; when + * Documentation/fsck-msgids.adoc documents these; when * modifying this list in any way, make sure to keep the * two in sync. */ @@ -30,6 +30,8 @@ enum fsck_msg_type { FUNC(BAD_EMAIL, ERROR) \ FUNC(BAD_NAME, ERROR) \ FUNC(BAD_OBJECT_SHA1, ERROR) \ + FUNC(BAD_PACKED_REF_ENTRY, ERROR) \ + FUNC(BAD_PACKED_REF_HEADER, ERROR) \ FUNC(BAD_PARENT_SHA1, ERROR) \ FUNC(BAD_REF_CONTENT, ERROR) \ FUNC(BAD_REF_FILETYPE, ERROR) \ @@ -53,6 +55,8 @@ enum fsck_msg_type { FUNC(MISSING_TYPE, ERROR) \ FUNC(MISSING_TYPE_ENTRY, ERROR) \ FUNC(MULTIPLE_AUTHORS, ERROR) \ + FUNC(PACKED_REF_ENTRY_NOT_TERMINATED, ERROR) \ + FUNC(PACKED_REF_UNSORTED, ERROR) \ FUNC(TREE_NOT_SORTED, ERROR) \ FUNC(UNKNOWN_TYPE, ERROR) \ FUNC(ZERO_PADDED_DATE, ERROR) \ diff --git a/git-gui/Makefile b/git-gui/Makefile index 667c39ed56..6c5a12bc32 100644 --- a/git-gui/Makefile +++ b/git-gui/Makefile @@ -1,3 +1,4 @@ +# The default target of this Makefile is... all:: # Define V=1 to have a more verbose compile. diff --git a/git-gui/po/glossary/Makefile b/git-gui/po/glossary/Makefile index 749aa2e7ec..e656b0d2b0 100644 --- a/git-gui/po/glossary/Makefile +++ b/git-gui/po/glossary/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +update-po:: + PO_TEMPLATE = git-gui-glossary.pot ALL_POFILES = $(wildcard *.po) @@ -541,6 +541,7 @@ static struct cmd_struct commands[] = { { "diff", cmd_diff, NO_PARSEOPT }, { "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "diff-index", cmd_diff_index, RUN_SETUP | NO_PARSEOPT }, + { "diff-pairs", cmd_diff_pairs, RUN_SETUP | NO_PARSEOPT }, { "diff-tree", cmd_diff_tree, RUN_SETUP | NO_PARSEOPT }, { "difftool", cmd_difftool, RUN_SETUP_GENTLY }, { "fast-export", cmd_fast_export, RUN_SETUP }, @@ -2,6 +2,7 @@ #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" +#include "git-zlib.h" #include "config.h" #include "builtin.h" #include "exec-cmd.h" @@ -797,7 +798,9 @@ void get_version_info(struct strbuf *buf, int show_build_options) #if defined OPENSSL_VERSION_TEXT strbuf_addf(buf, "OpenSSL: %s\n", OPENSSL_VERSION_TEXT); #endif -#if defined ZLIB_VERSION +#if defined ZLIBNG_VERSION + strbuf_addf(buf, "zlib-ng: %s\n", ZLIBNG_VERSION); +#elif defined ZLIB_VERSION strbuf_addf(buf, "zlib: %s\n", ZLIB_VERSION); #endif } @@ -16,8 +16,7 @@ const char *find_hook(struct repository *r, const char *name) int found_hook; - strbuf_reset(&path); - strbuf_repo_git_path(&path, r, "hooks/%s", name); + repo_git_path_replace(r, &path, "hooks/%s", name); found_hook = access(path.buf, X_OK) >= 0; #ifdef STRIP_EXTENSION if (!found_hook) { diff --git a/http-backend.c b/http-backend.c index 33cf378282..50b2858fad 100644 --- a/http-backend.c +++ b/http-backend.c @@ -183,7 +183,7 @@ static void send_strbuf(struct strbuf *hdr, static void send_local_file(struct strbuf *hdr, const char *the_type, const char *name) { - char *p = git_pathdup("%s", name); + char *p = repo_git_path(the_repository, "%s", name); size_t buf_alloc = 8192; char *buf = xmalloc(buf_alloc); int fd; @@ -598,8 +598,7 @@ static void init_curl_http_auth(CURL *result) { if ((!http_auth.username || !*http_auth.username) && (!http_auth.credential || !*http_auth.credential)) { - int empty_auth = curl_empty_auth_enabled(); - if ((empty_auth != -1 && !always_auth_proactively()) || empty_auth == 1) { + if (!always_auth_proactively() && curl_empty_auth_enabled()) { curl_easy_setopt(result, CURLOPT_USERPWD, ":"); return; } else if (!always_auth_proactively()) { @@ -59,7 +59,7 @@ static struct passwd *xgetpwuid_self(int *is_bogus) static void copy_gecos(const struct passwd *w, struct strbuf *name) { - char *src; + const char *src; /* Traditionally GECOS field had office phone numbers etc, separated * with commas. Also & stands for capitalized form of the login name. diff --git a/list-objects-filter-options.h b/list-objects-filter-options.h index 55fab8563d..7b2108b986 100644 --- a/list-objects-filter-options.h +++ b/list-objects-filter-options.h @@ -82,7 +82,7 @@ void list_objects_filter_init(struct list_objects_filter_options *filter_options * "filter" SP <arg> * * The filter keyword will be used by many commands. - * See Documentation/rev-list-options.txt for allowed values for <arg>. + * See Documentation/rev-list-options.adoc for allowed values for <arg>. * * Capture the given arg as the "filter_spec". This can be forwarded to * subordinate commands when necessary (although it's better to pass it through @@ -75,7 +75,7 @@ static int load_one_loose_object_map(struct repository *repo, struct object_dire insert_loose_map(dir, repo->hash_algo->empty_blob, repo->compat_hash_algo->empty_blob); insert_loose_map(dir, repo->hash_algo->null_oid, repo->compat_hash_algo->null_oid); - strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); + repo_common_path_replace(repo, &path, "objects/loose-object-idx"); fp = fopen(path.buf, "rb"); if (!fp) { strbuf_release(&path); @@ -133,7 +133,7 @@ int repo_write_loose_object_map(struct repository *repo) if (!should_use_loose_object_map(repo)) return 0; - strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); + repo_common_path_replace(repo, &path, "objects/loose-object-idx"); fd = hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1); iter = kh_begin(map); if (write_in_full(fd, loose_object_header, strlen(loose_object_header)) < 0) @@ -174,7 +174,7 @@ static int write_one_object(struct repository *repo, const struct object_id *oid struct stat st; struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT; - strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); + repo_common_path_replace(repo, &path, "objects/loose-object-idx"); hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1); fd = open(path.buf, O_WRONLY | O_CREAT | O_APPEND, 0666); @@ -190,7 +190,7 @@ static int write_one_object(struct repository *repo, const struct object_id *oid goto errout; if (close(fd)) goto errout; - adjust_shared_perm(path.buf); + adjust_shared_perm(repo, path.buf); rollback_lock_file(&lock); strbuf_release(&buf); strbuf_release(&path); diff --git a/merge-ort.c b/merge-ort.c index 46e78c3ffa..b0ff2236af 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -3048,7 +3048,8 @@ static int process_renames(struct merge_options *opt, } } - assert(source_deleted || oldinfo->filemask & old_sidemask); + assert(source_deleted || oldinfo->filemask & old_sidemask || + !strcmp(pair->one->path, pair->two->path)); /* Need to check for special types of rename conflicts... */ if (collision && !source_deleted) { diff --git a/merge-recursive.c b/merge-recursive.c index 5dfaf32b2c..884ccf99a5 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -2758,23 +2758,22 @@ static int process_renames(struct merge_options *opt, const struct rename *sre; /* - * FIXME: As string-list.h notes, it's O(n^2) to build a sorted - * string_list one-by-one, but O(n log n) to build it unsorted and - * then sort it. Note that as we build the list, we do not need to - * check if the existing destination path is already in the list, - * because the structure of diffcore_rename guarantees we won't - * have duplicates. + * Note that as we build the list, we do not need to check if the + * existing destination path is already in the list, because the + * structure of diffcore_rename guarantees we won't have duplicates. */ for (i = 0; i < a_renames->nr; i++) { sre = a_renames->items[i].util; - string_list_insert(&a_by_dst, sre->pair->two->path)->util + string_list_append(&a_by_dst, sre->pair->two->path)->util = (void *)sre; } for (i = 0; i < b_renames->nr; i++) { sre = b_renames->items[i].util; - string_list_insert(&b_by_dst, sre->pair->two->path)->util + string_list_append(&b_by_dst, sre->pair->two->path)->util = (void *)sre; } + string_list_sort(&a_by_dst); + string_list_sort(&b_by_dst); for (i = 0, j = 0; i < a_renames->nr || j < b_renames->nr;) { struct string_list *renames1, *renames2Dst; diff --git a/meson.build b/meson.build index bf95576f83..223384b130 100644 --- a/meson.build +++ b/meson.build @@ -191,30 +191,29 @@ project('git', 'c', fs = import('fs') program_path = [] -# Git for Windows provides all the tools we need to build Git. -if host_machine.system() == 'windows' - program_path += [ 'C:/Program Files/Git/bin', 'C:/Program Files/Git/usr/bin' ] +if get_option('sane_tool_path').length() != 0 + program_path = get_option('sane_tool_path') +elif host_machine.system() == 'windows' + # Git for Windows provides all the tools we need to build Git. + program_path = [ 'C:/Program Files/Git/bin', 'C:/Program Files/Git/usr/bin' ] endif cygpath = find_program('cygpath', dirs: program_path, required: false) diff = find_program('diff', dirs: program_path) +git = find_program('git', dirs: program_path, required: false) +sed = find_program('sed', dirs: program_path) shell = find_program('sh', dirs: program_path) tar = find_program('tar', dirs: program_path) -script_environment = environment() -foreach tool : ['cat', 'cut', 'grep', 'sed', 'sort', 'tr', 'uname'] - program = find_program(tool, dirs: program_path) - script_environment.prepend('PATH', fs.parent(program.full_path())) +# Sanity-check that programs required for the build exist. +foreach tool : ['cat', 'cut', 'grep', 'sort', 'tr', 'uname'] + find_program(tool, dirs: program_path) endforeach -git = find_program('git', dirs: program_path, required: false) -if git.found() - script_environment.prepend('PATH', fs.parent(git.full_path())) -endif - -if get_option('sane_tool_path') != '' - script_environment.prepend('PATH', get_option('sane_tool_path')) -endif +script_environment = environment() +foreach path : program_path + script_environment.prepend('PATH', path) +endforeach # The environment used by GIT-VERSION-GEN. Note that we explicitly override # environment variables that might be set by the user. This is by design so @@ -479,6 +478,7 @@ libgit_sources = [ 'userdiff.c', 'utf8.c', 'varint.c', + 'version.c', 'versioncmp.c', 'walker.c', 'wildmatch.c', @@ -540,6 +540,7 @@ builtin_sources = [ 'builtin/diagnose.c', 'builtin/diff-files.c', 'builtin/diff-index.c', + 'builtin/diff-pairs.c', 'builtin/diff-tree.c', 'builtin/diff.c', 'builtin/difftool.c', @@ -678,8 +679,9 @@ else build_options_config.set('WITH_BREAKING_CHANGES', '') endif -if get_option('sane_tool_path') != '' - build_options_config.set_quoted('BROKEN_PATH_FIX', 's|^\# @BROKEN_PATH_FIX@$|git_broken_path_fix "' + get_option('sane_tool_path') + '"|') +if get_option('sane_tool_path').length() != 0 + sane_tool_path = (host_machine.system() == 'windows' ? ';' : ':').join(get_option('sane_tool_path')) + build_options_config.set_quoted('BROKEN_PATH_FIX', 's|^\# @BROKEN_PATH_FIX@$|git_broken_path_fix "' + sane_tool_path + '"|') else build_options_config.set_quoted('BROKEN_PATH_FIX', '/^\# @BROKEN_PATH_FIX@$/d') endif @@ -699,7 +701,6 @@ libgit_c_args = [ '-DETC_GITATTRIBUTES="' + get_option('gitattributes') + '"', '-DETC_GITCONFIG="' + get_option('gitconfig') + '"', '-DFALLBACK_RUNTIME_PREFIX="' + get_option('prefix') + '"', - '-DGIT_EXEC_PATH="' + get_option('prefix') / get_option('libexecdir') / 'git-core"', '-DGIT_HOST_CPU="' + host_machine.cpu_family() + '"', '-DGIT_HTML_PATH="' + get_option('datadir') / 'doc/git-doc"', '-DGIT_INFO_PATH="' + get_option('infodir') + '"', @@ -772,13 +773,28 @@ endif # features. It is optional if you want to neither execute tests nor use any of # these optional features. perl_required = get_option('perl') -if get_option('tests') or get_option('gitweb').enabled() +if get_option('tests') or get_option('gitweb').enabled() or 'netrc' in get_option('credential_helpers') perl_required = true endif # Note that we only set NO_PERL if the Perl features were disabled by the user. # It may not be set when we have found Perl, but only use it to run tests. -perl = find_program('perl', version: '>=5.8.1', dirs: program_path, required: perl_required) +# +# At the time of writing, executing `perl --version` results in a string +# similar to the following output: +# +# This is perl 5, version 40, subversion 0 (v5.40.0) built for x86_64-linux-thread-multi +# +# Meson picks up the "40" as version number instead of using "v5.40.0" +# due to the regular expression it uses. This got fixed in Meson 1.7.0, +# but meanwhile we have to either use `-V:version` instead of `--version`, +# which we can do starting with Meson 1.5.0 and newer, or we have to +# match against the minor version. +if meson.version().version_compare('>=1.5.0') + perl = find_program('perl', dirs: program_path, required: perl_required, version: '>=5.26.0', version_argument: '-V:version') +else + perl = find_program('perl', dirs: program_path, required: perl_required, version: '>=26') +endif perl_features_enabled = perl.found() and get_option('perl').allowed() if perl_features_enabled build_options_config.set('NO_PERL', '') @@ -948,7 +964,9 @@ if curl.found() use_curl_for_imap_send = true endif - libgit_dependencies += curl + # Most executables don't have to link against libcurl, but we still need its + # include directories so that we can resolve LIBCURL_VERSION in "help.c". + libgit_dependencies += curl.partial_dependency(includes: true) libgit_c_args += '-DCURL_DISABLE_TYPECHECK' build_options_config.set('NO_CURL', '') else @@ -1092,11 +1110,11 @@ elif host_machine.system() == 'windows' libgit_sources += [ 'compat/mingw.c', 'compat/winansi.c', + 'compat/win32/dirent.c', 'compat/win32/flush.c', 'compat/win32/path-utils.c', 'compat/win32/pthread.c', 'compat/win32/syslog.c', - 'compat/win32/dirent.c', 'compat/win32mmap.c', 'compat/nedmalloc/nedmalloc.c', ] @@ -1373,7 +1391,11 @@ if https_backend == 'auto' and security_framework.found() endif openssl_required = 'openssl' in [csprng_backend, https_backend, sha1_backend, sha1_unsafe_backend, sha256_backend] -openssl = dependency('openssl', required: openssl_required, default_options: ['default_library=static']) +openssl = dependency('openssl', + required: openssl_required, + allow_fallback: openssl_required or https_backend == 'auto', + default_options: ['default_library=static'], +) if https_backend == 'auto' and openssl.found() https_backend = 'openssl' endif @@ -1387,6 +1409,7 @@ elif https_backend == 'openssl' else # We either couldn't find any dependencies with 'auto' or the user requested # 'none'. Both cases are benign. + https_backend = 'none' endif if https_backend != 'openssl' @@ -1486,6 +1509,7 @@ endif if get_option('runtime_prefix') libgit_c_args += '-DRUNTIME_PREFIX' build_options_config.set('RUNTIME_PREFIX', 'true') + git_exec_path = get_option('libexecdir') / 'git-core' if compiler.has_header('mach-o/dyld.h') libgit_c_args += '-DHAVE_NS_GET_EXECUTABLE_PATH' @@ -1522,7 +1546,9 @@ if get_option('runtime_prefix') endif else build_options_config.set('RUNTIME_PREFIX', 'false') + git_exec_path = get_option('prefix') / get_option('libexecdir') / 'git-core' endif +libgit_c_args += '-DGIT_EXEC_PATH="' + git_exec_path + '"' git_version_file = custom_target( command: [ @@ -1553,32 +1579,18 @@ version_def_h = custom_target( depends: [git_version_file], env: version_gen_environment, ) - -# Build a separate library for "version.c" so that we do not have to rebuild -# everything when the current Git commit changes. -libgit_version_library = static_library('git-version', - sources: [ - 'version.c', - version_def_h, - ], - c_args: libgit_c_args + [ - '-DGIT_VERSION_H="' + version_def_h.full_path() + '"', - ], - dependencies: libgit_dependencies, - include_directories: libgit_include_directories, -) - -libgit_library = static_library('git', - sources: libgit_sources, - c_args: libgit_c_args, - link_with: libgit_version_library, - dependencies: libgit_dependencies, - include_directories: libgit_include_directories, -) +libgit_sources += version_def_h libgit = declare_dependency( + link_with: static_library('git', + sources: libgit_sources, + c_args: libgit_c_args + [ + '-DGIT_VERSION_H="' + version_def_h.full_path() + '"', + ], + dependencies: libgit_dependencies, + include_directories: libgit_include_directories, + ), compile_args: libgit_c_args, - link_with: libgit_library, dependencies: libgit_dependencies, include_directories: libgit_include_directories, ) @@ -1619,88 +1631,89 @@ if host_machine.system() == 'windows' error('Unsupported compiler ' + compiler.get_id()) endif endif -common_main_library = static_library('common-main', - sources: common_main_sources, - c_args: libgit_c_args, - dependencies: libgit_dependencies, - include_directories: libgit_include_directories, -) -common_main = declare_dependency( - link_with: common_main_library, + +libgit_commonmain = declare_dependency( + link_with: static_library('common-main', + sources: common_main_sources, + dependencies: [ libgit ], + ), link_args: common_main_link_args, + dependencies: [ libgit ], ) bin_wrappers = [ ] test_dependencies = [ ] -git = executable('git', +git_builtin = executable('git', sources: builtin_sources + 'git.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) -bin_wrappers += git +bin_wrappers += git_builtin test_dependencies += executable('git-daemon', sources: 'daemon.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) test_dependencies += executable('git-sh-i18n--envsubst', sources: 'sh-i18n--envsubst.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) bin_wrappers += executable('git-shell', sources: 'shell.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) test_dependencies += executable('git-http-backend', sources: 'http-backend.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) bin_wrappers += executable('scalar', sources: 'scalar.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) if get_option('curl').enabled() - curl_sources = [ - 'http.c', - 'http-walker.c', - ] + libgit_curl = declare_dependency( + sources: [ + 'http.c', + 'http-walker.c', + ], + dependencies: [libgit_commonmain, curl], + ) - git_remote_http = executable('git-remote-http', - sources: curl_sources + 'remote-curl.c', - dependencies: [libgit, common_main], + test_dependencies += executable('git-remote-http', + sources: 'remote-curl.c', + dependencies: [libgit_curl], install: true, install_dir: get_option('libexecdir') / 'git-core', ) - test_dependencies += git_remote_http test_dependencies += executable('git-http-fetch', - sources: curl_sources + 'http-fetch.c', - dependencies: [libgit, common_main], + sources: 'http-fetch.c', + dependencies: [libgit_curl], install: true, install_dir: get_option('libexecdir') / 'git-core', ) if expat.found() test_dependencies += executable('git-http-push', - sources: curl_sources + 'http-push.c', - dependencies: [libgit, common_main], + sources: 'http-push.c', + dependencies: [libgit_curl], install: true, install_dir: get_option('libexecdir') / 'git-core', ) @@ -1708,8 +1721,8 @@ if get_option('curl').enabled() foreach alias : [ 'git-remote-https', 'git-remote-ftp', 'git-remote-ftps' ] test_dependencies += executable(alias, - objects: git_remote_http.extract_all_objects(recursive: false), - dependencies: [libgit, common_main], + sources: 'remote-curl.c', + dependencies: [libgit_curl], ) install_symlink(alias + executable_suffix, @@ -1719,22 +1732,17 @@ if get_option('curl').enabled() endforeach endif -imap_send_sources = ['imap-send.c'] -if use_curl_for_imap_send - imap_send_sources += curl_sources -endif - test_dependencies += executable('git-imap-send', - sources: imap_send_sources, - dependencies: [libgit, common_main], + sources: 'imap-send.c', + dependencies: [ use_curl_for_imap_send ? libgit_curl : libgit_commonmain ], install: true, install_dir: get_option('libexecdir') / 'git-core', ) foreach alias : [ 'git-receive-pack', 'git-upload-archive', 'git-upload-pack' ] bin_wrappers += executable(alias, - objects: git.extract_all_objects(recursive: false), - dependencies: [libgit, common_main], + objects: git_builtin.extract_all_objects(recursive: false), + dependencies: [libgit_commonmain], ) install_symlink(alias + executable_suffix, @@ -1961,10 +1969,9 @@ subdir('contrib') foreach key, value : { 'DIFF': diff.full_path(), + 'GIT_SOURCE_DIR': meson.project_source_root(), 'GIT_TEST_CMP': diff.full_path() + ' -u', 'GIT_TEST_GITPERLLIB': meson.project_build_root() / 'perl', - 'GIT_TEST_MERGE_TOOLS_DIR': meson.project_source_root() / 'mergetools', - 'GIT_TEST_POPATH': meson.project_source_root() / 'po', 'GIT_TEST_TEMPLATE_DIR': meson.project_build_root() / 'templates', 'GIT_TEST_TEXTDOMAINDIR': meson.project_build_root() / 'po', 'PAGER_ENV': get_option('pager_environment'), diff --git a/meson_options.txt b/meson_options.txt index 5c12e9055e..78d172a740 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -13,8 +13,8 @@ option('perl_cpan_fallback', type: 'boolean', value: true, description: 'Install bundled copies of CPAN modules that serve as a fallback in case the modules are not available on the system.') option('runtime_prefix', type: 'boolean', value: false, description: 'Resolve ancillary tooling and support files relative to the location of the runtime binary instead of hard-coding them into the binary.') -option('sane_tool_path', type: 'string', value: '', - description: 'A colon-separated list of paths to prepend to PATH if your tools in /usr/bin are broken.') +option('sane_tool_path', type: 'array', value: [], + description: 'An array of paths to pick up tools from in case the normal tools are broken or lacking.') # Build information compiled into Git and other parts like documentation. option('build_date', type: 'string', value: '', @@ -27,7 +27,9 @@ option('version', type: 'string', value: '', description: 'Version string reported by git-version(1) and other tools.') # Features supported by Git. -option('contrib', type: 'array', value: [ 'completion' ], choices: [ 'completion', 'subtree' ], +option('contrib', type: 'array', value: [ 'completion' ], choices: [ 'completion', 'contacts', 'subtree' ], + description: 'Contributed features to include.') +option('credential_helpers', type: 'array', value: [ ], choices: [ 'libsecret', 'netrc', 'osxkeychain', 'wincred' ], description: 'Contributed features to include.') option('curl', type: 'feature', value: 'enabled', description: 'Build helpers used to access remotes with the HTTP transport.') @@ -99,6 +101,8 @@ option('docs_backend', type: 'combo', choices: ['asciidoc', 'asciidoctor', 'auto description: 'Which backend to use to generate documentation.') # Testing. +option('coccinelle', type: 'feature', value: 'auto', + description: 'Provide a coccicheck target that generates a Coccinelle patch.') option('tests', type: 'boolean', value: true, description: 'Enable building tests. This requires Perl, but is separate from the "perl" option such that you can build tests without Perl features enabled.') option('test_output_directory', type: 'string', diff --git a/midx-write.c b/midx-write.c index 61b59d557d..48d6558253 100644 --- a/midx-write.c +++ b/midx-write.c @@ -1336,7 +1336,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir, return -1; } - if (adjust_shared_perm(get_tempfile_path(incr))) { + if (adjust_shared_perm(r, get_tempfile_path(incr))) { error(_("unable to adjust shared permissions for '%s'"), get_tempfile_path(incr)); return -1; diff --git a/notes-merge.c b/notes-merge.c index 8d701ed428..67a472020d 100644 --- a/notes-merge.c +++ b/notes-merge.c @@ -275,41 +275,45 @@ static void diff_tree_local(struct notes_merge_options *o, static void check_notes_merge_worktree(struct notes_merge_options *o) { + struct strbuf buf = STRBUF_INIT; + if (!o->has_worktree) { /* * Must establish NOTES_MERGE_WORKTREE. * Abort if NOTES_MERGE_WORKTREE already exists */ - if (file_exists(git_path(NOTES_MERGE_WORKTREE)) && - !is_empty_dir(git_path(NOTES_MERGE_WORKTREE))) { + if (file_exists(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)) && + !is_empty_dir(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE))) { if (advice_enabled(ADVICE_RESOLVE_CONFLICT)) die(_("You have not concluded your previous " "notes merge (%s exists).\nPlease, use " "'git notes merge --commit' or 'git notes " "merge --abort' to commit/abort the " "previous merge before you start a new " - "notes merge."), git_path("NOTES_MERGE_*")); + "notes merge."), repo_git_path_replace(the_repository, &buf, "NOTES_MERGE_*")); else die(_("You have not concluded your notes merge " - "(%s exists)."), git_path("NOTES_MERGE_*")); + "(%s exists)."), repo_git_path_replace(the_repository, &buf, "NOTES_MERGE_*")); } - if (safe_create_leading_directories_const(git_path( + if (safe_create_leading_directories_const(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE "/.test"))) die_errno("unable to create directory %s", - git_path(NOTES_MERGE_WORKTREE)); + repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)); o->has_worktree = 1; - } else if (!file_exists(git_path(NOTES_MERGE_WORKTREE))) + } else if (!file_exists(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE))) /* NOTES_MERGE_WORKTREE should already be established */ die("missing '%s'. This should not happen", - git_path(NOTES_MERGE_WORKTREE)); + repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)); + + strbuf_release(&buf); } static void write_buf_to_worktree(const struct object_id *obj, const char *buf, unsigned long size) { int fd; - char *path = git_pathdup(NOTES_MERGE_WORKTREE "/%s", oid_to_hex(obj)); + char *path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE "/%s", oid_to_hex(obj)); if (safe_create_leading_directories_const(path)) die_errno("unable to create directory for '%s'", path); @@ -695,7 +699,7 @@ int notes_merge_commit(struct notes_merge_options *o, const char *msg = strstr(buffer, "\n\n"); int baselen; - git_path_buf(&path, NOTES_MERGE_WORKTREE); + repo_git_path_replace(the_repository, &path, NOTES_MERGE_WORKTREE); if (o->verbosity >= 3) printf("Committing notes in notes merge worktree at %s\n", path.buf); @@ -757,7 +761,7 @@ int notes_merge_abort(struct notes_merge_options *o) struct strbuf buf = STRBUF_INIT; int ret; - git_path_buf(&buf, NOTES_MERGE_WORKTREE); + repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE); if (o->verbosity >= 3) printf("Removing notes merge worktree at %s/*\n", buf.buf); ret = remove_dir_recursively(&buf, REMOVE_DIR_KEEP_TOPLEVEL); diff --git a/object-file.c b/object-file.c index 00c3a4b910..726e41a047 100644 --- a/object-file.c +++ b/object-file.c @@ -394,7 +394,7 @@ int mkdir_in_gitdir(const char *path) } strbuf_release(&sb); } - return adjust_shared_perm(path); + return adjust_shared_perm(the_repository, path); } static enum scld_error safe_create_leading_directories_1(char *path, int share) @@ -443,7 +443,7 @@ static enum scld_error safe_create_leading_directories_1(char *path, int share) ret = SCLD_VANISHED; else ret = SCLD_FAILED; - } else if (share && adjust_shared_perm(path)) { + } else if (share && adjust_shared_perm(the_repository, path)) { ret = SCLD_PERMS; } *slash = slash_character; @@ -482,14 +482,14 @@ int odb_mkstemp(struct strbuf *temp_filename, const char *pattern) * restrictive except to remove write permission. */ int mode = 0444; - git_path_buf(temp_filename, "objects/%s", pattern); + repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); fd = git_mkstemp_mode(temp_filename->buf, mode); if (0 <= fd) return fd; /* slow path */ /* some mkstemp implementations erase temp_filename on failure */ - git_path_buf(temp_filename, "objects/%s", pattern); + repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); safe_create_leading_directories(temp_filename->buf); return xmkstemp_mode(temp_filename->buf, mode); } @@ -723,7 +723,7 @@ static void read_info_alternates(struct repository *r, void add_to_alternates_file(const char *reference) { struct lock_file lock = LOCK_INIT; - char *alts = git_pathdup("objects/info/alternates"); + char *alts = repo_git_path(the_repository, "objects/info/alternates"); FILE *in, *out; int found = 0; @@ -2111,7 +2111,7 @@ retry: } out: - if (adjust_shared_perm(filename)) + if (adjust_shared_perm(the_repository, filename)) return error(_("unable to set permission to '%s'"), filename); return 0; } @@ -2187,7 +2187,7 @@ static int create_tmpfile(struct strbuf *tmp, const char *filename) strbuf_add(tmp, filename, dirlen - 1); if (mkdir(tmp->buf, 0777) && errno != EEXIST) return -1; - if (adjust_shared_perm(tmp->buf)) + if (adjust_shared_perm(the_repository, tmp->buf)) return -1; /* Try again */ diff --git a/object-name.c b/object-name.c index 945d5bdef2..76749fbfe6 100644 --- a/object-name.c +++ b/object-name.c @@ -1273,7 +1273,7 @@ static int peel_onion(struct repository *r, const char *name, int len, } /* - * Documentation/revisions.txt says: + * Documentation/revisions.adoc says: * '<describeOutput>', e.g. 'v1.7.4.2-679-g3bee7fb':: * Output from `git describe`; i.e. a closest tag, optionally * followed by a dash and a number of commits, followed by a dash, a diff --git a/oss-fuzz/meson.build b/oss-fuzz/meson.build index ed79665501..878afd8426 100644 --- a/oss-fuzz/meson.build +++ b/oss-fuzz/meson.build @@ -15,6 +15,6 @@ foreach fuzz_program : fuzz_programs 'dummy-cmd-main.c', fuzz_program, ], - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], ) endforeach diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index a06a1f35c6..34e86d4994 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -1072,7 +1072,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer, finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE); - if (adjust_shared_perm(tmp_file.buf)) + if (adjust_shared_perm(the_repository, tmp_file.buf)) die_errno("unable to make temporary bitmap file readable"); if (rename(tmp_file.buf, filename)) diff --git a/pack-write.c b/pack-write.c index d61e29ba4e..823e40b42f 100644 --- a/pack-write.c +++ b/pack-write.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "environment.h" #include "gettext.h" @@ -287,7 +289,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo, write_rev_index_positions(f, pack_order, nr_objects); write_rev_trailer(hash_algo, f, hash); - if (adjust_shared_perm(path) < 0) + if (adjust_shared_perm(the_repository, path) < 0) die(_("failed to make %s readable"), path); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, @@ -350,7 +352,7 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo, write_mtimes_objects(f, to_pack, objects, nr_objects); write_mtimes_trailer(hash_algo, f, hash); - if (adjust_shared_perm(mtimes_name) < 0) + if (adjust_shared_perm(the_repository, mtimes_name) < 0) die(_("failed to make %s readable"), mtimes_name); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, @@ -566,12 +568,12 @@ void stage_tmp_packfiles(const struct git_hash_algo *hash_algo, char *rev_tmp_name = NULL; char *mtimes_tmp_name = NULL; - if (adjust_shared_perm(pack_tmp_name)) + if (adjust_shared_perm(the_repository, pack_tmp_name)) die_errno("unable to make temporary pack file readable"); *idx_tmp_name = (char *)write_idx_file(hash_algo, NULL, written_list, nr_written, pack_idx_opts, hash); - if (adjust_shared_perm(*idx_tmp_name)) + if (adjust_shared_perm(the_repository, *idx_tmp_name)) die_errno("unable to make temporary index file readable"); rev_tmp_name = write_rev_file(hash_algo, NULL, written_list, nr_written, diff --git a/parse-options.h b/parse-options.h index fca944d9a9..997ffbee80 100644 --- a/parse-options.h +++ b/parse-options.h @@ -6,7 +6,7 @@ struct repository; /** - * Refer to Documentation/technical/api-parse-options.txt for the API doc. + * Refer to Documentation/technical/api-parse-options.adoc for the API doc. */ enum parse_opt_type { @@ -2,8 +2,6 @@ * Utilities for paths and pathnames */ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "abspath.h" #include "environment.h" @@ -30,7 +28,7 @@ static int get_st_mode_bits(const char *path, int *mode) return 0; } -struct strbuf *get_pathname(void) +static struct strbuf *get_pathname(void) { static struct strbuf pathname_array[4] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT @@ -387,10 +385,11 @@ void report_linked_checkout_garbage(struct repository *r) strbuf_release(&sb); } -static void adjust_git_path(const struct repository *repo, +static void adjust_git_path(struct repository *repo, struct strbuf *buf, int git_dir_len) { const char *base = buf->buf + git_dir_len; + if (is_dir_file(base, "info", "grafts")) strbuf_splice(buf, 0, buf->len, repo->graft_file, strlen(repo->graft_file)); @@ -399,8 +398,8 @@ static void adjust_git_path(const struct repository *repo, repo->index_file, strlen(repo->index_file)); else if (dir_prefix(base, "objects")) replace_dir(buf, git_dir_len + 7, repo->objects->odb->path); - else if (git_hooks_path && dir_prefix(base, "hooks")) - replace_dir(buf, git_dir_len + 5, git_hooks_path); + else if (repo_settings_get_hooks_path(repo) && dir_prefix(base, "hooks")) + replace_dir(buf, git_dir_len + 5, repo_settings_get_hooks_path(repo)); else if (repo->different_commondir) update_common_dir(buf, git_dir_len, repo->commondir); } @@ -414,12 +413,12 @@ static void strbuf_worktree_gitdir(struct strbuf *buf, else if (!wt->id) strbuf_addstr(buf, repo->commondir); else - strbuf_git_common_path(buf, repo, "worktrees/%s", wt->id); + repo_common_path_append(repo, buf, "worktrees/%s", wt->id); } -void repo_git_pathv(const struct repository *repo, - const struct worktree *wt, struct strbuf *buf, - const char *fmt, va_list args) +static void repo_git_pathv(struct repository *repo, + const struct worktree *wt, struct strbuf *buf, + const char *fmt, va_list args) { int gitdir_len; strbuf_worktree_gitdir(buf, repo, wt); @@ -432,7 +431,7 @@ void repo_git_pathv(const struct repository *repo, strbuf_cleanup_path(buf); } -char *repo_git_path(const struct repository *repo, +char *repo_git_path(struct repository *repo, const char *fmt, ...) { struct strbuf path = STRBUF_INIT; @@ -443,14 +442,27 @@ char *repo_git_path(const struct repository *repo, return strbuf_detach(&path, NULL); } -void strbuf_repo_git_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +const char *repo_git_path_append(struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) { va_list args; va_start(args, fmt); repo_git_pathv(repo, NULL, sb, fmt, args); va_end(args); + return sb->buf; +} + +const char *repo_git_path_replace(struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + strbuf_reset(sb); + va_start(args, fmt); + repo_git_pathv(repo, NULL, sb, fmt, args); + va_end(args); + return sb->buf; } char *mkpathdup(const char *fmt, ...) @@ -506,39 +518,56 @@ char *repo_worktree_path(const struct repository *repo, const char *fmt, ...) struct strbuf path = STRBUF_INIT; va_list args; + va_start(args, fmt); + do_worktree_path(repo, &path, fmt, args); + va_end(args); + + return strbuf_detach(&path, NULL); +} + +const char *repo_worktree_path_append(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + if (!repo->worktree) return NULL; va_start(args, fmt); - do_worktree_path(repo, &path, fmt, args); + do_worktree_path(repo, sb, fmt, args); va_end(args); - return strbuf_detach(&path, NULL); + return sb->buf; } -void strbuf_repo_worktree_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +const char *repo_worktree_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) { va_list args; + strbuf_reset(sb); if (!repo->worktree) - return; + return NULL; va_start(args, fmt); do_worktree_path(repo, sb, fmt, args); va_end(args); + + return sb->buf; } /* Returns 0 on success, negative on failure. */ -static int do_submodule_path(struct strbuf *buf, const char *path, +static int do_submodule_path(struct repository *repo, + struct strbuf *buf, const char *path, const char *fmt, va_list args) { struct strbuf git_submodule_common_dir = STRBUF_INIT; struct strbuf git_submodule_dir = STRBUF_INIT; int ret; - ret = submodule_to_gitdir(&git_submodule_dir, path); + ret = submodule_to_gitdir(repo, &git_submodule_dir, path); if (ret) goto cleanup; @@ -557,13 +586,14 @@ cleanup: return ret; } -char *git_pathdup_submodule(const char *path, const char *fmt, ...) +char *repo_submodule_path(struct repository *repo, + const char *path, const char *fmt, ...) { int err; va_list args; struct strbuf buf = STRBUF_INIT; va_start(args, fmt); - err = do_submodule_path(&buf, path, fmt, args); + err = do_submodule_path(repo, &buf, path, fmt, args); va_end(args); if (err) { strbuf_release(&buf); @@ -572,22 +602,41 @@ char *git_pathdup_submodule(const char *path, const char *fmt, ...) return strbuf_detach(&buf, NULL); } -int strbuf_git_path_submodule(struct strbuf *buf, const char *path, - const char *fmt, ...) +const char *repo_submodule_path_append(struct repository *repo, + struct strbuf *buf, + const char *path, + const char *fmt, ...) { int err; va_list args; va_start(args, fmt); - err = do_submodule_path(buf, path, fmt, args); + err = do_submodule_path(repo, buf, path, fmt, args); va_end(args); + if (err) + return NULL; + return buf->buf; +} - return err; +const char *repo_submodule_path_replace(struct repository *repo, + struct strbuf *buf, + const char *path, + const char *fmt, ...) +{ + int err; + va_list args; + strbuf_reset(buf); + va_start(args, fmt); + err = do_submodule_path(repo, buf, path, fmt, args); + va_end(args); + if (err) + return NULL; + return buf->buf; } -void repo_common_pathv(const struct repository *repo, - struct strbuf *sb, - const char *fmt, - va_list args) +static void repo_common_pathv(const struct repository *repo, + struct strbuf *sb, + const char *fmt, + va_list args) { strbuf_addstr(sb, repo->commondir); if (sb->len && !is_dir_sep(sb->buf[sb->len - 1])) @@ -596,14 +645,38 @@ void repo_common_pathv(const struct repository *repo, strbuf_cleanup_path(sb); } -void strbuf_git_common_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +char *repo_common_path(const struct repository *repo, + const char *fmt, ...) { + struct strbuf sb = STRBUF_INIT; va_list args; va_start(args, fmt); + repo_common_pathv(repo, &sb, fmt, args); + va_end(args); + return strbuf_detach(&sb, NULL); +} + +const char *repo_common_path_append(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + repo_common_pathv(repo, sb, fmt, args); + va_end(args); + return sb->buf; +} + +const char *repo_common_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + strbuf_reset(sb); + va_start(args, fmt); repo_common_pathv(repo, sb, fmt, args); va_end(args); + return sb->buf; } static struct passwd *getpw_str(const char *username, size_t len) @@ -765,21 +838,22 @@ const char *enter_repo(const char *path, unsigned flags) return NULL; } -int calc_shared_perm(int mode) +int calc_shared_perm(struct repository *repo, + int mode) { int tweak; - if (get_shared_repository() < 0) - tweak = -get_shared_repository(); + if (repo_settings_get_shared_repository(repo) < 0) + tweak = -repo_settings_get_shared_repository(repo); else - tweak = get_shared_repository(); + tweak = repo_settings_get_shared_repository(repo); if (!(mode & S_IWUSR)) tweak &= ~0222; if (mode & S_IXUSR) /* Copy read bits to execute bits */ tweak |= (tweak & 0444) >> 2; - if (get_shared_repository() < 0) + if (repo_settings_get_shared_repository(repo) < 0) mode = (mode & ~0777) | tweak; else mode |= tweak; @@ -787,17 +861,17 @@ int calc_shared_perm(int mode) return mode; } - -int adjust_shared_perm(const char *path) +int adjust_shared_perm(struct repository *repo, + const char *path) { int old_mode, new_mode; - if (!get_shared_repository()) + if (!repo_settings_get_shared_repository(repo)) return 0; if (get_st_mode_bits(path, &old_mode) < 0) return -1; - new_mode = calc_shared_perm(old_mode); + new_mode = calc_shared_perm(repo, old_mode); if (S_ISDIR(old_mode)) { /* Copy read bits to execute bits */ new_mode |= (new_mode & 0444) >> 2; @@ -816,7 +890,7 @@ int adjust_shared_perm(const char *path) return 0; } -void safe_create_dir(const char *dir, int share) +void safe_create_dir(struct repository *repo, const char *dir, int share) { if (mkdir(dir, 0777) < 0) { if (errno != EEXIST) { @@ -824,7 +898,7 @@ void safe_create_dir(const char *dir, int share) exit(1); } } - else if (share && adjust_shared_perm(dir)) + else if (share && adjust_shared_perm(repo, dir)) die(_("Could not make %s writable by group"), dir); } @@ -25,22 +25,20 @@ char *mkpathdup(const char *fmt, ...) __attribute__((format (printf, 1, 2))); /* - * The `strbuf_git_common_path` family of functions will construct a path into a + * The `repo_common_path` family of functions will construct a path into a * repository's common git directory, which is shared by all worktrees. */ - -/* - * Constructs a path into the common git directory of repository `repo` and - * append it in the provided buffer `sb`. - */ -void strbuf_git_common_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +char *repo_common_path(const struct repository *repo, + const char *fmt, ...) + __attribute__((format (printf, 2, 3))); +const char *repo_common_path_append(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) + __attribute__((format (printf, 3, 4))); +const char *repo_common_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) __attribute__((format (printf, 3, 4))); -void repo_common_pathv(const struct repository *repo, - struct strbuf *buf, - const char *fmt, - va_list args); /* * The `repo_git_path` family of functions will construct a path into a repository's @@ -54,29 +52,16 @@ void repo_common_pathv(const struct repository *repo, * For an exhaustive list of the adjustments made look at `common_list` and * `adjust_git_path` in path.c. */ - -/* - * Return a path into the git directory of repository `repo`. - */ -char *repo_git_path(const struct repository *repo, +char *repo_git_path(struct repository *repo, const char *fmt, ...) __attribute__((format (printf, 2, 3))); - -/* - * Print a path into the git directory of repository `repo` into the provided - * buffer. - */ -void repo_git_pathv(const struct repository *repo, - const struct worktree *wt, struct strbuf *buf, - const char *fmt, va_list args); - -/* - * Construct a path into the git directory of repository `repo` and append it - * to the provided buffer `sb`. - */ -void strbuf_repo_git_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +const char *repo_git_path_append(struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) + __attribute__((format (printf, 3, 4))); +const char *repo_git_path_replace(struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) __attribute__((format (printf, 3, 4))); /* @@ -90,40 +75,44 @@ const char *worktree_git_path(struct repository *r, __attribute__((format (printf, 3, 4))); /* - * Return a path into the worktree of repository `repo`. + * The `repo_worktree_path` family of functions will construct a path into a + * repository's worktree. * - * If the repository doesn't have a worktree NULL is returned. + * Returns a `NULL` pointer in case the repository has no worktree. */ char *repo_worktree_path(const struct repository *repo, const char *fmt, ...) __attribute__((format (printf, 2, 3))); - -/* - * Construct a path into the worktree of repository `repo` and append it - * to the provided buffer `sb`. - * - * If the repository doesn't have a worktree nothing will be appended to `sb`. - */ -void strbuf_repo_worktree_path(struct strbuf *sb, - const struct repository *repo, +const char *repo_worktree_path_append(const struct repository *repo, + struct strbuf *sb, const char *fmt, ...) __attribute__((format (printf, 3, 4))); +const char *repo_worktree_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) + __attribute__((format (printf, 3, 4))); /* - * Return a path into a submodule's git directory located at `path`. `path` - * must only reference a submodule of the main repository (the_repository). - */ -char *git_pathdup_submodule(const char *path, const char *fmt, ...) - __attribute__((format (printf, 2, 3))); - -/* - * Construct a path into a submodule's git directory located at `path` and - * append it to the provided buffer `sb`. `path` must only reference a - * submodule of the main repository (the_repository). + * The `repo_submodule_path` family of functions will construct a path into a + * submodule's git directory located at `path`. `path` must be a submodule path + * as found in the index and must be part of the given repository. + * + * Returns a `NULL` pointer in case the submodule cannot be found. */ -int strbuf_git_path_submodule(struct strbuf *sb, const char *path, - const char *fmt, ...) +char *repo_submodule_path(struct repository *repo, + const char *path, + const char *fmt, ...) __attribute__((format (printf, 3, 4))); +const char *repo_submodule_path_append(struct repository *repo, + struct strbuf *sb, + const char *path, + const char *fmt, ...) + __attribute__((format (printf, 4, 5))); +const char *repo_submodule_path_replace(struct repository *repo, + struct strbuf *sb, + const char *path, + const char *fmt, ...) + __attribute__((format (printf, 4, 5))); void report_linked_checkout_garbage(struct repository *r); @@ -152,8 +141,8 @@ const char *git_path_shallow(struct repository *r); int ends_with_path_components(const char *path, const char *components); -int calc_shared_perm(int mode); -int adjust_shared_perm(const char *path); +int calc_shared_perm(struct repository *repo, int mode); +int adjust_shared_perm(struct repository *repo, const char *path); char *interpolate_path(const char *path, int real_home); @@ -230,101 +219,21 @@ char *xdg_cache_home(const char *filename); * directories under $GIT_DIR. Don't use it for working tree * directories. */ -void safe_create_dir(const char *dir, int share); - -/* - * Do not use this function. It is only exported to other subsystems until we - * can get rid of the below block of functions that implicitly rely on - * `the_repository`. - */ -struct strbuf *get_pathname(void); +void safe_create_dir(struct repository *repo, const char *dir, int share); # ifdef USE_THE_REPOSITORY_VARIABLE # include "strbuf.h" # include "repository.h" -/* - * Return a statically allocated path into the main repository's - * (the_repository) common git directory. - */ -__attribute__((format (printf, 1, 2))) -static inline const char *git_common_path(const char *fmt, ...) -{ - struct strbuf *pathname = get_pathname(); - va_list args; - va_start(args, fmt); - repo_common_pathv(the_repository, pathname, fmt, args); - va_end(args); - return pathname->buf; -} - -/* - * Construct a path into the main repository's (the_repository) git directory - * and place it in the provided buffer `buf`, the contents of the buffer will - * be overridden. - */ -__attribute__((format (printf, 2, 3))) -static inline char *git_path_buf(struct strbuf *buf, const char *fmt, ...) -{ - va_list args; - strbuf_reset(buf); - va_start(args, fmt); - repo_git_pathv(the_repository, NULL, buf, fmt, args); - va_end(args); - return buf->buf; -} - -/* - * Construct a path into the main repository's (the_repository) git directory - * and append it to the provided buffer `sb`. - */ -__attribute__((format (printf, 2, 3))) -static inline void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - repo_git_pathv(the_repository, NULL, sb, fmt, args); - va_end(args); -} - -/* - * Return a statically allocated path into the main repository's - * (the_repository) git directory. - */ -__attribute__((format (printf, 1, 2))) -static inline const char *git_path(const char *fmt, ...) -{ - struct strbuf *pathname = get_pathname(); - va_list args; - va_start(args, fmt); - repo_git_pathv(the_repository, NULL, pathname, fmt, args); - va_end(args); - return pathname->buf; -} - #define GIT_PATH_FUNC(func, filename) \ const char *func(void) \ { \ static char *ret; \ if (!ret) \ - ret = git_pathdup(filename); \ + ret = repo_git_path(the_repository, filename); \ return ret; \ } -/* - * Return a path into the main repository's (the_repository) git directory. - */ -__attribute__((format (printf, 1, 2))) -static inline char *git_pathdup(const char *fmt, ...) -{ - struct strbuf path = STRBUF_INIT; - va_list args; - va_start(args, fmt); - repo_git_pathv(the_repository, NULL, &path, fmt, args); - va_end(args); - return strbuf_detach(&path, NULL); -} - # endif /* USE_THE_REPOSITORY_VARIABLE */ #endif /* PATH_H */ @@ -1,7 +1,7 @@ # Bulgarian translation of git po-file. -# Copyright (C) 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Alexander Shopov <ash@kambanaria.org>. +# Copyright (C) 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025 Alexander Shopov <ash@kambanaria.org>. # This file is distributed under the same license as the git package. -# Alexander Shopov <ash@kambanaria.org>, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. +# Alexander Shopov <ash@kambanaria.org>, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025. # ======================== # DICTIONARY TO MERGE IN GIT GUI # ------------------------ @@ -233,6 +233,7 @@ # cache-tree кеша на обектите-дървета # acquire lock придобивам ключалка # detached отделѐн, неÑвързан +# revision walk обхождане на верÑиите # # ------------------------ # „$var“ - може да не Ñработва за shell има gettext и eval_gettext - проверка - намират Ñе леÑно по „$ @@ -261,8 +262,8 @@ msgid "" msgstr "" "Project-Id-Version: git 2.48\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-27 22:37+0100\n" -"PO-Revision-Date: 2024-12-27 22:40+0100\n" +"POT-Creation-Date: 2025-03-05 22:57+0000\n" +"PO-Revision-Date: 2025-03-06 09:15+0100\n" "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n" "Language-Team: Bulgarian <dict@fsa-bg.org>\n" "Language: bg\n" @@ -2655,6 +2656,18 @@ msgstr "git archive: протоколна грешка" msgid "git archive: expected a flush" msgstr "git archive: очакваше Ñе изчиÑтване на буферите чрез „flush“" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=БРОЙ] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "проблем при зареждане на чаÑтично хранилище" + +msgid "Minimum number of objects to request at a time" +msgstr "Минимален БРОЙ обекти заÑвÑвани наведнъж" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Ограничаване на липÑващите обекти до текущото чаÑтично хранилище" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -3434,10 +3447,6 @@ msgstr "" msgid "git version:\n" msgstr "верÑÐ¸Ñ Ð½Ð° git:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "грешка при изпълнението на „uname()“ — „%s“ (%d)\n" - msgid "compiler info: " msgstr "компилатор: " @@ -4466,8 +4475,98 @@ msgstr "" "ÐаÑтройката „clean.requireForce“ е зададена, което изиÑква опциÑта „-f“. " "ÐÑма да Ñе извърши изчиÑтване" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [ОПЦИЯ…] [--] ХРÐÐИЛИЩЕ [ДИРЕКТОРИЯ]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "" +"ПРЕДУПРЕЖДЕÐИЕ: не може да Ñе добави алтернативен източник на „%s“: %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "не може да бъде получена Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%s“" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "„%s“ ÑъщеÑтвува и не е директориÑ" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "„%s“ е Ñимволна връзка, не може да Ñе клонира Ñ Ð¾Ð¿Ñ†Ð¸Ñта „--local“" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "неуÑпешно итериране по „%s“" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "" +"Ñимволната връзка „%s“ ÑъщеÑтвува, не може да Ñе клонира Ñ Ð¾Ð¿Ñ†Ð¸Ñта „--local“" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "неуÑпешно изтриване на „%s“" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "твърдата връзка не може да Ñе провери при „%s“" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "твърдата връзка е различна от източника „%s“" + +#, c-format +msgid "failed to create link '%s'" +msgstr "връзката „%s“ не може да бъде Ñъздадена" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "файлът не може да бъде копиран като „%s“" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "неуÑпешно итериране по „%s“" + +#, c-format +msgid "done.\n" +msgstr "дейÑтвието завърши.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Клонирането бе уÑпешно за разлика от подготовката на работното дърво\n" +"за определен клон. Ð’Ñе пак може да проверите кои файлове и от кой\n" +"клон в момента Ñа изтеглени Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ñ‚Ð° „git status“. Може да\n" +"завършите изтеглÑнето на клона Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ñ‚Ð°:\n" +"\n" +" git restore --source=HEAD :/\n" + +msgid "remote did not send all necessary objects" +msgstr "отдалеченото хранилище не изпрати вÑички необходими обекти." + +#, c-format +msgid "unable to update %s" +msgstr "обектът „%s“ не може да бъде обновен" + +msgid "failed to initialize sparse-checkout" +msgstr "чаÑтичното изтеглÑне не може да Ñе инициализира" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "" +"указателÑÑ‚ „HEAD“ от отдалеченото хранилище Ñочи към нещо, което не " +"ÑъщеÑтвува. ИзтеглÑне не може да Ñе извърши" + +msgid "unable to checkout working tree" +msgstr "работното дърво не може да бъде подготвено" + +msgid "unable to write parameters to config file" +msgstr "наÑтройките не може да бъдат запиÑани в ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»" + +msgid "cannot repack to clean up" +msgstr "не може да Ñе извърши пакетиране за изчиÑтване на файловете" + +msgid "cannot unlink temporary alternates file" +msgstr "временниÑÑ‚ файл за алтернативни обекти не може да бъде изтрит" msgid "don't clone shallow repository" msgstr "без клониране на плитко хранилище" @@ -4521,6 +4620,9 @@ msgstr "използване на това ИМЕ вмеÑто „origin“ пр msgid "checkout <branch> instead of the remote's HEAD" msgstr "изтеглÑне на този КЛОÐ, а не ÑочениÑÑ‚ от Ð¾Ñ‚Ð´Ð°Ð»ÐµÑ‡ÐµÐ½Ð¸Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ» „HEAD“" +msgid "clone single revision <rev> and check out" +msgstr "клониране на единÑтвена ВЕРСИЯ и изтеглÑне в работната директориÑ" + msgid "path to git-upload-pack on the remote" msgstr "път към командата „git-upload-pack“ на отдалеченото хранилище" @@ -4544,9 +4646,8 @@ msgstr "" "клониране Ñамо на един клон — или ÑÐ¾Ñ‡ÐµÐ½Ð¸Ñ Ð¾Ñ‚ Ð¾Ñ‚Ð´Ð°Ð»ÐµÑ‡ÐµÐ½Ð¸Ñ â€žHEAD“, или изрично " "Ð·Ð°Ð´Ð°Ð´ÐµÐ½Ð¸Ñ Ñ â€ž--branch“" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "" -"без клониране на етикети, като поÑледващите доÑтавÑÐ½Ð¸Ñ Ð½Ñма да ги ÑледÑÑ‚" +msgid "clone tags, and make later fetches not to follow them" +msgstr "клониране на етикети, като поÑледващите доÑтавÑÐ½Ð¸Ñ Ð½Ñма да ги ÑледÑÑ‚" msgid "any cloned submodules will be shallow" msgstr "вÑички клонирани подмодули ще Ñа плитки" @@ -4590,104 +4691,8 @@ msgid "a URI for downloading bundles before fetching from origin remote" msgstr "" "ÐДРЕС за доÑтавÑне на пратки на git преди доÑтавÑне от отдалеченото хранилище" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "" -"ПРЕДУПРЕЖДЕÐИЕ: не може да Ñе добави алтернативен източник на „%s“: %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "не може да бъде получена Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%s“" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "„%s“ ÑъщеÑтвува и не е директориÑ" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "„%s“ е Ñимволна връзка, не може да Ñе клонира Ñ Ð¾Ð¿Ñ†Ð¸Ñта „--local“" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "неуÑпешно итериране по „%s“" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "" -"Ñимволната връзка „%s“ ÑъщеÑтвува, не може да Ñе клонира Ñ Ð¾Ð¿Ñ†Ð¸Ñта „--local“" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "неуÑпешно изтриване на „%s“" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "твърдата връзка не може да Ñе провери при „%s“" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "твърдата връзка е различна от източника „%s“" - -#, c-format -msgid "failed to create link '%s'" -msgstr "връзката „%s“ не може да бъде Ñъздадена" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "файлът не може да бъде копиран като „%s“" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "неуÑпешно итериране по „%s“" - -#, c-format -msgid "done.\n" -msgstr "дейÑтвието завърши.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Клонирането бе уÑпешно за разлика от подготовката на работното дърво\n" -"за определен клон. Ð’Ñе пак може да проверите кои файлове и от кой\n" -"клон в момента Ñа изтеглени Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ñ‚Ð° „git status“. Може да\n" -"завършите изтеглÑнето на клона Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ñ‚Ð°:\n" -"\n" -" git restore --source=HEAD :/\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "" -"Клонът „%s“ от отдалеченото хранилище, което клонирате,\n" -"и който Ñледва да бъде изтеглен, не ÑъщеÑтвува." - -msgid "remote did not send all necessary objects" -msgstr "отдалеченото хранилище не изпрати вÑички необходими обекти." - -#, c-format -msgid "unable to update %s" -msgstr "обектът „%s“ не може да бъде обновен" - -msgid "failed to initialize sparse-checkout" -msgstr "чаÑтичното изтеглÑне не може да Ñе инициализира" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "" -"указателÑÑ‚ „HEAD“ от отдалеченото хранилище Ñочи към нещо, което не " -"ÑъщеÑтвува. ИзтеглÑне не може да Ñе извърши" - -msgid "unable to checkout working tree" -msgstr "работното дърво не може да бъде подготвено" - -msgid "unable to write parameters to config file" -msgstr "наÑтройките не може да бъдат запиÑани в ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»" - -msgid "cannot repack to clean up" -msgstr "не може да Ñе извърши пакетиране за изчиÑтване на файловете" - -msgid "cannot unlink temporary alternates file" -msgstr "временниÑÑ‚ файл за алтернативни обекти не може да бъде изтрит" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [ОПЦИЯ…] [--] ХРÐÐИЛИЩЕ [ДИРЕКТОРИЯ]" msgid "Too many arguments." msgstr "Прекалено много аргументи." @@ -4796,6 +4801,10 @@ msgstr "отдалечениÑÑ‚ транÑпорт върна грешка" msgid "Remote branch %s not found in upstream %s" msgstr "ОтдалечениÑÑ‚ клон „%s“ липÑва в клонираното хранилище „%s“" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Отдалечената верÑÐ¸Ñ â€ž%s“ липÑва в клонираното хранилище „%s“" + msgid "You appear to have cloned an empty repository." msgstr "Изглежда клонирахте празно хранилище." @@ -4975,7 +4984,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: не може да Ñе прочете" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4985,7 +4994,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a|--interactive|--patch] [-s] [-v] [-u РЕЖИМ] [--amend]\n" +"git commit [-a|--interactive|--patch] [-s] [-v] [-u[РЕЖИМ]] [--amend]\n" " [--dry-run] [(-c|-C|--squash) ПОДÐÐ’ÐÐЕ |--fixup [(amend|" "reword):]ПОДÐÐ’ÐÐЕ]\n" " [-F ФÐЙЛ|-m СЪОБЩЕÐИЕ] [--reset-author] [--allow-empty]\n" @@ -6424,8 +6433,8 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Изпълнете\n" "\n" @@ -6435,7 +6444,7 @@ msgstr "" "„remote.%s.followRemoteHEAD, ако не иÑкате тези ÑъобщениÑ.\n" "Изпълнението на\n" "\n" -" git config set remote.%s.followRemoteHEAD %s\n" +" git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s\n" "\n" "ще изключи предупреждението, докато отдалечениÑÑ‚ указател HEAD не\n" "започне да Ñочи нещо друго." @@ -7124,6 +7133,9 @@ msgstr "" msgid "repack all other packs except the largest pack" msgstr "препакетиране на вÑичко без най-Ð³Ð¾Ð»ÐµÐ¼Ð¸Ñ Ð¿Ð°ÐºÐµÑ‚" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "Ð¿Ñ€ÐµÑ„Ð¸ÐºÑ Ð½Ð° имената на пакетите за окаÑтрени обекти" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "неразпозната ÑтойноÑÑ‚ на „gc.logExpiry“ %s" @@ -7944,6 +7956,10 @@ msgid "Cannot come back to cwd" msgstr "ПроцеÑÑŠÑ‚ не може да Ñе върне към предишната работна директориÑ" #, c-format +msgid "bad --pack_header: %s" +msgstr "неправилна ÑтойноÑÑ‚ за „--pack_header“: „%s“" + +#, c-format msgid "bad %s" msgstr "неправилна ÑтойноÑÑ‚ „%s“" @@ -8835,10 +8851,6 @@ msgstr "непозната Ð¾Ð¿Ñ†Ð¸Ñ Ð·Ð° ÑтратегиÑ: -X%s" msgid "malformed input line: '%s'." msgstr "входен ред Ñ Ð½ÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÐµÐ½ формат: „%s“." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "Ñливането не може да продължи — %d-тото завърши Ñ Ð³Ñ€ÐµÑˆÐºÐ°" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [ОПЦИЯ…] [ПОДÐÐ’ÐÐЕ…]" @@ -9685,6 +9697,13 @@ msgstr "" "СПИСЪК_С_ОБЕКТИ]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "неправилна Ð¾Ð¿Ñ†Ð¸Ñ â€ž--name-hash-version“: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "текущо опциÑта „--write-bitmap-index“ изиÑква „--name-hash-version=1“" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -10025,6 +10044,11 @@ msgstr "протокол" msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "без ползване на наÑтройки „uploadpack.blobpackfileuri“ Ñ Ñ‚Ð¾Ð·Ð¸ протокол" +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"използване на указаната Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð·Ð° контролни Ñуми за групиране на подобните " +"обекти" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "веригата Ñ Ñ€Ð°Ð·Ð»Ð¸ÐºÐ¸ е прекалено дълбока — %d, ще Ñе ползва %d" @@ -11304,8 +11328,8 @@ msgstr "не е указан журнал Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð·Ð° изтриРmsgid "invalid ref format: %s" msgstr "неправилен формат на указател: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=ФОРМÐТ [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=ФОРМÐТ [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -11316,6 +11340,9 @@ msgstr "указване на форма̀та за указател, към кРmsgid "perform a non-destructive dry-run" msgstr "пробно изпълнение — без промÑна на данни" +msgid "drop reflogs entirely during the migration" +msgstr "журналът на указателите да Ñе изтрие изцÑло по време на миграциÑта" + msgid "missing --ref-format=<format>" msgstr "липÑва опциÑта --ref-format=ФОРМÐТ" @@ -11786,8 +11813,14 @@ msgstr "Ðикой от адреÑите, които не Ñа за Ð¸Ð·Ñ‚Ð»Ð°Ñ msgid "be verbose; must be placed before a subcommand" msgstr "повече подробноÑти. ПоÑÑ‚Ð°Ð²Ñ Ñе пред подкоманда" -msgid "git repack [<options>]" -msgstr "git repack [ОПЦИЯ…]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=БРОЙ] [--depth=БРОЙ] [--threads=БРОЙ] [--keep-pack=ИМЕ_ÐÐ_ПÐКЕТ]\n" +"[--write-midx] [--name-hash-version=БРОЙ]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11875,6 +11908,11 @@ msgid "pass --no-reuse-object to git-pack-objects" msgstr "" "подаване на опциÑта „--no-reuse-object“ на командата „git-pack-objects“" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"укажете Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð·Ð° контролни Ñуми за групиране на подобните обекти по път" + msgid "do not run git-update-server-info" msgstr "без изпълнение на командата „git-update-server-info“" @@ -11927,9 +11965,6 @@ msgstr "откриване на геометрична прогреÑÐ¸Ñ Ñ Ñ‡Ð msgid "write a multi-pack index of the resulting packs" msgstr "запазване на многопакетен Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° Ñъздадените пакети" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "Ð¿Ñ€ÐµÑ„Ð¸ÐºÑ Ð½Ð° имената на пакетите за окаÑтрени обекти" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "Ð¿Ñ€ÐµÑ„Ð¸ÐºÑ Ð½Ð° имената на пакетите за филтрирани обекти" @@ -12146,9 +12181,6 @@ msgstr "опциÑта „-l“ приема точно един шаблон" msgid "need some commits to replay" msgstr "необходимо е да има Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð·Ð° прилагане отново" -msgid "--onto and --advance are incompatible" -msgstr "опциите „--onto“ и „--advance“ Ñа неÑъвмеÑтими" - msgid "all positive revisions given must be references" msgstr "вÑички зададени положителни верÑии трÑбва да Ñа указатели" @@ -14852,6 +14884,9 @@ msgstr "ВнаÑÑне на хранилище на GNU Arch в Git" msgid "Create an archive of files from a named tree" msgstr "Създаване на архив Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²ÐµÑ‚Ðµ от именовано дърво" +msgid "Download missing objects in a partial clone" +msgstr "ИзтеглÑне на липÑващите обекти в чаÑтично хранилище" + msgid "Use binary search to find the commit that introduced a bug" msgstr "Двоично търÑене на промÑната, коÑто е причинила грешка" @@ -16852,6 +16887,12 @@ msgstr "неправилен аргумент към „%s“" msgid "invalid regex given to -I: '%s'" msgstr "неправилен регулÑрен израз подаден към „-I“: „%s“" +msgid "-G requires a non-empty argument" +msgstr "опциÑта „-G“ изиÑква аргумент" + +msgid "-S requires a non-empty argument" +msgstr "опциÑта „-S“ изиÑква аргумент" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "неразпознат параметър към опциÑта „--submodule“: „%s“" @@ -19123,6 +19164,10 @@ msgid "unable to write file %s" msgstr "файлът „%s“ не може да бъде запиÑан" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "ÑмалÑващиÑÑ‚ Ñе файл „%s“ не може да бъде запиÑван" + +#, c-format msgid "unable to set permission to '%s'" msgstr "права̀та за доÑтъп до „%s“ не може да бъдат зададени" @@ -19722,6 +19767,52 @@ msgstr "непознат флаг „%c“" msgid "unknown non-ascii option in string: `%s'" msgstr "непозната ÑтойноÑÑ‚ извън „ascii“ в низа: „%s“" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=%s]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[%s]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " %s" + msgid "..." msgstr "…" @@ -19809,6 +19900,21 @@ msgid "failed to parse %s" msgstr "„%s“ не може да бъде анализиран" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "неуÑпешно обхождане на дъщерните елементи на дървото „%s“: то липÑва" + +#, c-format +msgid "failed to find object %s" +msgstr "обектът „%s“ липÑва" + +#, c-format +msgid "failed to find tag %s" +msgstr "етикетът „%s“ липÑва" + +msgid "failed to setup revision walk" +msgstr "неуÑпешно наÑтройване на обхождането на верÑиите" + +#, c-format msgid "Could not make %s writable by group" msgstr "Ðе може да Ñе дадат права̀ за Ð·Ð°Ð¿Ð¸Ñ Ð² директориÑта „%s“ на групата" @@ -19957,6 +20063,22 @@ msgstr "" msgid "could not fetch %s from promisor remote" msgstr "„%s“ не може да Ñе доÑтави от гарантиращото хранилище" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "има хранилище Ñ Ð¸Ð¼Ðµ „%s“, но адреÑÑŠÑ‚ му Ñочи към „%s“, а не към „%s“" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "непозната ÑтойноÑÑ‚ „%s“ за наÑтройката „%s“" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "непознат елемент „%s“ в информациÑта за отдалеченото хранилище" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "липÑва приетото вече хранилище-гарант „%s“" + msgid "object-info: expected flush after arguments" msgstr "object-info: Ñлед аргументите Ñе очаква изчиÑтване на буферите" @@ -20803,6 +20925,14 @@ msgid "invalid refspec '%s'" msgstr "неправилен указател: „%s“" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "шаблонът „%s“ не Ñъдържа „*“" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "замеÑтителÑÑ‚ „%s“ не Ñъдържа „*“" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "" "неправилно екраниране или цитиране в ÑтойноÑтта към Ð¾Ð¿Ñ†Ð¸Ñ Ð·Ð° изтлаÑкване: " @@ -20930,6 +21060,28 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: непозната команда „%s“ от git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"изчитането на отдалеченото хранилище от „%s/%s“ предÑтои да бъде " +"премахнато.\n" +"Ðко вÑе още ползвате директориÑта „remotes/“, препоръчваме да Ñ Ð¼Ð¸Ð³Ñ€Ð¸Ñ€Ð°Ñ‚Ðµ\n" +"към ÑледÑщи директории на база наÑтройки чрез командата:\n" +"\n" +" git remote rename %s %s\n" +"\n" +"Ðко не може поради нÑкаква причина, молим да ни извеÑтите за Ð½ÐµÑ Ñ\n" +"е-пиÑмо до пощенÑÐºÐ¸Ñ ÑпиÑък: <git@vger.kernel.org>." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "" "Ñъкращението за отдалечено хранилище не може за започва ÑÑŠÑ Ð·Ð½Ð°ÐºÐ° „/“: %s" @@ -20965,14 +21117,6 @@ msgid "%s tracks both %s and %s" msgstr "„%s“ Ñледи както „%s“, така и „%s“" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "ключ „%s“ на шаблона не Ñъдържа „*“" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "ÑтойноÑÑ‚ „%s“ на шаблона не Ñъдържа „*“" - -#, c-format msgid "src refspec %s does not match any" msgstr "указателÑÑ‚ на верÑиÑ-източник „%s“ не Ñъвпада Ñ Ð½Ð¸ÐºÐ¾Ð¹ обект" @@ -22945,6 +23089,28 @@ msgstr "" "какъв брой запиÑи в кеша на обектите-дървета да Ñе отбележат като невалидни " "(Ñтандартно е 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk ОПЦИЯ… -- ОПЦИЯ_ЗÐ_ВЕРСИИ…" + +msgid "toggle inclusion of blob objects" +msgstr "превключване на помеÑтването на обекти-BLOB" + +msgid "toggle inclusion of commit objects" +msgstr "превключване на помеÑтването на обекти-подаваниÑ" + +msgid "toggle inclusion of tag objects" +msgstr "превключване на помеÑтването на обекти-етикети" + +msgid "toggle inclusion of tree objects" +msgstr "превключване на помеÑтването на обекти-дърво" + +msgid "toggle pruning of uninteresting paths" +msgstr "" +"превключване на окаÑтрÑнето на пътищата, които не предÑтавлÑват интереÑ" + +msgid "read a pattern list over stdin" +msgstr "изчитане на ÑпиÑък Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð¸ от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´" + #, c-format msgid "commit %s is not marked reachable" msgstr "подаването „%s“ не е отбелÑзано като доÑтижимо" @@ -23581,6 +23747,10 @@ msgstr "грешка: " msgid "warning: " msgstr "предупреждение: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "грешка при изпълнението на „uname()“ — „%s“ (%d)\n" + msgid "Fetching objects" msgstr "ДоÑтавÑне на обектите" @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-20 17:44+0100\n" -"PO-Revision-Date: 2024-12-27 16:43+0100\n" +"POT-Creation-Date: 2025-03-06 18:29+0100\n" +"PO-Revision-Date: 2025-03-07 17:28+0100\n" "Last-Translator: Ralf Thielow <ralf.thielow@gmail.com>\n" "Language-Team: German\n" "Language: de\n" @@ -2400,6 +2400,18 @@ msgstr "git archive: Protokollfehler" msgid "git archive: expected a flush" msgstr "git archive: erwartete eine Spülung (flush)" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "Problem beim Laden von sparse-checkout" + +msgid "Minimum number of objects to request at a time" +msgstr "Mindestanzahl der gleichzeitig anzufordernden Objekte" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "fehlenden Objekte im aktuellen sparse-checkout beschränken" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -3167,10 +3179,6 @@ msgstr "" msgid "git version:\n" msgstr "git Version:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() ist fehlgeschlagen mit Fehler '%s' (%d)\n" - msgid "compiler info: " msgstr "Compiler Info: " @@ -4201,8 +4209,95 @@ msgstr "" "clean.requireForce ist 'true' und -f ist nicht angegeben: clean wird " "verweigert" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<Optionen>] [--] <Repository> [<Verzeichnis>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: Konnte Alternative für '%s' nicht hinzufügen: %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "Konnte '%s' nicht lesen" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s existiert und ist kein Verzeichnis" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "" +"'%s' ist eine symbolische Verknüpfung, verweigere das Klonen mit --local" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "Fehler beim Starten der Iteration über '%s'" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "" +"symbolische Verknüpfung '%s' existiert, verweigere das Klonen mit --local" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "Konnte '%s' nicht entfernen." + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "Hardlink bei '%s' kann nicht geprüft werden" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "Hardlink unterscheidet sich von der Quelle bei '%s'" + +#, c-format +msgid "failed to create link '%s'" +msgstr "Konnte Verweis '%s' nicht erstellen" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "Konnte Datei nicht nach '%s' kopieren" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "Fehler beim Iterieren über '%s'" + +#, c-format +msgid "done.\n" +msgstr "Fertig.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Klonen erfolgreich, Auschecken ist aber fehlgeschlagen.\n" +"Sie können mit 'git status' prüfen, was ausgecheckt worden ist\n" +"und das Auschecken mit 'git restore --source=HEAD :/' erneut versuchen.\n" + +msgid "remote did not send all necessary objects" +msgstr "Remote-Repository hat nicht alle erforderlichen Objekte gesendet" + +#, c-format +msgid "unable to update %s" +msgstr "kann %s nicht aktualisieren" + +msgid "failed to initialize sparse-checkout" +msgstr "Fehler beim Initialisieren vom partiellen Checkout." + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "" +"HEAD des Remote-Repositories verweist auf nicht existierende Referenz, kann " +"nicht ausgecheckt werden" + +msgid "unable to checkout working tree" +msgstr "Arbeitsverzeichnis konnte nicht ausgecheckt werden" + +msgid "unable to write parameters to config file" +msgstr "konnte Parameter nicht in Konfigurationsdatei schreiben" + +msgid "cannot repack to clean up" +msgstr "Kann \"repack\" zum Aufräumen nicht aufrufen" + +msgid "cannot unlink temporary alternates file" +msgstr "Kann temporäre \"alternates\"-Datei nicht entfernen" msgid "don't clone shallow repository" msgstr "Repository mit unvollständiger Historie nicht klonen" @@ -4255,6 +4350,9 @@ msgstr "<Name> statt 'origin' für Upstream-Repository verwenden" msgid "checkout <branch> instead of the remote's HEAD" msgstr "<Branch> auschecken, anstatt HEAD des Remote-Repositories" +msgid "clone single revision <rev> and check out" +msgstr "einzelnen Commit <Commit> klonen und auschecken" + msgid "path to git-upload-pack on the remote" msgstr "Pfad zu \"git-upload-pack\" auf der Gegenseite" @@ -4280,8 +4378,8 @@ msgstr "Historie eines flachen Klons vertiefen, Referenz exkludiert" msgid "clone only one branch, HEAD or --branch" msgstr "nur einen Branch klonen, HEAD oder --branch" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "keine Tags klonen, und auch bei späteren Abrufen nicht beachten" +msgid "clone tags, and make later fetches not to follow them" +msgstr "Tags klonen und dafür sorgen, dass spätere Abrufe ihnen nicht folgen" msgid "any cloned submodules will be shallow" msgstr "jedes geklonte Submodul mit unvollständiger Historie (shallow)" @@ -4326,99 +4424,8 @@ msgstr "" "eine URI für das Herunterladen von Bundles vor dem Abruf\n" "aus dem ursprünglichen Remote-Repository" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: Konnte Alternative für '%s' nicht hinzufügen: %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "Konnte '%s' nicht lesen" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s existiert und ist kein Verzeichnis" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "" -"'%s' ist eine symbolische Verknüpfung, verweigere das Klonen mit --local" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "Fehler beim Starten der Iteration über '%s'" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "" -"symbolische Verknüpfung '%s' existiert, verweigere das Klonen mit --local" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "Konnte '%s' nicht entfernen." - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "Hardlink bei '%s' kann nicht geprüft werden" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "Hardlink unterscheidet sich von der Quelle bei '%s'" - -#, c-format -msgid "failed to create link '%s'" -msgstr "Konnte Verweis '%s' nicht erstellen" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "Konnte Datei nicht nach '%s' kopieren" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "Fehler beim Iterieren über '%s'" - -#, c-format -msgid "done.\n" -msgstr "Fertig.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Klonen erfolgreich, Auschecken ist aber fehlgeschlagen.\n" -"Sie können mit 'git status' prüfen, was ausgecheckt worden ist\n" -"und das Auschecken mit 'git restore --source=HEAD :/' erneut versuchen.\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Konnte zu klonenden Remote-Branch %s nicht finden." - -msgid "remote did not send all necessary objects" -msgstr "Remote-Repository hat nicht alle erforderlichen Objekte gesendet" - -#, c-format -msgid "unable to update %s" -msgstr "kann %s nicht aktualisieren" - -msgid "failed to initialize sparse-checkout" -msgstr "Fehler beim Initialisieren vom partiellen Checkout." - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "" -"HEAD des Remote-Repositories verweist auf nicht existierende Referenz, kann " -"nicht ausgecheckt werden" - -msgid "unable to checkout working tree" -msgstr "Arbeitsverzeichnis konnte nicht ausgecheckt werden" - -msgid "unable to write parameters to config file" -msgstr "konnte Parameter nicht in Konfigurationsdatei schreiben" - -msgid "cannot repack to clean up" -msgstr "Kann \"repack\" zum Aufräumen nicht aufrufen" - -msgid "cannot unlink temporary alternates file" -msgstr "Kann temporäre \"alternates\"-Datei nicht entfernen" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<Optionen>] [--] <Repository> [<Verzeichnis>]" msgid "Too many arguments." msgstr "Zu viele Argumente." @@ -4531,6 +4538,10 @@ msgstr "Remoteübertragung meldete Fehler" msgid "Remote branch %s not found in upstream %s" msgstr "Remote-Branch %s nicht im Upstream-Repository %s gefunden" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Remote-Commit %s nicht im Upstream-Repository %s gefunden" + msgid "You appear to have cloned an empty repository." msgstr "Sie scheinen ein leeres Repository geklont zu haben." @@ -4710,7 +4721,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: Fehler beim Lesen" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4720,14 +4731,14 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<Modus>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<Modus>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <Commit> | --fixup [(amend|" "reword):]<Commit>]\n" " [-F <Datei> | -m <Nachricht>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<Autor>]\n" " [--date=<Datum>] [--cleanup=<Modus>] [--[no-]status]\n" " [-i | -o] [--pathspec-from-file=<Datei> [--pathspec-file-nul]]\n" -" [(--trailer <Token>[(=|:)<Wert>])...] [-S[<Key-Id>]]\n" +" [(--trailer <Token>[(=|:)<Wert>])...] [-S[<Key-ID>>]]\n" " [--] [<Pfadspezifikation>...]" msgid "git status [<options>] [--] [<pathspec>...]" @@ -6139,14 +6150,15 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Führen Sie 'git remote set-head %s %s' aus, um der Änderung zu folgen,\n" "oder setzen Sie die Konfiguration 'remote.%s.followRemoteHEAD' auf einen\n" -"anderen Wert, wenn Sie diese Meldung nicht sehen wollen. Konkret wird diese\n" -"Warnung mit 'git config set remote.%s.followRemoteHEAD %s' deaktiviert\n" -"bis die Gegenstelle HEAD in etwas anderes ändert." +"anderen Wert wenn Sie diese Meldung nicht sehen wollen. Speziell der Befehl\n" +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"wird die Warnung deaktivieren, bis das Remote-Repository HEAD in etwas\n" +"anderes ändert." msgid "multiple branches detected, incompatible with --set-upstream" msgstr "mehrere Branches erkannt, inkompatibel mit --set-upstream" @@ -6842,6 +6854,9 @@ msgstr "" msgid "repack all other packs except the largest pack" msgstr "alle anderen Pakete, außer das größte Paket, neu packen" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "pack-Präfix zum Speichern eines Pakets mit gelöschten Objekten" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "Fehler beim Parsen des Wertes '%s' von gc.logExpiry" @@ -7659,6 +7674,10 @@ msgid "Cannot come back to cwd" msgstr "Kann nicht zurück zum Arbeitsverzeichnis wechseln" #, c-format +msgid "bad --pack_header: %s" +msgstr "ungültiger --pack_header: %s" + +#, c-format msgid "bad %s" msgstr "%s ist ungültig" @@ -8537,11 +8556,6 @@ msgstr "unbekannte Strategie-Option: -X%s" msgid "malformed input line: '%s'." msgstr "Fehlerhafte Eingabezeile: '%s'." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "" -"Merge kann nicht fortgesetzt werden; unsauberes Ergebnis von %d erhalten" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<Optionen>] [<Commit>...]" @@ -9382,6 +9396,13 @@ msgstr "" "<Objektliste>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "ungültige Option für --name-hash-version: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "derzeit erfordert --write-bitmap-index --name-hash-version=1" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9718,6 +9739,11 @@ msgstr "" "jegliche konfigurierte uploadpack.blobpackfileuri für dieses Protkoll " "ausschließen" +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"die angegebene Name-Hash-Funktion verwenden, um ähnliche Objekte zu " +"gruppieren" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "Tiefe für Verkettung von Unterschieden %d ist zu tief, erzwinge %d" @@ -11006,8 +11032,8 @@ msgstr "Kein Reflog zum Löschen angegeben." msgid "invalid ref format: %s" msgstr "Ungültiges Format für Referenzen: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<Format> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<Format> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -11018,6 +11044,9 @@ msgstr "das Referenzformat angeben, in das konvertiert werden soll" msgid "perform a non-destructive dry-run" msgstr "einen zerstörungsfreien Trockenlauf durchführen" +msgid "drop reflogs entirely during the migration" +msgstr "Reflogs während der Migration vollständig zu löschen" + msgid "missing --ref-format=<format>" msgstr "fehlendes --ref-format=<Format>" @@ -11488,8 +11517,14 @@ msgstr "Werde keine URLs entfernen, die nicht für \"push\" bestimmt sind" msgid "be verbose; must be placed before a subcommand" msgstr "erweiterte Ausgaben; muss vor einem Unterbefehl angegeben werden" -msgid "git repack [<options>]" -msgstr "git repack [<Optionen>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<Paketname>]\n" +"[--write-midx] [--name-hash-version=<n>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11568,6 +11603,12 @@ msgstr "--no-reuse-delta an git-pack-objects übergeben" msgid "pass --no-reuse-object to git-pack-objects" msgstr "--no-reuse-object an git-pack-objects übergeben" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"die Version des Hash-Namens angeben, die für die Gruppierung ähnlicher " +"Objekte nach Pfad verwendet werden soll" + msgid "do not run git-update-server-info" msgstr "git-update-server-info nicht ausführen" @@ -11619,9 +11660,6 @@ msgstr "eine geometrische Progression mit Faktor <N> finden" msgid "write a multi-pack index of the resulting packs" msgstr "ein Multi-Pack-Index des resultierenden Pakets schreiben" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "pack-Präfix zum Speichern eines Pakets mit gelöschten Objekten" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "Paketpräfix, um ein Paket mit herausgefilterten Objekten zu speichern" @@ -11839,9 +11877,6 @@ msgstr "Mit -l kann nur ein Muster angegeben werden" msgid "need some commits to replay" msgstr "zum erneuten Abspielen werden Commits benötigt" -msgid "--onto and --advance are incompatible" -msgstr "--onto und --advance sind inkompatibel" - msgid "all positive revisions given must be references" msgstr "alle angegebenen positiven Commits müssen Referenzen sein" @@ -14571,6 +14606,9 @@ msgstr "ein GNU Arch Repository in Git importieren" msgid "Create an archive of files from a named tree" msgstr "Dateiarchiv von angegebenem Verzeichnis erstellen" +msgid "Download missing objects in a partial clone" +msgstr "fehlender Objekte in einem partiellen Klon herunterladen" + msgid "Use binary search to find the commit that introduced a bug" msgstr "" "Binärsuche verwenden, um den Commit zu finden, der einen Fehler verursacht " @@ -16543,6 +16581,12 @@ msgstr "ungültiges Argument für %s" msgid "invalid regex given to -I: '%s'" msgstr "ungültiger regulärer Ausdruck für -I gegeben: '%s'" +msgid "-G requires a non-empty argument" +msgstr "-G erfordert ein nicht leeres Argument" + +msgid "-S requires a non-empty argument" +msgstr "-S erfordert ein nicht leeres Argument" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "Fehler beim Parsen des --submodule Optionsparameters: '%s'" @@ -18782,6 +18826,10 @@ msgid "unable to write file %s" msgstr "Konnte Datei %s nicht schreiben." #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "konnte nicht in eine wiederholt verschwindende Datei %s schreiben" + +#, c-format msgid "unable to set permission to '%s'" msgstr "Konnte Zugriffsberechtigung auf '%s' nicht setzen." @@ -19355,6 +19403,52 @@ msgstr "Unbekannter Schalter `%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "Unbekannte nicht-Ascii Option in String: `%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -19442,6 +19536,21 @@ msgid "failed to parse %s" msgstr "Fehler beim Parsen von %s." #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "Fehlen beim Durchlaufen der Kinder von Baum %s: nicht gefunden" + +#, c-format +msgid "failed to find object %s" +msgstr "Objekt nicht gefunden: %s" + +#, c-format +msgid "failed to find tag %s" +msgstr "Tag nicht gefunden: %s" + +msgid "failed to setup revision walk" +msgstr "Einrichtung des Revisionsgangs fehlgeschlagen" + +#, c-format msgid "Could not make %s writable by group" msgstr "Konnte Gruppenschreibrecht für %s nicht setzen." @@ -19591,6 +19700,25 @@ msgstr "Promisor-Remote-Name kann nicht mit '/' beginnen: %s" msgid "could not fetch %s from promisor remote" msgstr "konnte %s nicht von Promisor-Remote abrufen" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "" +"bekanntes Remote-Repository mit dem Namen '%s', aber mit der URL '%s' statt " +"'%s'" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "unbekannter '%s'-Wert für '%s'-Konfigurationsoption" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "unbekanntes Element '%s' aus Information aus Remote-Repository" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "" +"akzeptiertes partiell geklontes \"Remote-Repository '%s' nicht gefunden" + msgid "object-info: expected flush after arguments" msgstr "object-info: erwartete Flush nach Argumenten" @@ -20428,6 +20556,14 @@ msgid "invalid refspec '%s'" msgstr "ungültige Refspec '%s'" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "Muster '%s' hat keinen '*'" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "Ersetzung '%s' hat keinen '*'" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "Ungültiges Quoting beim \"push-option\"-Wert: '%s'" @@ -20550,6 +20686,28 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: Unbekannter Befehl '%s' von Git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"Lese von Remote-Repository \"%s/%s\", das zum Entfernen vorgeschlagen wird.\n" +"\n" +"Wenn Sie noch das Verzeichnis \"remotes/\" verwenden, wird empfohlen\n" +"auf konfigurationsbasierte Remote-Repositories umzusteigen:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"Wenn dies nicht möglich ist, teilen Sie uns bitte mit, warum Sie das noch\n" +"verwenden müssen, indem Sie eine E-Mail an <git@vger.kernel.org> senden." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "" "Kürzel für Remote-Repository in der Konfiguration kann nicht mit '/' " @@ -20586,14 +20744,6 @@ msgid "%s tracks both %s and %s" msgstr "%s folgt sowohl %s als auch %s" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "Schlüssel '%s' des Musters hatte kein '*'." - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "Wert '%s' des Musters hat kein '*'." - -#, c-format msgid "src refspec %s does not match any" msgstr "Src-Refspec %s entspricht keiner Referenz." @@ -22519,6 +22669,27 @@ msgstr "" "Anzahl der Einträge im Cache-Verzeichnis, die ungültig gemacht werden sollen " "(Standardwert 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <Optionen> -- <Commit-Optionen>" + +msgid "toggle inclusion of blob objects" +msgstr "Einbeziehung von Blob-Objekten umschalten" + +msgid "toggle inclusion of commit objects" +msgstr "Einbeziehung von Commit-Objekten umschalten" + +msgid "toggle inclusion of tag objects" +msgstr "Einbeziehung von Tag-Objekten umschalten" + +msgid "toggle inclusion of tree objects" +msgstr "Einbeziehung von Tree-Objekten umschalten" + +msgid "toggle pruning of uninteresting paths" +msgstr "Auslassen von uninteressanten Pfaden umschalten" + +msgid "read a pattern list over stdin" +msgstr "Liste von Mustern von der Standard-Eingabe lesen" + #, c-format msgid "commit %s is not marked reachable" msgstr "Commit %s ist nicht als erreichbar gekennzeichnet." @@ -23168,6 +23339,10 @@ msgstr "Fehler: " msgid "warning: " msgstr "Warnung: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() ist fehlgeschlagen mit Fehler '%s' (%d)\n" + msgid "Fetching objects" msgstr "Anfordern der Objekte" @@ -24190,7 +24365,3 @@ msgstr "Lasse %s mit Backup-Suffix '%s' aus.\n" #, perl-format msgid "Do you really want to send %s? [y|N]: " msgstr "Wollen Sie %s wirklich versenden? [y|N]: " - -#, c-format -#~ msgid "preferred pack (%s) is invalid" -#~ msgstr "bevorzugtes Paket (%s) ist ungültig" @@ -87,8 +87,8 @@ msgid "" msgstr "" "Project-Id-Version: git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-23 18:57+0000\n" -"PO-Revision-Date: 2024-12-29 18:26+0100\n" +"POT-Creation-Date: 2025-03-05 22:57+0000\n" +"PO-Revision-Date: 2025-03-06 16:46+0100\n" "Last-Translator: Cédric Malard <c.malard-git@valdun.net>\n" "Language-Team: Jean-Noël Avila <jn.avila@free.fr>\n" "Language: fr\n" @@ -2452,6 +2452,18 @@ msgstr "git archive : erreur de protocole" msgid "git archive: expected a flush" msgstr "git archive : vidage attendu" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "problème lors du chargement de l'extraction clairsemée" + +msgid "Minimum number of objects to request at a time" +msgstr "Nombre minimum d'objets à demander à chaque fois" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Restreindre les objets manquants à l'extraction clairsemée actuelle" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -3217,10 +3229,6 @@ msgstr "" msgid "git version:\n" msgstr "version git ::\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "échec de uname() avec l'erreur '%s' (%d)\n" - msgid "compiler info: " msgstr "info compilateur : " @@ -4243,8 +4251,93 @@ msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" "clean.requireForce positionné est true et -f non fourni ; refus de nettoyer" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<options>] [--] <dépôt> [<répertoire>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info : impossible d'ajouter une alternative pour '%s' : %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "échec du stat de '%s'" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s existe et n'est pas un répertoire" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' est un lien symbolique, refus de cloner avec --local" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "échec du démarrage un itérateur sur '%s'" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "le lien symbolique '%s' existe, refus de cloner avec --local" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "échec pour délier '%s'" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "le lien dur ne peut pas être vérifié à '%s'" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "le lien dur est différent de la source à '%s'" + +#, c-format +msgid "failed to create link '%s'" +msgstr "échec de la création du lien '%s'" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "échec de la copie vers '%s'" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "échec de l'itération sur '%s'" + +#, c-format +msgid "done.\n" +msgstr "fait.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Le clone a réussi, mais l'extraction a échoué.\n" +"Vous pouvez inspecter ce qui a été extrait avec 'git status'\n" +"et réessayer avec 'git restore --source=HEAD :/'\n" + +msgid "remote did not send all necessary objects" +msgstr "le serveur distant n'a pas envoyé tous les objets nécessaires" + +#, c-format +msgid "unable to update %s" +msgstr "impossible de mettre à jour %s" + +msgid "failed to initialize sparse-checkout" +msgstr "échec lors de l'initialisation l'extraction clairsemée" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "" +"la HEAD distante réfère à une référence non existante, impossible de " +"l'extraire" + +msgid "unable to checkout working tree" +msgstr "impossible d'extraire la copie de travail" + +msgid "unable to write parameters to config file" +msgstr "impossible d'écrire les paramètres dans le fichier de configuration" + +msgid "cannot repack to clean up" +msgstr "impossible de remballer pour nettoyer" + +msgid "cannot unlink temporary alternates file" +msgstr "impossible de délier le fichier temporaire alternates" msgid "don't clone shallow repository" msgstr "ne pas cloner un dépôt superficiel" @@ -4297,6 +4390,9 @@ msgstr "utiliser <nom> au lieu de 'origin' pour suivre la branche amont" msgid "checkout <branch> instead of the remote's HEAD" msgstr "extraire <branche> au lieu de la HEAD du répertoire distant" +msgid "clone single revision <rev> and check out" +msgstr "cloner la révision unique <rév> et l'extraire" + msgid "path to git-upload-pack on the remote" msgstr "chemin vers git-upload-pack sur le serveur distant" @@ -4318,10 +4414,9 @@ msgstr "approfondit l'historique d'un clone superficiel en excluant une ref" msgid "clone only one branch, HEAD or --branch" msgstr "cloner seulement une branche, HEAD ou --branch" -msgid "don't clone any tags, and make later fetches not to follow them" +msgid "clone tags, and make later fetches not to follow them" msgstr "" -"ne pas cloner les tags et indiquer aux récupérations futures de ne pas le " -"faire" +"cloner les tags et indiquer aux récupérations futures de ne pas le faire" msgid "any cloned submodules will be shallow" msgstr "tous les sous-modules clonés seront superficiels" @@ -4367,97 +4462,8 @@ msgstr "" "un URI pour télécharger des paquets avant de récupérer depuis le distant " "d'origine" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info : impossible d'ajouter une alternative pour '%s' : %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "échec du stat de '%s'" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s existe et n'est pas un répertoire" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' est un lien symbolique, refus de cloner avec --local" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "échec du démarrage un itérateur sur '%s'" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "le lien symbolique '%s' existe, refus de cloner avec --local" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "échec pour délier '%s'" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "le lien dur ne peut pas être vérifié à '%s'" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "le lien dur est différent de la source à '%s'" - -#, c-format -msgid "failed to create link '%s'" -msgstr "échec de la création du lien '%s'" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "échec de la copie vers '%s'" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "échec de l'itération sur '%s'" - -#, c-format -msgid "done.\n" -msgstr "fait.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Le clone a réussi, mais l'extraction a échoué.\n" -"Vous pouvez inspecter ce qui a été extrait avec 'git status'\n" -"et réessayer avec 'git restore --source=HEAD :/'\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Impossible de trouver la branche distante '%s' à cloner." - -msgid "remote did not send all necessary objects" -msgstr "le serveur distant n'a pas envoyé tous les objets nécessaires" - -#, c-format -msgid "unable to update %s" -msgstr "impossible de mettre à jour %s" - -msgid "failed to initialize sparse-checkout" -msgstr "échec lors de l'initialisation l'extraction clairsemée" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "" -"la HEAD distante réfère à une référence non existante, impossible de " -"l'extraire" - -msgid "unable to checkout working tree" -msgstr "impossible d'extraire la copie de travail" - -msgid "unable to write parameters to config file" -msgstr "impossible d'écrire les paramètres dans le fichier de configuration" - -msgid "cannot repack to clean up" -msgstr "impossible de remballer pour nettoyer" - -msgid "cannot unlink temporary alternates file" -msgstr "impossible de délier le fichier temporaire alternates" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<options>] [--] <dépôt> [<répertoire>]" msgid "Too many arguments." msgstr "Trop d'arguments." @@ -4563,6 +4569,10 @@ msgstr "le transport distant a retourné une erreur" msgid "Remote branch %s not found in upstream %s" msgstr "La branche distante %s n'a pas été trouvée dans le dépôt amont %s" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "La révision distante %s n'a pas été trouvée dans le dépôt amont %s" + msgid "You appear to have cloned an empty repository." msgstr "Vous semblez avoir cloné un dépôt vide." @@ -4737,7 +4747,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree : échec de la lecture" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4747,14 +4757,14 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" -"reword):]<commit>)]\n" +"reword):]<commit>]\n" " [-F <fichier> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<auteur>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" " [-i | -o] [--pathspec-from-file=<fichier> [--pathspec-file-nul]]\n" -" [(--trailer <symbole>[(=|:)<valeur>])...] [-S[<id-clé>]]\n" +" [(--trailer <jeton>[(=|:)<valeur>])...] [-S[<id-clé>]]\n" " [--] [<spéc-de-chemin>...]" msgid "git status [<options>] [--] [<pathspec>...]" @@ -6168,13 +6178,14 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Lancez 'git remote set-head %s %s' pour suivre la modification, ou\n" "réglez l'option de configuration 'remote.%s.followRemoteHEAD' à une\n" "valeur différente si vous ne souhaitez pas voir ce message. Lancer\n" -"spécifiquement 'git config set remote.%s.followRemoteHEAD %s'\n" +"spécifiquement 'git config set remote.%s.followRemoteHEAD warn-if-not-branch-" +"%s'\n" "va désactiver l'alerte jusqu'à ce que le distant change HEAD." msgid "multiple branches detected, incompatible with --set-upstream" @@ -6860,6 +6871,9 @@ msgstr "" msgid "repack all other packs except the largest pack" msgstr "recompacter tous les autres paquets excepté le plus gros paquet" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "préfixe de paquet pour stocker un paquet contenant les objets élagués" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "impossible d'analyser gc.logExpiry %s" @@ -7674,6 +7688,10 @@ msgid "Cannot come back to cwd" msgstr "Impossible de revenir au répertoire de travail courant" #, c-format +msgid "bad --pack_header: %s" +msgstr "mauvais --pack_header : %s" + +#, c-format msgid "bad %s" msgstr "mauvais %s" @@ -8561,10 +8579,6 @@ msgstr "option de stratégie inconnue : -X%s" msgid "malformed input line: '%s'." msgstr "ligne en entrée malformée : '%s'." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "la fusion ne peut pas continuer ; résultat non propre retourné %d" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<options>] [<commit>...]" @@ -9398,6 +9412,13 @@ msgstr "" "objets>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "option --name-hash-version invalide : %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "actuellement, --write-bitmap-index nécessite --name-hash-version=1" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9730,6 +9751,11 @@ msgstr "protocole" msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "exclure tout uploadpack.blobpackfileuri configuré avec ce protocole" +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"utiliser la fonction d'empreinte de nom spécifiée pour grouper les objets " +"similaires" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "la profondeur %d de chaîne de delta est trop grande, forcée à %d" @@ -10992,8 +11018,8 @@ msgstr "pas de journal de références à supprimer spécifié" msgid "invalid ref format: %s" msgstr "format de référence invalide : %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<format> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -11004,6 +11030,9 @@ msgstr "spécifier le format de réference vers lequel convertir" msgid "perform a non-destructive dry-run" msgstr "faire l'action en mode simulé non destructif" +msgid "drop reflogs entirely during the migration" +msgstr "abandonner complètement le reflog pendant la migration" + msgid "missing --ref-format=<format>" msgstr "--ref-format=<format> manquant" @@ -11475,8 +11504,14 @@ msgstr "Pas de suppression de toutes les URLs non-push" msgid "be verbose; must be placed before a subcommand" msgstr "être verbeux : doit être placé avant une sous-commande" -msgid "git repack [<options>]" -msgstr "git repack [<options>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<nom-de-paquet>]\n" +"[--write-midx] [--name-hash-version=<n>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11557,6 +11592,12 @@ msgstr "passer --no-reuse-delta à git-pack-objects" msgid "pass --no-reuse-object to git-pack-objects" msgstr "passer --no-reuse-object à git-pack-objects" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"spécifier la verison d'empreinte de nom à utiliser pour grouper les objets " +"similaires par chemin" + msgid "do not run git-update-server-info" msgstr "ne pas lancer git-update-server-info" @@ -11606,9 +11647,6 @@ msgstr "trouver une progression géométrique avec un facteur <N>" msgid "write a multi-pack index of the resulting packs" msgstr "écrire un index de multi-paquet des paquets résultants" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "préfixe de paquet pour stocker un paquet contenant les objets élagués" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "préfixe de paquet pour stocker un paquet contenant les objets filtrés" @@ -11825,9 +11863,6 @@ msgstr "-l n'accepte qu'un motifs" msgid "need some commits to replay" msgstr "commits requis pour pouvoir rejouer" -msgid "--onto and --advance are incompatible" -msgstr "--onto et --advance sont incompatibles" - msgid "all positive revisions given must be references" msgstr "toutes les révisions positives fournies doivent être des références" @@ -14539,6 +14574,9 @@ msgstr "Importer dans Git un dépôt GNU Arch" msgid "Create an archive of files from a named tree" msgstr "Créer une archive des fichiers depuis un arbre nommé" +msgid "Download missing objects in a partial clone" +msgstr "Télécharger les objets manquants dans un clone partiel" + msgid "Use binary search to find the commit that introduced a bug" msgstr "Trouver par recherche binaire la modification qui a introduit un bogue" @@ -16531,6 +16569,12 @@ msgstr "argument invalide pour %s" msgid "invalid regex given to -I: '%s'" msgstr "regex invalide fournie à -I : '%s'" +msgid "-G requires a non-empty argument" +msgstr "-G exige un argument non vide" + +msgid "-S requires a non-empty argument" +msgstr "-S exige un argument non vide" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "échec de l'analyse du paramètre de l'option --submodule : '%s'" @@ -18767,6 +18811,10 @@ msgid "unable to write file %s" msgstr "impossible d'écrire le fichier %s" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "impossible d'écrire le fichier %s qui disparaît répétitivement" + +#, c-format msgid "unable to set permission to '%s'" msgstr "impossible de régler les droits de '%s'" @@ -19338,6 +19386,52 @@ msgstr "bascule inconnue « %c »" msgid "unknown non-ascii option in string: `%s'" msgstr "option non-ascii inconnue dans la chaîne : '%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -19425,6 +19519,21 @@ msgid "failed to parse %s" msgstr "échec de l'analyse de %s" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "échec de parcours des enfants de l'arbre %s : non trouvé" + +#, c-format +msgid "failed to find object %s" +msgstr "échec de la recherche de l'objet %s" + +#, c-format +msgid "failed to find tag %s" +msgstr "impossible de trouver l'étiquette %s" + +msgid "failed to setup revision walk" +msgstr "impossible définir un parcours de révisions" + +#, c-format msgid "Could not make %s writable by group" msgstr "Impossible de rendre %s inscriptible pour le groupe" @@ -19581,6 +19690,22 @@ msgstr "un nom de prometteur distant ne peut pas commencer par '/' : %s" msgid "could not fetch %s from promisor remote" msgstr "impossible de récupérer %s depuis le distant de prometteur" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "distant connu nommé '%s' mais avec l'url '%s' au lieu de '%s'" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "valeur inconnue '%s' pour l'option de config '%s'" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "élément inconnu '%s' pour l'info de distant" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "distant accpté de prometteur '%s' non trouvé" + msgid "object-info: expected flush after arguments" msgstr "object-info : vidage attendu après les arguments" @@ -20418,6 +20543,14 @@ msgid "invalid refspec '%s'" msgstr "spécificateur de réference invalide : '%s'" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "la valeur '%s' du motif n'a pas de '*'" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "le remplacement '%s' n'a pas de '*'" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "citation invalide dans la valeur push-option : '%s'" @@ -20539,6 +20672,28 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl : commande inconnue '%s' depuis git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"lecture depuis \"%s/%s\", dont la suppression est programmée.\n" +"\n" +"Si vous utilisez encore le répertoire \"remotes\", il est recommandé de\n" +"migrer vers une gestion à base de configuration :\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"S'il vous est impossible de migrer, veuillez nous avertir par\n" +"un courriel à <git@vger.kernel.org>." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "" "un raccourci de configuration de distant ne peut pas commencer par '/' : %s" @@ -20574,14 +20729,6 @@ msgid "%s tracks both %s and %s" msgstr "%s suit à la fois %s et %s" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "la clé '%s' du modèle n'a pas de '*'" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "la valeur '%s' du modèle n'a pas de '*'" - -#, c-format msgid "src refspec %s does not match any" msgstr "" "le spécificateur de référence source %s ne correspond à aucune référence" @@ -22505,6 +22652,27 @@ msgstr "effacer l'arbre de cache avant chaque itération" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "nombre d'entrées dans l'arbre de cache à invalider (par défaut, 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <options> -- <options-de-révision>" + +msgid "toggle inclusion of blob objects" +msgstr "activer l'inclusion des objets blob" + +msgid "toggle inclusion of commit objects" +msgstr "activer l'inclusion des objets commit" + +msgid "toggle inclusion of tag objects" +msgstr "activer l'inclusion des objets étiquette" + +msgid "toggle inclusion of tree objects" +msgstr "activer l'inclusion des objets arbre" + +msgid "toggle pruning of uninteresting paths" +msgstr "activer l'élagage des chemins inintéressants" + +msgid "read a pattern list over stdin" +msgstr "lire les motifs depuis stdin" + #, c-format msgid "commit %s is not marked reachable" msgstr "le commit %s n'est pas marqué joignable" @@ -23151,6 +23319,10 @@ msgstr "erreur : " msgid "warning: " msgstr "avertissement : " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "échec de uname() avec l'erreur '%s' (%d)\n" + msgid "Fetching objects" msgstr "Récupération des objets" @@ -24128,5 +24300,23 @@ msgid "Do you really want to send %s? [y|N]: " msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : " #, c-format +#~ msgid "Could not find remote branch %s to clone." +#~ msgstr "Impossible de trouver la branche distante '%s' à cloner." + +#, c-format +#~ msgid "merging cannot continue; got unclean result of %d" +#~ msgstr "la fusion ne peut pas continuer ; résultat non propre retourné %d" + +#~ msgid "git repack [<options>]" +#~ msgstr "git repack [<options>]" + +#~ msgid "--onto and --advance are incompatible" +#~ msgstr "--onto et --advance sont incompatibles" + +#, c-format +#~ msgid "key '%s' of pattern had no '*'" +#~ msgstr "la clé '%s' du modèle n'a pas de '*'" + +#, c-format #~ msgid "preferred pack (%s) is invalid" #~ msgstr "le paquet préféré (%s) est invalide" @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-23 18:57+0000\n" -"PO-Revision-Date: 2025-01-06 15:50+0700\n" +"POT-Creation-Date: 2025-03-05 22:57+0000\n" +"PO-Revision-Date: 2025-03-09 17:44+0700\n" "Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n" "Language-Team: Indonesian\n" "Language: id\n" @@ -2890,6 +2890,22 @@ msgstr "git archive: kesalahan protokol" msgid "git archive: expected a flush" msgstr "git archive: sebuah bilasan diharapkan" +#: builtin/backfill.c +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +#: builtin/backfill.c +msgid "problem loading sparse-checkout" +msgstr "galat memuat sparse-checkout" + +#: builtin/backfill.c +msgid "Minimum number of objects to request at a time" +msgstr "Jumlah objek minum yang diminta pada suatu waktu" + +#: builtin/backfill.c +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Batasi objek yang hilang ke sparse-checkout saat ini" + #: builtin/bisect.c msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" @@ -3312,7 +3328,7 @@ msgstr "perlihatkan email pengarang daripada nama (asali: off)" msgid "ignore whitespace differences" msgstr "abaikan perbedaan spasi putih" -#: builtin/blame.c builtin/log.c +#: builtin/blame.c builtin/clone.c builtin/log.c msgid "rev" msgstr "revisi" @@ -3829,11 +3845,6 @@ msgid "git version:\n" msgstr "versi git:\n" #: builtin/bugreport.c -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() gagal dengan kesalahan '%s' (%d)\n" - -#: builtin/bugreport.c msgid "compiler info: " msgstr "info pengompilasi: " @@ -5090,8 +5101,112 @@ msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "clean.requireForce 'true' dan -f tidak diberikan: menolak membersihkan" #: builtin/clone.c -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<opsi>] [--] <repo> [<direktori>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: Tidak dapat menambahkan alternatif untuk '%s': %s\n" + +#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c +#, c-format +msgid "failed to stat '%s'" +msgstr "gagal men-stat '%s'" + +#: builtin/clone.c +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s ada dan bukan direktori" + +#: builtin/clone.c +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' tautan simbolik, menolak mengkloning dengan --local" + +#: builtin/clone.c +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "gagal memulai iterator pada '%s'" + +#: builtin/clone.c +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "tautan simbolik '%s' ada, menolak mengkloning dengan --local" + +#: builtin/clone.c compat/precompose_utf8.c +#, c-format +msgid "failed to unlink '%s'" +msgstr "gagal menghapus tautan '%s'" + +#: builtin/clone.c +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "tautan keras tidak dapat diperiksa pada '%s'" + +#: builtin/clone.c +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "tautan keras berbeda dari sumber pada '%s'" + +#: builtin/clone.c +#, c-format +msgid "failed to create link '%s'" +msgstr "gagal membuat tautan '%s'" + +#: builtin/clone.c +#, c-format +msgid "failed to copy file to '%s'" +msgstr "gagal menyalin berkas ke '%s'" + +#: builtin/clone.c refs/files-backend.c +#, c-format +msgid "failed to iterate over '%s'" +msgstr "gagal iterasi pada '%s'" + +#: builtin/clone.c +#, c-format +msgid "done.\n" +msgstr "selesai.\n" + +#: builtin/clone.c +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Klon sukses, tapi checkout gagal.\n" +"Anda dapat periksa apa yang dicheckout dengan 'git status'\n" +"dan coba lagi dengan 'git restore --source=HEAD :/'\n" + +#: builtin/clone.c fetch-pack.c +msgid "remote did not send all necessary objects" +msgstr "remote tidak mengirim semua objek yang dibutuhkan" + +#: builtin/clone.c +#, c-format +msgid "unable to update %s" +msgstr "tidak dapat memperbarui %s" + +#: builtin/clone.c +msgid "failed to initialize sparse-checkout" +msgstr "gagal menginisalisasi checkout tipis" + +#: builtin/clone.c +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "HEAD remote merujuk pada ref yang tidak ada, tidak dapat men-checkout" + +#: builtin/clone.c +msgid "unable to checkout working tree" +msgstr "tidak dapat men-checkout pohon kerja" + +#: builtin/clone.c +msgid "unable to write parameters to config file" +msgstr "tidak dapat menulis parameter ke berkas konfigurasi" + +#: builtin/clone.c +msgid "cannot repack to clean up" +msgstr "tidak dapat memaket ulang untuk pembersihan" + +#: builtin/clone.c +msgid "cannot unlink temporary alternates file" +msgstr "tidak dapat batal-taut berkas alternatif sementara" #: builtin/clone.c msgid "don't clone shallow repository" @@ -5164,6 +5279,10 @@ msgid "checkout <branch> instead of the remote's HEAD" msgstr "checkout <cabang> daripada HEAD remote" #: builtin/clone.c +msgid "clone single revision <rev> and check out" +msgstr "klon satu revisi <revisi> dan check out" + +#: builtin/clone.c msgid "path to git-upload-pack on the remote" msgstr "jalur ke git-upload-pack pada remote" @@ -5192,8 +5311,8 @@ msgid "clone only one branch, HEAD or --branch" msgstr "klon hanya satu cabang, HEAD atau --branch" #: builtin/clone.c -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "jangan klon tag apapun, dan buat pengambilan nanti tidak mengikutinya" +msgid "clone tags, and make later fetches not to follow them" +msgstr "klon tag dan jangan ikuti mereka pada pengambilan berikutnya" #: builtin/clone.c msgid "any cloned submodules will be shallow" @@ -5251,117 +5370,8 @@ msgid "a URI for downloading bundles before fetching from origin remote" msgstr "sebuah URI untuk mengunduh bundel sebelum mengambil dari remote asal" #: builtin/clone.c -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: Tidak dapat menambahkan alternatif untuk '%s': %s\n" - -#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c -#, c-format -msgid "failed to stat '%s'" -msgstr "gagal men-stat '%s'" - -#: builtin/clone.c -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s ada dan bukan direktori" - -#: builtin/clone.c -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' tautan simbolik, menolak mengkloning dengan --local" - -#: builtin/clone.c -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "gagal memulai iterator pada '%s'" - -#: builtin/clone.c -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "tautan simbolik '%s' ada, menolak mengkloning dengan --local" - -#: builtin/clone.c compat/precompose_utf8.c -#, c-format -msgid "failed to unlink '%s'" -msgstr "gagal menghapus tautan '%s'" - -#: builtin/clone.c -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "tautan keras tidak dapat diperiksa pada '%s'" - -#: builtin/clone.c -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "tautan keras berbeda dari sumber pada '%s'" - -#: builtin/clone.c -#, c-format -msgid "failed to create link '%s'" -msgstr "gagal membuat tautan '%s'" - -#: builtin/clone.c -#, c-format -msgid "failed to copy file to '%s'" -msgstr "gagal menyalin berkas ke '%s'" - -#: builtin/clone.c refs/files-backend.c -#, c-format -msgid "failed to iterate over '%s'" -msgstr "gagal iterasi pada '%s'" - -#: builtin/clone.c -#, c-format -msgid "done.\n" -msgstr "selesai.\n" - -#: builtin/clone.c -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Klon sukses, tapi checkout gagal.\n" -"Anda dapat periksa apa yang dicheckout dengan 'git status'\n" -"dan coba lagi dengan 'git restore --source=HEAD :/'\n" - -#: builtin/clone.c -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Tidak dapat menemukan cabang remote %s untuk diklon." - -#: builtin/clone.c fetch-pack.c -msgid "remote did not send all necessary objects" -msgstr "remote tidak mengirim semua objek yang dibutuhkan" - -#: builtin/clone.c -#, c-format -msgid "unable to update %s" -msgstr "tidak dapat memperbarui %s" - -#: builtin/clone.c -msgid "failed to initialize sparse-checkout" -msgstr "gagal menginisalisasi checkout tipis" - -#: builtin/clone.c -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "HEAD remote merujuk pada ref yang tidak ada, tidak dapat men-checkout" - -#: builtin/clone.c -msgid "unable to checkout working tree" -msgstr "tidak dapat men-checkout pohon kerja" - -#: builtin/clone.c -msgid "unable to write parameters to config file" -msgstr "tidak dapat menulis parameter ke berkas konfigurasi" - -#: builtin/clone.c -msgid "cannot repack to clean up" -msgstr "tidak dapat memaket ulang untuk pembersihan" - -#: builtin/clone.c -msgid "cannot unlink temporary alternates file" -msgstr "tidak dapat batal-taut berkas alternatif sementara" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<opsi>] [--] <repo> [<direktori>]" #: builtin/clone.c msgid "Too many arguments." @@ -5492,6 +5502,11 @@ msgid "Remote branch %s not found in upstream %s" msgstr "Cabang remote %s tidak ditemukan di hulu %s" #: builtin/clone.c +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Revisi remote %s tidak ditemukan di hulu %s" + +#: builtin/clone.c msgid "You appear to have cloned an empty repository." msgstr "Anda tampaknya mengklon repositori kosong." @@ -5555,7 +5570,8 @@ msgstr "" "[no-]progress]\n" " <opsi pemisahan>" -#: builtin/commit-graph.c builtin/fetch.c builtin/log.c builtin/repack.c +#: builtin/commit-graph.c builtin/fetch.c builtin/gc.c builtin/log.c +#: builtin/repack.c msgid "dir" msgstr "direktori" @@ -5715,7 +5731,7 @@ msgstr "git commit-tree: gagal membaca" #: builtin/commit.c msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -5725,7 +5741,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <komit> | --fixup [(amend|" "reword):]<komit>]\n" " [-F <berkas> | -m <pesan>] [--reset-author] [--allow-empty]\n" @@ -7472,14 +7488,14 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Jalankan 'git remote set-head %s %s' untuk mengikuti perubahan, atau setel\n" "opsi konfigurasi 'remote.%s.followRemoteHEAD' ke nilai yang berbeda jika\n" -"Anda tidak ingin melihat pesan ini lagi. Secara rinci menjalakan\n" -"'git config set remote.%s followRemoteHEAD %s' akan mematikan peringatan\n" -"ini sampai remote mengubah HEAD ke yang lain." +"Anda tidak ingin melihat pesan ini lagi. Secara rinci menjalankan\n" +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s' akan\n" +"mematikan peringatan ini sampai remote mengubah HEAD ke yang lain." #: builtin/fetch.c msgid "multiple branches detected, incompatible with --set-upstream" @@ -8341,6 +8357,10 @@ msgstr "paksa jalankan gc bahkan jika mungkin ada gc lain yang berjalan" msgid "repack all other packs except the largest pack" msgstr "pak ulang semua pak yang lain kecuali pak terbesar" +#: builtin/gc.c builtin/repack.c +msgid "pack prefix to store a pack containing pruned objects" +msgstr "awalan pak untuk menyimpan pak berisi objek terpangkas" + #: builtin/gc.c #, c-format msgid "failed to parse gc.logExpiry value %s" @@ -9353,6 +9373,11 @@ msgstr "tidak dapat menyelesaikan pack-objects untuk mempak ulang tautan lokal" msgid "Cannot come back to cwd" msgstr "tidak dapat kembali ke direktori kerja saat ini" +#: builtin/index-pack.c builtin/unpack-objects.c +#, c-format +msgid "bad --pack_header: %s" +msgstr "--pack_header jelek: %s" + #: builtin/index-pack.c #, c-format msgid "bad %s" @@ -10476,11 +10501,6 @@ msgstr "opsi strategi tidak dikenal: -X%s" msgid "malformed input line: '%s'." msgstr "baris masukan jelek: '%s'." -#: builtin/merge-tree.c -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "penggabungan tidak dapat berlanjut; dapat hasil kotor dari %d" - #: builtin/merge.c msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<opsi>] [<komit>...]" @@ -11524,6 +11544,15 @@ msgstr "" #: builtin/pack-objects.c #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "opsi --name-hash-version tidak valid: %d" + +#: builtin/pack-objects.c +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "saat ini, --write-bitmap-index memerlukan --name-hash-version=1" + +#: builtin/pack-objects.c +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -11935,6 +11964,12 @@ msgstr "" "protokol ini" #: builtin/pack-objects.c +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"gunakan fungsi nama-hash yang dirincikan untuk mengelompokan objek yang " +"serupa" + +#: builtin/pack-objects.c #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "kedalaman rantai delta %d terlalu dalam, memaksakan %d" @@ -13428,8 +13463,8 @@ msgid "invalid ref format: %s" msgstr "format referensi tidak valid: %s" #: builtin/refs.c -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<format> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" #: builtin/refs.c msgid "git refs verify [--strict] [--verbose]" @@ -13444,6 +13479,10 @@ msgid "perform a non-destructive dry-run" msgstr "lakukan uji coba non desktruktif" #: builtin/refs.c +msgid "drop reflogs entirely during the migration" +msgstr "buang keseluruhan log referensi selama migrasi" + +#: builtin/refs.c msgid "missing --ref-format=<format>" msgstr "--ref-format=<format> hilang" @@ -14024,8 +14063,14 @@ msgid "be verbose; must be placed before a subcommand" msgstr "jadi lebih bertele-tele; harus ditempatkan sebelum subperintah" #: builtin/repack.c -msgid "git repack [<options>]" -msgstr "git repack [<opsi>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<nama pak>]\n" +"[--write-midx] [--name-hash-version=<n>]" #: builtin/repack.c msgid "" @@ -14119,6 +14164,13 @@ msgid "pass --no-reuse-object to git-pack-objects" msgstr "lewatkan --no-reuse-object ke git-pack-objects" #: builtin/repack.c +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"tentukan versi nama hash yang digunakan untuk mengelompokan objek yang " +"serupa berdasarkan jalur" + +#: builtin/repack.c msgid "do not run git-update-server-info" msgstr "jangan jalankan git-update-server-info" @@ -14185,10 +14237,6 @@ msgid "write a multi-pack index of the resulting packs" msgstr "tulis indeks multipak dari pak yang dihasilkan" #: builtin/repack.c -msgid "pack prefix to store a pack containing pruned objects" -msgstr "awalan pak untuk menyimpan pak berisi objek terpangkas" - -#: builtin/repack.c msgid "pack prefix to store a pack containing filtered out objects" msgstr "awalan pak untuk menyimpan pak berisi objek tersaring" @@ -14463,10 +14511,6 @@ msgid "need some commits to replay" msgstr "butuh beberapa komit untuk dimainkan ulang" #: builtin/replay.c -msgid "--onto and --advance are incompatible" -msgstr "--onto dan --advance tidak kompatibel" - -#: builtin/replay.c msgid "all positive revisions given must be references" msgstr "semua revisi positif yang diberikan haruslah referensi" @@ -17768,6 +17812,10 @@ msgid "Create an archive of files from a named tree" msgstr "Buat arsip berkas dari pohon bernama" #: command-list.h +msgid "Download missing objects in a partial clone" +msgstr "Unduh objek yang hilang dalam klon parsial" + +#: command-list.h msgid "Use binary search to find the commit that introduced a bug" msgstr "Gunakan pencarian biner untuk mencari komit yang memasukkan bug" @@ -20191,6 +20239,14 @@ msgid "invalid regex given to -I: '%s'" msgstr "regex tidak valid diberikan ke -I: '%s'" #: diff.c +msgid "-G requires a non-empty argument" +msgstr "-G butuh sebuah argumen bukan kosong" + +#: diff.c +msgid "-S requires a non-empty argument" +msgstr "-S butuh sebuah argumen bukan kosong" + +#: diff.c #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "gagal menguraikan parameter opsi --submodule: '%s'" @@ -22888,6 +22944,11 @@ msgstr "tidak dapat menulis berkas %s" #: object-file.c #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "tidak dapat menulis berkas yang menghilang %s terus-menerus" + +#: object-file.c +#, c-format msgid "unable to set permission to '%s'" msgstr "tidak dapat menyetel perizinan ke '%s'" @@ -23579,6 +23640,55 @@ msgstr "sakelar tidak dikenal `%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "opsi non-ascii di dalam untai tidak dikenal: `%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid " <%s>" +msgstr " <%s>" + #: parse-options.c msgid "..." msgstr "..." @@ -23682,6 +23792,25 @@ msgstr "nilai lingkungan boolean '%s' jelek untuk '%s'" msgid "failed to parse %s" msgstr "gagal menguraikan %s" +#: path-walk.c +#, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "gagal berjalan anak pohon %s: tidak ditemukan" + +#: path-walk.c +#, c-format +msgid "failed to find object %s" +msgstr "gagal menemukan objek %s" + +#: path-walk.c +#, c-format +msgid "failed to find tag %s" +msgstr "gagal menemukan tag %s" + +#: path-walk.c +msgid "failed to setup revision walk" +msgstr "gagal men-setup jalan revisi" + #: path.c #, c-format msgid "Could not make %s writable by group" @@ -23868,6 +23997,26 @@ msgstr "nama remote penjanji tidak dapat diawali dengan '/': %s" msgid "could not fetch %s from promisor remote" msgstr "tidak dapat mengambil %s dari remote penjanji" +#: promisor-remote.c +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "remote yang terkenal bernama '%s' tapi dengan url '%s' daripada '%s'" + +#: promisor-remote.c +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "nilai '%s' tidak dikenal untuk opsi konfigurasi '%s'" + +#: promisor-remote.c +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "elemen '%s' dari info remote tidak dikenal" + +#: promisor-remote.c +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "remote penjanji yang diterima '%s' tidak ditemukan" + #: protocol-caps.c msgid "object-info: expected flush after arguments" msgstr "object-info: bilasan diharapkan setelah argumen" @@ -24870,6 +25019,16 @@ msgstr "nama referensi %s simbolik, menyalinnya tidak didukung" msgid "invalid refspec '%s'" msgstr "spek referensi tidak valid '%s'" +#: refspec.c +#, c-format +msgid "pattern '%s' has no '*'" +msgstr "pola '%s' tidak mempunyai '*'" + +#: refspec.c +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "pengganti '%s' tidak mempunyai '*'" + #: remote-curl.c #, c-format msgid "invalid quoting in push-option value: '%s'" @@ -25025,6 +25184,28 @@ msgstr "remote-curl: perintah tidak dikenal '%s' dari git" #: remote.c #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"membaca remote dari \"%s/%s\", yang dinominasikan untuk dihapus.\n" +"\n" +"Jika Anda masih menggunakan direktori \"remotes/\" disarankan untuk\n" +"migrasi ke remote berdasarkan konfigurasi:\n" +"\n" +"\tgit remote rename %s %s\n" +"Jika tidak, mohon beri tahu kami mengapa Anda masih menggunakannya dengan\n" +"mengirimkan surel ke <git@vger.kernel.org>." + +#: remote.c +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "pintasan konfigurasi remote tidak dapat diawali dengan '/': %s" @@ -25068,16 +25249,6 @@ msgstr "%s melacak baik %s dan %s" #: remote.c #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "kunci '%s' dari pola tidak ada '*'" - -#: remote.c -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "nilai '%s' dari pola tidak ada '*'" - -#: remote.c -#, c-format msgid "src refspec %s does not match any" msgstr "spek referensi sumber %s tidak cocok dengan apapun" @@ -27389,6 +27560,34 @@ msgstr "bersihkan pohon tembolok sebelum setiap iterasi" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "jumlah entri di dalam pohon tembolok untuk dinirvalidasi (asali 0)" +#: t/helper/test-path-walk.c +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <opsi> -- <opsi revisi>" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of blob objects" +msgstr "sertakan objek blob" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of commit objects" +msgstr "sertakan objek komit" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tag objects" +msgstr "sertakan objek tag" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tree objects" +msgstr "sertakan objek pohon" + +#: t/helper/test-path-walk.c +msgid "toggle pruning of uninteresting paths" +msgstr "pangkas jalur yang tidak menarik" + +#: t/helper/test-path-walk.c +msgid "read a pattern list over stdin" +msgstr "baca daftar pola dari masukan standar" + #: t/helper/test-reach.c #, c-format msgid "commit %s is not marked reachable" @@ -28148,6 +28347,11 @@ msgstr "kesalahan: " msgid "warning: " msgstr "peringatan: " +#: version.c +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() gagal dengan kesalahan '%s' (%d)\n" + #: walker.c msgid "Fetching objects" msgstr "Mengambil objek" @@ -17602,7 +17602,7 @@ msgstr "Controllo la ridenominazione di '%s' in '%s'\n" #: builtin/mv.c:185 msgid "bad source" -msgstr "sourgente errata" +msgstr "sorgente errata" #: builtin/mv.c:188 msgid "can not move directory into itself" @@ -7,6 +7,7 @@ # Changwoo Ryu <cwryu@debian.org>, 2015-2018. # Sihyeon Jang <uneedsihyeon@gmail.com>, 2018. # Gwan-gyeong Mun <elongbug@gmail.com>, 2018. +# Seoyeon Kwon <syeon0204@gmail.com>, 2025. # # - 작업ìžëŠ” 위 Contributors 목ë¡ì— 추가해 주세요. # - 번ì—하면서 80ì»¬ëŸ¼ì„ ë„˜ì–´ê°€ì§€ 않ë„ë¡ í•´ 주세요. @@ -7666,7 +7667,7 @@ msgid "" " git commit --allow-empty\n" "\n" msgstr "" -"ì´ì „ 커맷 빼오기가 비어 있습니다. ì•„ë§ˆë„ ì¶©ëŒ í•´ê²° ê³¼ì •ì—서 ê·¸ë ‡ê²Œ ëì„\n" +"ì´ì „ 커밋 빼오기가 비어 있습니다. ì•„ë§ˆë„ ì¶©ëŒ í•´ê²° ê³¼ì •ì—서 ê·¸ë ‡ê²Œ ëì„\n" "것입니다. ê·¸ëž˜ë„ ì»¤ë°‹í•˜ë ¤ë©´ 다ìŒê³¼ ê°™ì´ í•˜ì‹ì‹œì˜¤:\n" "\n" " git commit --allow-empty\n" @@ -1,14 +1,14 @@ # Swedish translations for Git. -# Copyright (C) 2010-2024 Peter Krefting <peter@softwolves.pp.se> +# Copyright (C) 2010-2025 Peter Krefting <peter@softwolves.pp.se> # This file is distributed under the same license as the Git package. -# Peter Krefting <peter@softwolves.pp.se>, 2010-2024. +# Peter Krefting <peter@softwolves.pp.se>, 2010-2025. # msgid "" msgstr "" -"Project-Id-Version: git 2.48.0\n" +"Project-Id-Version: git 2.49.0\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-30 11:57+0100\n" -"PO-Revision-Date: 2024-12-30 12:03+0100\n" +"POT-Creation-Date: 2025-03-10 17:45+0100\n" +"PO-Revision-Date: 2025-03-10 17:48+0100\n" "Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n" "Language-Team: Svenska <tp-sv@listor.tp-sv.se>\n" "Language: sv\n" @@ -1477,7 +1477,7 @@ msgid "" "Use '\\!' for literal leading exclamation." msgstr "" "Negativa mönster ignoreras i git-attribut\n" -"Använd '\\!' för att inleda med ett utropstecken." +"Använd â€\\!†för att inleda med ett utropstecken." #, c-format msgid "cannot fstat gitattributes file '%s'" @@ -2060,7 +2060,7 @@ msgid "" "It does not apply to blobs recorded in its index." msgstr "" "Har du handredigerat din patch?\n" -"Den kan inte tillämpas pÃ¥ blobbar som antecknats i dess index." +"Den kan inte tillämpas pÃ¥ blob:ar som antecknats i dess index." msgid "Falling back to patching base and 3-way merge..." msgstr "" @@ -2316,6 +2316,18 @@ msgstr "git archive: protokollfel" msgid "git archive: expected a flush" msgstr "git archive: förväntade en tömning (flush)" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "problem med att läsa filen sparse-checkout" + +msgid "Minimum number of objects to request at a time" +msgstr "Minsta antal objekt att be om varje gÃ¥ng" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Begränsa saknade objekt till befintlig â€sparse-checkoutâ€" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -2921,7 +2933,7 @@ msgid "delete branch (even if not merged)" msgstr "ta bort gren (även om inte helt sammanslagen)" msgid "move/rename a branch and its reflog" -msgstr "flytta/ta bort en gren och dess reflogg" +msgstr "flytta/ta bort en gren och dess referenslogg" msgid "move/rename a branch, even if target exists" msgstr "flytta/ta bort en gren, även om mÃ¥let finns" @@ -2930,7 +2942,7 @@ msgid "do not output a newline after empty formatted refs" msgstr "skriv inte ut ett nyradstecken efter tomma formaterade referenser" msgid "copy a branch and its reflog" -msgstr "kopiera en gren och dess reflogg" +msgstr "kopiera en gren och dess referenslogg" msgid "copy a branch, even if target exists" msgstr "kopiera en gren, även om mÃ¥let finns" @@ -2942,7 +2954,7 @@ msgid "show current branch name" msgstr "visa namn pÃ¥ aktuell gren" msgid "create the branch's reflog" -msgstr "skapa grenens reflogg" +msgstr "skapa grenens referenslogg" msgid "edit the description for the branch" msgstr "redigera beskrivning för grenen" @@ -3055,10 +3067,6 @@ msgstr "" msgid "git version:\n" msgstr "git version:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() misslyckades med felet â€%s†(%d)\n" - msgid "compiler info: " msgstr "kompilatorinfo:" @@ -3095,7 +3103,7 @@ msgid "" "You can delete any lines you don't wish to share.\n" msgstr "" "Tack för att du skriver en buggraport för Git!\n" -"Om du svarar pÃ¥ följande frÃ¥gor är det lättare för oss att första " +"Om du svarar pÃ¥ följande frÃ¥gor är det lättare för oss att förstÃ¥ " "problemet.\n" "Skriv gärna pÃ¥ engelska\n" "\n" @@ -3332,11 +3340,11 @@ msgid "blob|tree" msgstr "blob|träd" msgid "use a <path> for (--textconv | --filters); Not with 'batch'" -msgstr "använd en <sökväg> för (--textconv | --filters): Inte med 'batch'" +msgstr "använd en <sökväg> för (--textconv | --filters): Inte med â€batchâ€" #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" -msgstr "'%s=<%s>' behöver '%s' eller '%s'" +msgstr "â€%s=<%s>†behöver â€%s†eller â€%sâ€" msgid "path|tree-ish" msgstr "sökväg|träd-igt" @@ -3368,13 +3376,13 @@ msgid "" "git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] " "<pathname>..." msgstr "" -"git check-attr [--source <träd:igt>] [-a | --all | <attr>...] [--] " +"git check-attr [--source <träd-igt>] [-a | --all | <attr>...] [--] " "<sökväg>..." msgid "" "git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]" msgstr "" -"git check-attr --stdin [-z] [--source <träd:igt>] [-a | --all | <attr>...]" +"git check-attr --stdin [-z] [--source <träd-igt>] [-a | --all | <attr>...]" msgid "report all attributes set on file" msgstr "visa alla attribut som satts pÃ¥ filen" @@ -3887,7 +3895,7 @@ msgid "create/reset and checkout a branch" msgstr "skapa/nollställ och checka ut en gren" msgid "create reflog for new branch" -msgstr "skapa reflogg för ny gren" +msgstr "skapa referenslogg för ny gren" msgid "second guess 'git checkout <no-such-branch>' (default)" msgstr "förutspÃ¥ â€git checkout <gren-saknas>†(förval)" @@ -4062,8 +4070,91 @@ msgstr "ta endast bort ignorerade filer" msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "clean.requireForce är true och -f angavs inte: vägrar städa" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<flaggor>] [--] <arkiv> [<kat>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: Kan inte skapa suppleant för â€%sâ€: %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "misslyckades ta status pÃ¥ â€%sâ€" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s finns och är ingen katalog" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "â€%s†är en symbolisk länk, vägrar klona med --local" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "misslyckades starta iterator över â€%sâ€" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "symbolisk länk â€%s†finns redan, vägrar klona med --local" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "misslyckades ta bort länken â€%sâ€" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "hÃ¥rd länk kan inte kontrolleras vid â€%sâ€" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "hÃ¥rd länk skiljer sig frÃ¥n källan vid â€%sâ€" + +#, c-format +msgid "failed to create link '%s'" +msgstr "misslyckades skapa länken â€%sâ€" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "misslyckades kopiera filen till â€%sâ€" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "misslyckades iterera över â€%sâ€" + +#, c-format +msgid "done.\n" +msgstr "klart.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Klonen lyckades, men utcheckningen misslyckades.\n" +"Du kan inspektera det som checkades ut med â€git statusâ€\n" +"och försöka med â€git restore --source=HEAD :/â€\n" + +msgid "remote did not send all necessary objects" +msgstr "fjärren sände inte alla nödvändiga objekt" + +#, c-format +msgid "unable to update %s" +msgstr "kan inte uppdatera %s" + +msgid "failed to initialize sparse-checkout" +msgstr "misslyckades initiera sparse-checkout" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "HEAD hos fjärren pekar pÃ¥ en obefintlig referens, kan inte checka ut" + +msgid "unable to checkout working tree" +msgstr "kan inte checka ut arbetskatalogen" + +msgid "unable to write parameters to config file" +msgstr "kan inte skriva parametrar till konfigurationsfilen" + +msgid "cannot repack to clean up" +msgstr "kan inte packa om för att städa upp" + +msgid "cannot unlink temporary alternates file" +msgstr "kunde inte ta bort temporär â€alternatesâ€-fil" msgid "don't clone shallow repository" msgstr "klona inte grunt arkiv" @@ -4116,6 +4207,9 @@ msgstr "använd <namn> istället för â€origin†för att spÃ¥ra uppströms" msgid "checkout <branch> instead of the remote's HEAD" msgstr "checka ut <gren> istället för fjärrens HEAD" +msgid "clone single revision <rev> and check out" +msgstr "klona ensam revision <rev> och checka ut" + msgid "path to git-upload-pack on the remote" msgstr "sökväg till git-upload-pack pÃ¥ fjärren" @@ -4137,8 +4231,8 @@ msgstr "fördjupa historik för grund klon, exkludera ref" msgid "clone only one branch, HEAD or --branch" msgstr "klona endast en gren, HEAD eller --branch" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "klona inga taggar och gör att senare hämtningar inte följer dem" +msgid "clone tags, and make later fetches not to follow them" +msgstr "klona taggar och gör att senare hämtningar inte följer dem" msgid "any cloned submodules will be shallow" msgstr "klonade undermoduler kommer vara grunda" @@ -4179,95 +4273,8 @@ msgstr "uri" msgid "a URI for downloading bundles before fetching from origin remote" msgstr "en URI för att hämta buntar innan de hämtas frÃ¥n ursprungsfjärr" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: Kan inte skapa suppleant för â€%sâ€: %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "misslyckades ta status pÃ¥ â€%sâ€" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s finns och är ingen katalog" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "â€%s†är en symbolisk länk, vägrar klona med --local" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "misslyckades starta iterator över â€%sâ€" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "symbolisk länk â€%s†finns redan, vägrar klona med --local" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "misslyckades ta bort länken â€%sâ€" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "hÃ¥rd länk kan inte kontrolleras vid â€%sâ€" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "hÃ¥rd länk skiljer sig frÃ¥n källan vid â€%sâ€" - -#, c-format -msgid "failed to create link '%s'" -msgstr "misslyckades skapa länken â€%sâ€" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "misslyckades kopiera filen till â€%sâ€" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "misslyckades iterera över â€%sâ€" - -#, c-format -msgid "done.\n" -msgstr "klart.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Klonen lyckades, men utcheckningen misslyckades.\n" -"Du kan inspektera det som checkades ut med â€git statusâ€\n" -"och försöka med â€git restore --source=HEAD :/â€\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Kunde inte hitta fjärrgrenen %s för att klona." - -msgid "remote did not send all necessary objects" -msgstr "fjärren sände inte alla nödvändiga objekt" - -#, c-format -msgid "unable to update %s" -msgstr "kan inte uppdatera %s" - -msgid "failed to initialize sparse-checkout" -msgstr "misslyckades initiera sparse-checkout" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "HEAD hos fjärren pekar pÃ¥ en obefintlig referens, kan inte checka ut" - -msgid "unable to checkout working tree" -msgstr "kan inte checka ut arbetskatalogen" - -msgid "unable to write parameters to config file" -msgstr "kan inte skriva parametrar till konfigurationsfilen" - -msgid "cannot repack to clean up" -msgstr "kan inte packa om för att städa upp" - -msgid "cannot unlink temporary alternates file" -msgstr "kunde inte ta bort temporär â€alternatesâ€-fil" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<flaggor>] [--] <arkiv> [<kat>]" msgid "Too many arguments." msgstr "För mÃ¥nga argument." @@ -4367,6 +4374,10 @@ msgstr "fjärrtransport rapporterade fel" msgid "Remote branch %s not found in upstream %s" msgstr "Fjärrgrenen %s hittades inte i uppströmsarkivet %s" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Fjärr-revisionen %s hittades inte i uppströmsarkivet %s" + msgid "You appear to have cloned an empty repository." msgstr "Du verkar ha klonat ett tomt arkiv." @@ -4540,7 +4551,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: misslyckades läsa" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4550,7 +4561,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<läge>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<läge>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <incheckning> | --fixup [(amend|" "reword):]<incheckning>]\n" " [-F <fil> | -m <medd>] [--reset-author] [--allow-empty]\n" @@ -4791,7 +4802,7 @@ msgstr "Ange meddelandet en av flaggorna -m eller -F.\n" #, c-format msgid "--author '%s' is not 'Name <email>' and matches no existing author" msgstr "" -"--author '%s' är inte 'Namn <epost>' och motsvarar ingen befintlig författare" +"--author â€%s†är inte â€Namn <epost>†och motsvarar ingen befintlig författare" #, c-format msgid "Invalid ignored mode '%s'" @@ -5202,7 +5213,7 @@ msgid "writing to stdin is not supported" msgstr "skriva till standard in stöds inte" msgid "writing config blobs is not supported" -msgstr "skriva konfigurations-blobbar stöds inte" +msgstr "skriva konfigurations-blob:ar stöds inte" #, c-format msgid "" @@ -5239,7 +5250,7 @@ msgid "" "section in \"git help worktree\" for details" msgstr "" "--worktree kan inte användas med flera arbetskataloger om inte\n" -"konfigurationsutöknignen worktreeConfig har aktiverats. Läsa stycket\n" +"konfigurationsutökningen worktreeConfig har aktiverats. Läsa stycket\n" "â€KONFIGURATIONSFIL†i â€git help worktree†för detaljer" msgid "Other" @@ -5325,7 +5336,7 @@ msgid "editing stdin is not supported" msgstr "redigering av standard in stöds ej" msgid "editing blobs is not supported" -msgstr "redigering av blobbar stöds ej" +msgstr "redigering av blob:ar stöds ej" #, c-format msgid "cannot create configuration file %s" @@ -5601,7 +5612,7 @@ msgstr "objektet â€%s†som angavs är felaktigt." #, c-format msgid "more than two blobs given: '%s'" -msgstr "mer än tvÃ¥ blobbar angavs: â€%sâ€" +msgstr "mer än tvÃ¥ blob:ar angavs: â€%sâ€" #, c-format msgid "unhandled object '%s' given." @@ -5760,7 +5771,7 @@ msgid "reference parents which are not in fast-export stream by object id" msgstr "referera föräldrar som inte finns i fast-export-ström med objekt-id" msgid "show original object ids of blobs/commits" -msgstr "visa ursprungliga objekt-id för blobbar/incheckningar" +msgstr "visa ursprungliga objekt-id för blob:ar/incheckningar" msgid "label tags with mark ids" msgstr "märk taggar med märke-id" @@ -5931,14 +5942,14 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Kör â€git remote set-head %s %s†för att följa ändringen, eller sätt\n" "konfigurationsflaggan â€remote %s.followRemoteHEAD†till ett annat värde\n" "om du inte vill se det här meddelandet. Du kan specifikt inaktivera\n" "varningen till fjärren ändrar HEAD till nÃ¥got annat genom att köra\n" -"â€git config set remote %s.followRemoteHEAD %sâ€." +"â€git config set remote %s.followRemoteHEAD warn-if-not-branch-%sâ€." msgid "multiple branches detected, incompatible with --set-upstream" msgstr "flera grenar upptäcktes, inkompatibelt med --set-upstream" @@ -6328,11 +6339,11 @@ msgstr "%s: objekt trasigt eller saknas" #, c-format msgid "%s: invalid reflog entry %s" -msgstr "%s: ogiltig reflog-post %s" +msgstr "%s: ogiltig referensloggpost %s" #, c-format msgid "Checking reflog %s->%s" -msgstr "Kontrollerar reflog %s→%s" +msgstr "Kontrollerar referenslogg %s→%s" #, c-format msgid "%s: invalid sha1 pointer %s" @@ -6441,7 +6452,7 @@ msgid "make index objects head nodes" msgstr "gör indexobjekt till huvudnoder" msgid "make reflogs head nodes (default)" -msgstr "gör refloggar till huvudnoder (standard)" +msgstr "gör referensloggar till huvudnoder (standard)" msgid "also consider packs and alternate objects" msgstr "ta även hänsyn till paket och supplerande objekt" @@ -6502,11 +6513,11 @@ msgstr "kunde inte skapa fsmonitor-kaka â€%sâ€" #, c-format msgid "fsmonitor: cookie_result '%d' != SEEN" -msgstr "fsmonitor: cookie_result '%d' != SEEN" +msgstr "fsmonitor: cookie_result â€%d†!= SEEN" #, c-format msgid "could not start IPC thread pool on '%s'" -msgstr "kunde inte starta IPC-trÃ¥dpol pÃ¥ â€%sâ€" +msgstr "kunde inte starta IPC-trÃ¥dpool pÃ¥ â€%sâ€" msgid "could not start fsmonitor listener thread" msgstr "kunde inte starta fsmonitor-lyssnartrÃ¥d" @@ -6618,6 +6629,9 @@ msgstr "tvinga gc-körning även om en annan gc kanske körs" msgid "repack all other packs except the largest pack" msgstr "packa om alla paket förutom det största paketet" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "paketprefix att lagra ett paket som innehÃ¥ller bortrensade objekt" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "misslyckades tolka värdet %s för gc.logExpiry" @@ -7176,7 +7190,7 @@ msgstr "flaggan â€%s†tar inte nÃ¥gra argument som inte är flaggor" msgid "" "the '--no-[external-commands|aliases]' options can only be used with '--all'" msgstr "" -"flaggorna '--no-[external-commands|aliases]' kan endast användas med â€--allâ€" +"flaggorna â€--no-[external-commands|aliases]†kan endast användas med â€--allâ€" #, c-format msgid "usage: %s%s" @@ -7407,6 +7421,10 @@ msgid "Cannot come back to cwd" msgstr "Kan inte gÃ¥ tillbaka till arbetskatalogen (cwd)" #, c-format +msgid "bad --pack_header: %s" +msgstr "felaktig --pack_header: %s" + +#, c-format msgid "bad %s" msgstr "felaktig %s" @@ -7977,7 +7995,7 @@ msgid "suppress duplicate entries" msgstr "undertryck dublettposter" msgid "show sparse directories in the presence of a sparse index" -msgstr "visa glesa kataloger när et glest index existerar" +msgstr "visa glesa kataloger när ett glest index existerar" msgid "" "--format cannot be used with -s, -o, -k, -t, --resolve-undo, --deduplicate, " @@ -8261,10 +8279,6 @@ msgstr "okänd strategiflagga: -X%s" msgid "malformed input line: '%s'." msgstr "felaktig indatarad: â€%sâ€." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "sammanslagning kan inte fortsätta; fick inte rent resultat frÃ¥n %d" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<flaggor>] [<incheckning>...]" @@ -8969,7 +8983,7 @@ msgid "failed to remove 'git notes merge' worktree" msgstr "misslyckades ta bort arbetskatalogen för â€git notes mergeâ€" msgid "failed to read ref NOTES_MERGE_PARTIAL" -msgstr "misslyckades läsa references NOTES_MERGE_PARTIAL" +msgstr "misslyckades läsa referensen NOTES_MERGE_PARTIAL" msgid "could not find commit from NOTES_MERGE_PARTIAL." msgstr "kunde inte hitta incheckning frÃ¥n NOTES_MERGE_PARTIAL." @@ -9081,6 +9095,13 @@ msgstr "" "git pack-objects [<flaggor>] <basnamn> [< <reflista> | < <objektlista>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "ogiltig flagga för --name-hash-version: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "--write-bitmap-index kräver för närvarande, --name-hash-version=1" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9190,14 +9211,14 @@ msgid "" "value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-" "hash> <uri>' (got '%s')" msgstr "" -"värdet pÃ¥ uploadpack.blobpackfileuri mÃ¥ste vara pÃ¥ formen '<objekt-hash> " -"<paket-hash> <uri>' (fick '%s')" +"värdet pÃ¥ uploadpack.blobpackfileuri mÃ¥ste vara pÃ¥ formen â€<objekt-hash> " +"<paket-hash> <uri>†(fick â€%sâ€)" #, c-format msgid "" "object already configured in another uploadpack.blobpackfileuri (got '%s')" msgstr "" -"objektet redan konfigurerat i et annat uploadpack.blobpackfileuri (fick '%s)" +"objektet redan konfigurerat i ett annat uploadpack.blobpackfileuri (fick â€%sâ€" #, c-format msgid "could not get type of object %s in pack %s" @@ -9401,6 +9422,10 @@ msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "" "uteslut redan konfigurerade uploadpack.blobpackfileuri med detta protokoll" +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"använd den angivna namn-hash-funktionen för att gruppera liknande objekt" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "deltakedjedjupet %d är för djupt, pÃ¥tvingar %d" @@ -10189,7 +10214,7 @@ msgstr "" "Ange vilken gren du vill ombasera mot.\n" "Se git-rebase(1) för detaljer.\n" "\n" -" git rebase '<gren>'\n" +" git rebase â€<gren>â€\n" "\n" #, c-format @@ -10603,7 +10628,8 @@ msgid "process the reflogs of all references" msgstr "hantera referensloggar för alla referenser" msgid "limits processing to reflogs from the current worktree only" -msgstr "begränsar hantering av referensloggar till endast aktuell arbetskatalog" +msgstr "" +"begränsar hantering av referensloggar till endast aktuell arbetskatalog" #, c-format msgid "Marking reachable objects..." @@ -10620,8 +10646,8 @@ msgstr "ingen referenslogg att ta bort angavs" msgid "invalid ref format: %s" msgstr "felaktigt referensformat: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<format> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -10632,6 +10658,9 @@ msgstr "ange referensformatet att konvertera till" msgid "perform a non-destructive dry-run" msgstr "utför ett icke-destruktiv testkörning" +msgid "drop reflogs entirely during the migration" +msgstr "kasta referensloggar helt under migreringen" + msgid "missing --ref-format=<format>" msgstr "saknad --ref-format=<format>" @@ -11091,8 +11120,14 @@ msgstr "Kommer inte ta bort alla icke-sänd-URL:er" msgid "be verbose; must be placed before a subcommand" msgstr "var pratsam; mÃ¥ste skrivas före ett underkommando" -msgid "git repack [<options>]" -msgstr "git repack [<flaggor>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<paket-namn>]\n" +"[--write-midx] [--name-hash-version=<n>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11166,6 +11201,12 @@ msgstr "sänd --no-reuse-delta till git-pack-objects" msgid "pass --no-reuse-object to git-pack-objects" msgstr "sänd --no-reuse-object till git-pack-objects" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"ange den namnhash-version som ska användas för att gruppera liknande objekt " +"efter sökväg" + msgid "do not run git-update-server-info" msgstr "kör inte git-update-server-info" @@ -11214,9 +11255,6 @@ msgstr "hitta ett geometrisk förlopp med faktor <N>" msgid "write a multi-pack index of the resulting packs" msgstr "skriv ett flerpaketsindex för de skapade paketen" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "paketprefix att lagra ett paket som innehÃ¥ller bortrensade objekt" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "paketprefix att lagra ett paket som innehÃ¥ller utfiltrerade objekt" @@ -11433,9 +11471,6 @@ msgstr "endast ett mönster kan anges med -l" msgid "need some commits to replay" msgstr "behöver nÃ¥gra incheckningar för omspelning" -msgid "--onto and --advance are incompatible" -msgstr "--onto och --advance kan inte kombineras" - msgid "all positive revisions given must be references" msgstr "alla positiva revisioner som anges mÃ¥ste vara referenser" @@ -12020,7 +12055,7 @@ msgid "<n>[,<base>]" msgstr "<n>[,<bas>]" msgid "show <n> most recent ref-log entries starting at base" -msgstr "visa <n> nyaste refloggposter med början pÃ¥ bas" +msgstr "visa <n> nyaste referensloggposter med början pÃ¥ bas" msgid "no branches given, and HEAD is not valid" msgstr "inga grenar angavs, och HEAD är inte giltigt" @@ -12134,7 +12169,7 @@ msgid "" "directory '%s' contains untracked files, but is not in the sparse-checkout " "cone" msgstr "" -"katalogen â€%s†innehÃ¥ller ospÃ¥rade filer, men är inte i omrÃ¥det som ages i " +"katalogen â€%s†innehÃ¥ller ospÃ¥rade filer, men är inte i omrÃ¥det som anges i " "â€sparse-checkoutâ€" #, c-format @@ -12726,7 +12761,7 @@ msgstr "misslyckades klona â€%s†till undermodulsökvägen â€%sâ€" #, c-format msgid "could not get submodule directory for '%s'" -msgstr "kunde inte fÃ¥ tag i undermodulkatalog för â€%sâ€" +msgstr "kunde inte fÃ¥ tag i undermodulskatalog för â€%sâ€" msgid "alternative anchor for relative paths" msgstr "alternativa ankare för relativa sökvägar" @@ -12830,8 +12865,8 @@ msgid "" "Fetched in submodule path '%s', but it did not contain %s. Direct fetching " "of that commit failed." msgstr "" -"Hämtade i undermodulssökvägen â€%sâ€, men den innehöll inte %s. Direkt " -"hämtning av incheckningen misslyckades." +"Hämtade i undermodulsökvägen â€%sâ€, men den innehöll inte %s. Direkt hämtning " +"av incheckningen misslyckades." #, c-format msgid "could not initialize submodule at path '%s'" @@ -13199,7 +13234,7 @@ msgid "replace the tag if exists" msgstr "ersätt taggen om den finns" msgid "create a reflog" -msgstr "skapa en reflog" +msgstr "skapa en referenslogg" msgid "Tag listing options" msgstr "Alternativ för listning av taggar" @@ -13924,7 +13959,7 @@ msgstr "okänd kapabilitet â€%sâ€" #, c-format msgid "'%s' does not look like a v2 or v3 bundle file" -msgstr "'%s' ser inte ut som en v2- eller v3-bunt-fil" +msgstr "â€%s†ser inte ut som en v2- eller v3-bunt-fil" #, c-format msgid "unrecognized header: %s%s (%d)" @@ -14058,6 +14093,9 @@ msgstr "Importera ett GNU Arch-arkiv till Git" msgid "Create an archive of files from a named tree" msgstr "Skapa ett arkiv över filer frÃ¥n ett namngivet träd" +msgid "Download missing objects in a partial clone" +msgstr "Hämta saknade objekt i en delvis kloning" + msgid "Use binary search to find the commit that introduced a bug" msgstr "Använd binärsökning för att hitta ändringen som introducerade ett fel" @@ -14164,7 +14202,7 @@ msgid "Compare a tree to the working tree or index" msgstr "Jämför en träd med arbetskatalogen eller indexet" msgid "Compares the content and mode of blobs found via two tree objects" -msgstr "Visar innehÃ¥ll och läge för blobbar som hittats via tvÃ¥ trädobjekt" +msgstr "Visar innehÃ¥ll och läge för blob:ar som hittats via tvÃ¥ trädobjekt" msgid "Show changes using common diff tools" msgstr "Visa ändringar med vanliga diff-verktyg" @@ -14996,19 +15034,19 @@ msgstr "kunde inte läsa katalogändringar [GLE %ld]" #, c-format msgid "opendir('%s') failed" -msgstr "opendir('%s') misslyckades" +msgstr "opendir(â€%sâ€) misslyckades" #, c-format msgid "lstat('%s') failed" -msgstr "lstat('%s') misslyckades" +msgstr "lstat(â€%sâ€) misslyckades" #, c-format msgid "strbuf_readlink('%s') failed" -msgstr "strbuf_readlink('%s') misslyckades" +msgstr "strbuf_readlink(â€%sâ€) misslyckades" #, c-format msgid "closedir('%s') failed" -msgstr "closedir('%s') misslyckades" +msgstr "closedir(â€%sâ€) misslyckades" #, c-format msgid "[GLE %ld] unable to open for read '%ls'" @@ -15335,7 +15373,7 @@ msgstr "referensen â€%s†pekar inte pÃ¥ en blob" #, c-format msgid "unable to resolve config blob '%s'" -msgstr "kan inte slÃ¥ upp konfigurerings-blobben â€%sâ€" +msgstr "kan inte slÃ¥ upp konfigurerings-blob:en â€%sâ€" msgid "unable to parse command-line config" msgstr "kan inte tolka kommandoradskonfiguration" @@ -15968,6 +16006,12 @@ msgstr "ogiltigt argument för %s" msgid "invalid regex given to -I: '%s'" msgstr "ogiltigt reguljärt uttryck angavs för -I: â€%sâ€" +msgid "-G requires a non-empty argument" +msgstr "-G kräver ett icke-tomt argument" + +msgid "-S requires a non-empty argument" +msgstr "-S kräver ett icke-tomt argument" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "misslyckades tolka argument till flaggan --submodule: â€%sâ€" @@ -16080,7 +16124,7 @@ msgid "" "do not munge pathnames and use NULs as output field terminators in --raw or " "--numstat" msgstr "" -"skriv inte om sökvägsnamn och använd NUL-tecken som fältseparerare i --raw " +"skriv inte om sökvägsnamn och använd NUL-tecken som fältavdelare i --raw " "eller --numstat" msgid "<prefix>" @@ -16495,7 +16539,7 @@ msgid "already have %s (%s)" msgstr "har redan %s (%s)" msgid "fetch-pack: unable to fork off sideband demultiplexer" -msgstr "fetch-patch: kan inte grena (fork) av sidbandsmultiplexare" +msgstr "fetch-patch: kan inte grena (fork) av sidbands-avmultiplexare" msgid "protocol error: bad pack header" msgstr "protokollfel: felaktigt packhuvud" @@ -16689,7 +16733,7 @@ msgstr "" "â€git help -a†och â€git help -g†visar tillgängliga underkommandon och\n" "nÃ¥gra konceptvägledningar. Se â€git help <kommando>†eller â€git help\n" "<koncept>†för att läsa mer om specifika underkommandon och koncept.\n" -"See â€git help git†för en översikt över systemet." +"Se â€git help git†för en översikt över systemet." #, c-format msgid "unsupported command listing type '%s'" @@ -17020,7 +17064,7 @@ msgstr "inte ett git-arkiv" #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "" -"argumentet till --packfile mÃ¥ste vara ett giltigt hashvärde (fick '%s')" +"argumentet till --packfile mÃ¥ste vara ett giltigt hashvärde (fick â€%sâ€)" #, c-format msgid "negative value for http.postBuffer; defaulting to %d" @@ -17056,7 +17100,7 @@ msgid "" " asked for: %s\n" " redirect: %s" msgstr "" -"kan inte uppdatera urlbas frÃ¥n omdirigerin:\n" +"kan inte uppdatera urlbas frÃ¥n omdirigering:\n" " bad om: %s\n" " omdirigering: %s" @@ -17914,7 +17958,7 @@ msgid "multi-pack-index stores a 64-bit offset, but off_t is too small" msgstr "multi-pack-index innehÃ¥ller 64-bitars offset, men off_t är för liten" msgid "multi-pack-index large offset out of bounds" -msgstr "stort offset för mult-pack-index utanför gränsen" +msgstr "stort offset för multi-pack-index utanför gränsen" msgid "multi-pack-index file exists, but failed to parse" msgstr "multi-pack-indexfilen finns, men kunde inte tolkas" @@ -17985,7 +18029,7 @@ msgstr "Kan inte checka in oinitierat/orefererat anteckningsträd" #, c-format msgid "Bad notes.rewriteMode value: '%s'" -msgstr "Felaktigt värde för notes.rewriteMode: '%s'" +msgstr "Felaktigt värde för notes.rewriteMode: â€%sâ€" #, c-format msgid "Refusing to rewrite notes in %s (outside of refs/notes/)" @@ -18135,6 +18179,10 @@ msgid "unable to write file %s" msgstr "kan inte skriva filen %s" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "kan inte skriva till filen %s som hela tiden försvinner" + +#, c-format msgid "unable to set permission to '%s'" msgstr "kan inte sätta behörigheten till â€%sâ€" @@ -18538,7 +18586,8 @@ msgstr "bitkarteresultat stämmer inte överens" #, c-format msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" -msgstr "pseudosammanslagningsindex utanför intervallet (%<PRIu32> ≥ %<PRIuMAX>)" +msgstr "" +"pseudosammanslagningsindex utanför intervallet (%<PRIu32> ≥ %<PRIuMAX>)" #, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" @@ -18694,6 +18743,52 @@ msgstr "okänd flagga â€%câ€" msgid "unknown non-ascii option in string: `%s'" msgstr "okänd icke-ascii-flagga i strängen: â€%sâ€" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -18779,6 +18874,21 @@ msgid "failed to parse %s" msgstr "misslyckades tolka %s" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "misslyckades traversera löven i trädet %s: hittades inte" + +#, c-format +msgid "failed to find object %s" +msgstr "misslyckades hitta objektet %s" + +#, c-format +msgid "failed to find tag %s" +msgstr "misslyckades hitta taggen %s" + +msgid "failed to setup revision walk" +msgstr "misslyckades starta revisionstraversering" + +#, c-format msgid "Could not make %s writable by group" msgstr "Kunde inte göra %s skrivbar för gruppen" @@ -18923,6 +19033,22 @@ msgstr "kontraktsfjärr kan inte börja med â€/â€: %s" msgid "could not fetch %s from promisor remote" msgstr "kunde inte hämta %s frÃ¥n kontraktsfjärr" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "känd fjärr som heter â€%s†med med url:en â€%s†istället för â€%sâ€" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "okänt värde â€%s†för inställningen â€%sâ€" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "okänt värde â€%s†frÃ¥n fjärrinformation" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "godkänd kontraktsfjärr â€%s†hittades inte" + msgid "object-info: expected flush after arguments" msgstr "object-info: förväntade â€flush†efter argument" @@ -19248,7 +19374,7 @@ msgstr "" " enrads, om inget incheckningsmeddelande angavs); använd\n" " -c <incheckning> för att skriva om meddelandet.\n" "u, update-ref <ref> = spÃ¥ra en platshÃ¥llare för <ref> att uppdatera\n" -" till denna position bland nya inchecknngar.\n" +" till denna position bland nya incheckningar.\n" " <ref> uppdateras i slutet av ombaseringen.\n" "\n" "Du kan byta ordning pÃ¥ raderna; de utförs uppifrÃ¥n och ned.\n" @@ -19616,7 +19742,7 @@ msgid "refusing to update ref with bad name '%s'" msgstr "vägrar uppdatera referens med trasigt namn â€%sâ€" msgid "refusing to force and skip creation of reflog" -msgstr "vägrar att tvinga och hoppa över skapande av reflogg" +msgstr "vägrar att tvinga och hoppa över skapande av referenslogg" #, c-format msgid "update_ref failed for ref '%s': %s" @@ -19749,6 +19875,14 @@ msgid "invalid refspec '%s'" msgstr "felaktig referensspecifikation: â€%sâ€" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "mönstret â€%s†innehÃ¥ller ingen â€*â€" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "ersättningen â€%s†innehÃ¥ller ingen â€*â€" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "felaktig citering pÃ¥ värde för push-option: â€%sâ€" @@ -19867,6 +20001,28 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: okänt kommando â€%s†frÃ¥n git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"läser fjärren frÃ¥n â€%s/%sâ€, som har nominerats för borttagning.\n" +"\n" +"Om du fortfarande använder â€remotes/â€-katalogen rekommenderas du\n" +"migrera till konfigurationsbaserade fjärrar:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"Om du inte kan det, berätta för oss varför du fortfarande behöver\n" +"använda det pÃ¥ e-post till <git@vger.kernel.org>." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "konfigurerad kortform för fjärr kan inte börja med â€/â€: %s" @@ -19901,14 +20057,6 @@ msgid "%s tracks both %s and %s" msgstr "%s spÃ¥rar bÃ¥de %s och %s" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "nyckeln â€%s†i mönstret innehÃ¥ller ingen â€*â€" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "värdet â€%s†i mönstret innehÃ¥ller ingen â€*â€" - -#, c-format msgid "src refspec %s does not match any" msgstr "käll-referensspecifikationen %s motsvarar ingen" @@ -21798,6 +21946,27 @@ msgstr "töm cacheträdet före varje iteration" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "antal poster i cacheträdet att ogiltigförklara (förval är 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <flaggor> -- <revision-flaggor>" + +msgid "toggle inclusion of blob objects" +msgstr "växla om blob-objekt ska vara med eller inte" + +msgid "toggle inclusion of commit objects" +msgstr "växla om incheckningsobjekt ska vara med eller inte" + +msgid "toggle inclusion of tag objects" +msgstr "växla om taggobjekt ska vara med eller inte" + +msgid "toggle inclusion of tree objects" +msgstr "växla om trädobjekt ska vara med eller inte" + +msgid "toggle pruning of uninteresting paths" +msgstr "växla bortrensning av ointressanta sökvägar" + +msgid "read a pattern list over stdin" +msgstr "läs en mönsterlista frÃ¥n standard in" + #, c-format msgid "commit %s is not marked reachable" msgstr "incheckning %s är inte märkt nÃ¥bar" @@ -22431,6 +22600,10 @@ msgstr "fel: " msgid "warning: " msgstr "varning: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() misslyckades med felet â€%s†(%d)\n" + msgid "Fetching objects" msgstr "Hämtar objekt" @@ -23265,7 +23438,7 @@ msgstr "Nödvändig SMTP-server har inte angivits korrekt." #, perl-format msgid "Server does not support STARTTLS! %s" -msgstr "Servern stöder inte SMARTTLS! %s" +msgstr "Servern stöder inte STARTTLS! %s" #, perl-format msgid "STARTTLS failed! %s" @@ -96,8 +96,8 @@ msgid "" msgstr "" "Project-Id-Version: Git Turkish Localization Project\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-23 18:57+0000\n" -"PO-Revision-Date: 2025-01-01 15:00+0300\n" +"POT-Creation-Date: 2025-03-11 15:01+0300\n" +"PO-Revision-Date: 2025-03-11 15:00+0300\n" "Last-Translator: Emir SARI <emir_sari@icloud.com>\n" "Language-Team: Turkish (https://github.com/bitigchi/git-po/)\n" "Language: tr\n" @@ -2408,6 +2408,18 @@ msgstr "git archive: Protokol hatası" msgid "git archive: expected a flush" msgstr "git archive: FloÅŸ bekleniyordu" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "aralıklı çıkış yüklenirken sorun" + +msgid "Minimum number of objects to request at a time" +msgstr "Bir kerede istenecek en çok nesne sayısı" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Eksik nesneleri geçerli aralıklı çıkışa sınırla" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -3149,10 +3161,6 @@ msgstr "" msgid "git version:\n" msgstr "git sürümü:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() '%s' hatasını verip çıktı (%d)\n" - msgid "compiler info: " msgstr "derleyici bilgisi: " @@ -4158,8 +4166,91 @@ msgstr "" "clean.requireForce 'true' olarak ayarlı ve -f verilmedi; temizlik " "reddediliyor" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<seçenekler>] [--] <depo> [<dizin>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: '%s' için alternatif eklenemedi: %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "'%s' dosyasının bilgileri alınamadı" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s var ve bir dizin deÄŸil" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' bir sembolik baÄŸ; --local ile klonlama reddediliyor" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "yineleyici '%s' üzerinden çalıştırılamadı" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "'%s' sembolik bağı var, --local ile klonlama reddediliyor" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "'%s' baÄŸlantısı kesilemedi" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "sabit baÄŸlantı, '%s' konumunda denetlenemiyor" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "sabit baÄŸlantı, '%s' konumundaki kaynaktan farklı" + +#, c-format +msgid "failed to create link '%s'" +msgstr "'%s' bağı oluÅŸturulamadı" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "dosya ÅŸuraya kopyalanamadı: '%s'" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "'%s' üzerinde yinelenemedi" + +#, c-format +msgid "done.\n" +msgstr "bitti.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Klonlama baÅŸarılı oldu; ancak çıkış yapılamadı.\n" +"Neyin çıkış yapılıp yapılmadığını 'git status' ile inceleyebilir\n" +"ve 'git restore --source=HEAD' ile yeniden deneyebilirsiniz.\n" + +msgid "remote did not send all necessary objects" +msgstr "uzak konum gereken tüm nesneleri göndermedi" + +#, c-format +msgid "unable to update %s" +msgstr "%s güncellenemiyor" + +msgid "failed to initialize sparse-checkout" +msgstr "sparse-checkout ilklendirilemedi" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "uzak konum HEAD'i, var olmayan baÅŸvuruya baÅŸvuruyor; çıkış yapılamıyor" + +msgid "unable to checkout working tree" +msgstr "çalışma aÄŸacı çıkış yapılamıyor" + +msgid "unable to write parameters to config file" +msgstr "parametreler yapılandırma dosyasına yazılamıyor" + +msgid "cannot repack to clean up" +msgstr "temizlik için yeniden paketlenemiyor" + +msgid "cannot unlink temporary alternates file" +msgstr "geçici alternatifler dosyasının baÄŸlantısı kesilemiyor" msgid "don't clone shallow repository" msgstr "sığ depoyu klonlama" @@ -4212,6 +4303,9 @@ msgstr "üstkaynağı izlemek için 'origin' yerine <ad> kullan" msgid "checkout <branch> instead of the remote's HEAD" msgstr "uzak konumun HEAD'i yerine <dal>'ı çıkış yap" +msgid "clone single revision <rev> and check out" +msgstr "tek revizyonlu <rev>'i klonla ve çıkış yap" + msgid "path to git-upload-pack on the remote" msgstr "uzak konumdaki git-upload-pack'e olan yol" @@ -4233,8 +4327,8 @@ msgstr "baÅŸvuru hariç tutarak sığ klonun geçmiÅŸini derinleÅŸtir" msgid "clone only one branch, HEAD or --branch" msgstr "yalnızca bir dal klonla, HEAD veya --branch" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "etiket klonlama ve sonraki getirmeler de onları izlemesin" +msgid "clone tags, and make later fetches not to follow them" +msgstr "etiketleri klonla ve sonraki getirmelerin onları izlememesini saÄŸla" msgid "any cloned submodules will be shallow" msgstr "klonlanan altmodüller sığ olacak" @@ -4277,95 +4371,8 @@ msgstr "uri" msgid "a URI for downloading bundles before fetching from origin remote" msgstr "uzak konum kökeninden getirmeden önce demetleri indirmek için bir URI" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: '%s' için alternatif eklenemedi: %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "'%s' dosyasının bilgileri alınamadı" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s var ve bir dizin deÄŸil" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' bir sembolik baÄŸ; --local ile klonlama reddediliyor" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "yineleyici '%s' üzerinden çalıştırılamadı" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "'%s' sembolik bağı var, --local ile klonlama reddediliyor" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "'%s' baÄŸlantısı kesilemedi" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "sabit baÄŸlantı, '%s' konumunda denetlenemiyor" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "sabit baÄŸlantı, '%s' konumundaki kaynaktan farklı" - -#, c-format -msgid "failed to create link '%s'" -msgstr "'%s' bağı oluÅŸturulamadı" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "dosya ÅŸuraya kopyalanamadı: '%s'" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "'%s' üzerinde yinelenemedi" - -#, c-format -msgid "done.\n" -msgstr "bitti.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Klonlama baÅŸarılı oldu; ancak çıkış yapılamadı.\n" -"Neyin çıkış yapılıp yapılmadığını 'git status' ile inceleyebilir\n" -"ve 'git restore --source=HEAD' ile yeniden deneyebilirsiniz.\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Klonlanacak %s uzak dal bulunamadı." - -msgid "remote did not send all necessary objects" -msgstr "uzak konum gereken tüm nesneleri göndermedi" - -#, c-format -msgid "unable to update %s" -msgstr "%s güncellenemiyor" - -msgid "failed to initialize sparse-checkout" -msgstr "sparse-checkout ilklendirilemedi" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "uzak konum HEAD'i, var olmayan baÅŸvuruya baÅŸvuruyor; çıkış yapılamıyor" - -msgid "unable to checkout working tree" -msgstr "çalışma aÄŸacı çıkış yapılamıyor" - -msgid "unable to write parameters to config file" -msgstr "parametreler yapılandırma dosyasına yazılamıyor" - -msgid "cannot repack to clean up" -msgstr "temizlik için yeniden paketlenemiyor" - -msgid "cannot unlink temporary alternates file" -msgstr "geçici alternatifler dosyasının baÄŸlantısı kesilemiyor" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<seçenekler>] [--] <depo> [<dizin>]" msgid "Too many arguments." msgstr "Çok fazla argüman." @@ -4465,6 +4472,10 @@ msgstr "uzak konum taşıması hata bildirdi" msgid "Remote branch %s not found in upstream %s" msgstr "%s uzak dalı %s üstkaynağında bulunamadı" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "%s uzak revizyonu, %s üstkaynağında bulunamadı" + msgid "You appear to have cloned an empty repository." msgstr "BoÅŸ bir depoyu klonlamış görünüyorsunuz." @@ -4641,7 +4652,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: okunamadı" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4651,11 +4662,11 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<kip>] [--amend]\n" -" [--dry-run] [(-c | -C | --squash) <iÅŸleme> | --fixup\n" -" [(amend|reword):]<iÅŸleme>] [-F <dosya> | -m <ileti>] [--" -"reset-author] [--allow-empty]\n" -" [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<kip>]] [--amend]\n" +" [--dry-run] [(-c | -C | --squash) <iÅŸleme> |\n" +" --fixup [(amend|reword):]<iÅŸleme>]\n" +" [-F <dosya> | -m <ileti>] [--reset-author] [--allow-empty]\n" +" [--allow-empty-message] [--no-verify] [-e] [--author=<yazar>]\n" " [--date=<tarih>] [--cleanup=<kip>] [--[no-]status]\n" " [-i | -o] [--pathspec-from-file=<dosya> [--pathspec-file-nul]]\n" " [(--trailer <jeton>[(=|:)<deÄŸer>])...] [-S[<anahtar-kimliÄŸi>]]\n" @@ -6044,15 +6055,15 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "DeÄŸiÅŸikliÄŸi izlemek için 'git remote set-head %s %s' yapın veya\n" "'remote.%s.followRemoteHEAD' yapılandırma seçeneÄŸini baÅŸka bir\n" "deÄŸere ayarlayın (bu iletiyi görmek istemiyorsanız). Özellikle\n" -"'git config set remote.%s.followRemoteHEAD %s' komutunu çalıştırmak\n" -"uyarıyı HEAD'e veya baÅŸka bir ÅŸeye uzaktan deÄŸiÅŸiklik olana dek\n" -"devre dışı bırakır." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"komutunu çalıştırmak, uyarıyı HEAD'e veya baÅŸka bir ÅŸeye uzaktan\n" +"deÄŸiÅŸiklik olana dek devre dışı bırakır." msgid "multiple branches detected, incompatible with --set-upstream" msgstr "birden çok dal algılandı, --set-upstream ile uyumsuz" @@ -6729,6 +6740,9 @@ msgstr "baÅŸka bir gc çalışıyor olsa bile zorla gc çalıştır" msgid "repack all other packs except the largest pack" msgstr "en büyük paket dışındaki diÄŸer tüm paketleri yeniden paketle" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "budanan nesneler içeren paketi depolamak için paket öneki" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "gc.logExpiry deÄŸeri %s ayrıştırılamadı" @@ -7526,6 +7540,10 @@ msgid "Cannot come back to cwd" msgstr "Geçerli çalışma dizinine geri gelinemiyor" #, c-format +msgid "bad --pack_header: %s" +msgstr "hatalı --pack_header: %s" + +#, c-format msgid "bad %s" msgstr "hatalı %s" @@ -8384,10 +8402,6 @@ msgstr "bilinmeyen strateji seçeneÄŸi: -X%s" msgid "malformed input line: '%s'." msgstr "hatalı oluÅŸturulmuÅŸ girdi satırı: '%s'." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "birleÅŸtirme sürdürülemiyor; %d için temiz olmayan sonuçlar alındı" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<seçenekler>] [<iÅŸleme>...]" @@ -9202,6 +9216,13 @@ msgstr "" "listesi>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "geçersiz --name-hash-version seçeneÄŸi: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "ÅŸu anda --write-bitmap-index, --name-hash-version=1 gerektiriyor" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9526,6 +9547,9 @@ msgstr "" "bu protokol ile herhangi bir yapılandırılmış uploadpack.blobpackfileuri " "ögesini hariç tut" +msgid "use the specified name-hash function to group similar objects" +msgstr "benzer nesneleri gruplamak için belirtilen name-hash iÅŸlevini kullan" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "delta zincir derinliÄŸi %d çok derin, %d zorlanıyor" @@ -10756,8 +10780,8 @@ msgstr "silmek için bir baÅŸvuru günlüğü belirtilmedi" msgid "invalid ref format: %s" msgstr "geçersiz baÅŸvuru biçimi: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<biçim> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<biçim> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -10768,6 +10792,9 @@ msgstr "dönüştürülecek baÅŸvuru biçimini belirt" msgid "perform a non-destructive dry-run" msgstr "yıkıcı olmayan bir deneme gerçekleÅŸtir" +msgid "drop reflogs entirely during the migration" +msgstr "göç sırasında baÅŸvuru günlüklerini tümüyle bırak" + msgid "missing --ref-format=<format>" msgstr "--ref-format=<biçim> eksik" @@ -11234,8 +11261,14 @@ msgstr "Tüm itme olmayan URL'ler silinmeyecek" msgid "be verbose; must be placed before a subcommand" msgstr "ayrıntılı anlat; bir altkomuttan önce yerleÅŸtirilmelidir" -msgid "git repack [<options>]" -msgstr "git repack [<seçenekler>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<paket-adı>]\n" +"[--write-midx] [--name-hash-version=<n>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11309,6 +11342,11 @@ msgstr "'git-pack-objects'e --no-reuse-delta geçir" msgid "pass --no-reuse-object to git-pack-objects" msgstr "'git-pack-objects'e --no-reuse-object geçir" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"benzer nesneleri yola göre gruplamada kullanılacak name-hash sürümünü belirt" + msgid "do not run git-update-server-info" msgstr "'git-update-server-info' çalıştırma" @@ -11357,9 +11395,6 @@ msgstr "<N> faktörlü bir geometrik ilerleme bul" msgid "write a multi-pack index of the resulting packs" msgstr "ortaya çıkan paketlerin bir çoklu paket indeksini yaz" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "budanan nesneler içeren paketi depolamak için paket öneki" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "süzülen nesneler içeren paketi depolamak için paket öneki" @@ -11576,9 +11611,6 @@ msgstr "-l ile yalnızca bir dizgi verilebilir" msgid "need some commits to replay" msgstr "yeniden oynatmak için birkaç iÅŸleme gerekli" -msgid "--onto and --advance are incompatible" -msgstr "--onto ve --advance birbiriyle uyumsuz" - msgid "all positive revisions given must be references" msgstr "verilen tüm pozitif revizyonlar, baÅŸvuru olmalı" @@ -14200,6 +14232,9 @@ msgstr "Git'e bir GNU Arch deposu içe aktar" msgid "Create an archive of files from a named tree" msgstr "Ad verilmiÅŸ aÄŸaçtan bir dosyalar arÅŸivi oluÅŸtur" +msgid "Download missing objects in a partial clone" +msgstr "Eksik nesneleri kısımsal bir klonda indir" + msgid "Use binary search to find the commit that introduced a bug" msgstr "Hatalara neden olan iÅŸlemeyi bulmada ikili arama kullan" @@ -16111,6 +16146,12 @@ msgstr "%s için geçersiz argüman" msgid "invalid regex given to -I: '%s'" msgstr "-I'ya geçersiz düzenli ifade verildi: '%s'" +msgid "-G requires a non-empty argument" +msgstr "-G, boÅŸ olmayan bir argüman gerektiriyor" + +msgid "-S requires a non-empty argument" +msgstr "-S, boÅŸ olmayan bir argüman gerektiriyor" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "--submodule seçenek parametresi ayrıştırılamadı: '%s'" @@ -18290,6 +18331,10 @@ msgid "unable to write file %s" msgstr "%s dosyası yazılamıyor" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "sürekli olarak kaybolan %s dosyası yazılamıyor" + +#, c-format msgid "unable to set permission to '%s'" msgstr "'%s' ögesine izin ayarlanamıyor" @@ -18851,6 +18896,52 @@ msgstr "bilinmeyen anahtar '%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "dizi içinde bilinmeyen ascii dışı seçenek: '%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -18937,6 +19028,21 @@ msgid "failed to parse %s" msgstr "%s ayrıştırılamadı" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "%s aÄŸacının alt ögeleri yürütülemedi: bulunamadı" + +#, c-format +msgid "failed to find object %s" +msgstr "%s nesnesi bulunamadı" + +#, c-format +msgid "failed to find tag %s" +msgstr "%s etiketi bulunamadı" + +msgid "failed to setup revision walk" +msgstr "revizyon yürüyüşü ayarlanamadı" + +#, c-format msgid "Could not make %s writable by group" msgstr "%s grup ile yazılabilir yapılamadı" @@ -19079,6 +19185,22 @@ msgstr "vaatçi uzak konum adı '/' ile baÅŸlayamaz: %s" msgid "could not fetch %s from promisor remote" msgstr "vaatçi uzak konumundan %s getirilemedi" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "bilinen uzak konum adı '%s'; ancak url'si '%s'; '%s' olmalı" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "'%s' yapılandırma seçeneÄŸi için bilinmeyen deÄŸer: '%s'" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "uzak bilgiden bilinmeyen öge '%s'" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "kabul edilmiÅŸ vaatçi uzak konum '%s' bulunamadı" + msgid "object-info: expected flush after arguments" msgstr "object-info: argümanlardan sonra floÅŸ bekleniyordu" @@ -19902,6 +20024,14 @@ msgid "invalid refspec '%s'" msgstr "geçersiz baÅŸvuru belirteci '%s'" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "'%s' dizgisinde '*' yok" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "'%s' yedeÄŸinde '*' yok" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "push-option deÄŸerinde geçersiz tırnak içine alım: '%s'" @@ -20021,6 +20151,31 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: git'ten bilinmeyen komut '%s'" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"Kaldırma için aday gösterilmiÅŸ \"%s/%s\" konumundan\n" +"uzak konum okunuyor.\n" +"\n" +"EÄŸer hâlâ \"remotes\" dizinini kullanıyorsanız\n" +"yapılandırma tabanlı uzak konumlara geçiÅŸ yapmanız\n" +"önerilir:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"EÄŸer geçiÅŸ yapamıyorsanız bunu neden kullandığınıza\n" +"dair bir iletiyi <git@vger.kernel.org> adresine\n" +"gönderin." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "uzak konum yapılandırma stenografisi '/' ile baÅŸlayamaz: %s" @@ -20055,14 +20210,6 @@ msgid "%s tracks both %s and %s" msgstr "%s hem %s hem %s ögelerini izler" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "dizginin '%s' anahtarında '*' yoktu" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "dizginin '%s' deÄŸerinde '*' yok" - -#, c-format msgid "src refspec %s does not match any" msgstr "kaynak baÅŸvuru belirteci %s baÅŸka hiçbir ÅŸeyle eÅŸleÅŸmiyor" @@ -21948,6 +22095,27 @@ msgstr "her bir yinelemeden önce önbellek aÄŸacını temizle" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "önbellek aÄŸacındaki geçersizleÅŸtirilecek girdi sayısı (öntanımlı 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <seçenekler> -- <revizyon-seçenekleri>" + +msgid "toggle inclusion of blob objects" +msgstr "ikili nesnelerin içerilmesini aç/kapat" + +msgid "toggle inclusion of commit objects" +msgstr "iÅŸleme nesnelerinin içerilmesini aç/kapat" + +msgid "toggle inclusion of tag objects" +msgstr "etiket nesnelerinin içerilmesini aç/kapat" + +msgid "toggle inclusion of tree objects" +msgstr "aÄŸaç nesnelerinin içerilmesini aç/kapat" + +msgid "toggle pruning of uninteresting paths" +msgstr "ilgisiz yolların budanmasını aç/kapat" + +msgid "read a pattern list over stdin" +msgstr "stdin'den bir dizgi listesi oku" + #, c-format msgid "commit %s is not marked reachable" msgstr "%s iÅŸlemesi ulaşılabilir olarak imlenmedi" @@ -22575,6 +22743,10 @@ msgstr "hata: " msgid "warning: " msgstr "uyarı: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() '%s' hatasını verip çıktı (%d)\n" + msgid "Fetching objects" msgstr "Nesneler getiriliyor" @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: Git v2.46\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2025-01-04 19:26-0800\n" -"PO-Revision-Date: 2025-01-03 14:17-0800\n" +"POT-Creation-Date: 2025-03-09 15:40-0700\n" +"PO-Revision-Date: 2025-03-09 16:53-0700\n" "Last-Translator: Kateryna Golovanova <kate@kgthreads.com>\n" "Language-Team: Ukrainian <https://github.com/arkid15r/git-uk-l10n/>\n" "Language: uk\n" @@ -1433,7 +1433,7 @@ msgid "write the archive to this file" msgstr "запиÑати архів до цього файлу" msgid "read .gitattributes in working directory" -msgstr "прочитати .gitattributes робочої директорії" +msgstr "читати .gitattributes робочої директорії" msgid "report archived files on stderr" msgstr "звітувати про заархівовані файли в stderr" @@ -2357,6 +2357,18 @@ msgstr "git archive: помилка протоколу" msgid "git archive: expected a flush" msgstr "git archive: очікувалоÑÑŒ flush" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<н>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "проблема із завантаженнÑм розрідженого переходу" + +msgid "Minimum number of objects to request at a time" +msgstr "Мінімальна кількіÑть обʼєктів Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ за один раз" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Обмежити відÑутні обʼєкти поточним розрідженим переходом" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -3117,15 +3129,11 @@ msgstr "" msgid "git version:\n" msgstr "верÑÑ–Ñ git:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() завершивÑÑ Ð½ÐµÐ²Ð´Ð°Ð»Ð¾ з помилкою \"%s\" (%d)\n" - msgid "compiler info: " msgstr "Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ‰Ð¾Ð´Ð¾ компілÑтора: " msgid "libc info: " -msgstr "Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ‰Ð¾Ð´Ð¾ libc: " +msgstr "Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ‰Ð¾Ð´Ð¾ libc: " msgid "not run from a git repository - no hooks to show\n" msgstr "запущено не з git Ñховища - немає гачків Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ\n" @@ -3448,7 +3456,7 @@ msgid "use .gitattributes only from the index" msgstr "викориÑтовувати .gitattributes тільки з індекÑу" msgid "read file names from stdin" -msgstr "зчитувати назви файлів з stdin" +msgstr "читати назви файлів з stdin" msgid "terminate input and output records by a NUL character" msgstr "завершувати вхідні та вихідні запиÑи Ñимволом NUL" @@ -3493,13 +3501,13 @@ msgid "also read contacts from stdin" msgstr "також читати контакти з stdin" msgid "read additional mailmap entries from file" -msgstr "зчитувати додаткові запиÑи mailmap з файлу" +msgstr "читати додаткові запиÑи mailmap з файлу" msgid "blob" msgstr "blob" msgid "read additional mailmap entries from blob" -msgstr "зчитувати додаткові запиÑи mailmap з blob" +msgstr "читати додаткові запиÑи mailmap з blob" msgid "no contacts specified" msgstr "контакти не вказані" @@ -3538,10 +3546,10 @@ msgid "update stat information in the index file" msgstr "оновити ÑтатиÑтичну інформацію в індекÑному файлі" msgid "read list of paths from the standard input" -msgstr "зчитати ÑпиÑок шлÑхів зі Ñтандартного вводу" +msgstr "читати ÑпиÑок шлÑхів зі Ñтандартного вводу" msgid "write the content to temporary files" -msgstr "запиÑати вміÑÑ‚ у тимчаÑові файли" +msgstr "запиÑати вміÑÑ‚ до тимчаÑових файлів" msgid "copy out the files from named stage" msgstr "Ñкопіювати файли з іменованої Ñтадії" @@ -4146,11 +4154,94 @@ msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" "clean.requireForce вÑтановлено у true Ñ– -f не задано: відмовлено в прибиранні" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<опції>] [--] <Ñховище> [<директоріÑ>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "інфо: Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ запозичений обʼєкт Ð´Ð»Ñ \"%s\": %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ stat \"%s\"" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s Ñ–Ñнує Ñ– не Ñ” директорією" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "\"%s\" Ñ” Ñимвольним поÑиланнÑм, відмовлено в клонуванні з --local" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "не вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити ітератор Ð´Ð»Ñ \"%s\"" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "Ñимвольне поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\" Ñ–Ñнує, відмовлено в клонуванні з --local" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ \"%s\"" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "неможливо перевірити жорÑтке поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\"" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "жорÑтке поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ñ€Ñ–Ð·Ð½ÑєтьÑÑ Ð²Ñ–Ð´ джерела в \"%s\"" + +#, c-format +msgid "failed to create link '%s'" +msgstr "не вдалоÑÑ Ñтворити поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\"" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "не вдалоÑÑ Ñкопіювати файл у \"%s\"" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "не вдалоÑÑ Ð·Ð´Ñ–Ð¹Ñнити перебір Ð´Ð»Ñ \"%s\"" + +#, c-format +msgid "done.\n" +msgstr "готово.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"ÐšÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð¾ уÑпішно, але не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¹Ñ‚Ð¸ на гілку.\n" +"Ви можете перевірити, що було додано за допомогою 'git status'\n" +"Ñ– повторити Ñпробу за допомогою \"git restore --source=HEAD :/\"\n" + +msgid "remote did not send all necessary objects" +msgstr "віддалене Ñховище не надіÑлало вÑÑ– необхідні обʼєкти" + +#, c-format +msgid "unable to update %s" +msgstr "не вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ %s" + +msgid "failed to initialize sparse-checkout" +msgstr "не вдалоÑÑ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ розріджений перехід" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "віддалений HEAD вказує на неіÑнуюче поÑиланнÑ, неможливо перейти" + +msgid "unable to checkout working tree" +msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ Ñтан робочої директорії" + +msgid "unable to write parameters to config file" +msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати параметри до конфігураційного файлу" + +msgid "cannot repack to clean up" +msgstr "неможливо перепакувати Ð´Ð»Ñ Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ" + +msgid "cannot unlink temporary alternates file" +msgstr "неможливо видалити тимчаÑовий файл запозичених обʼєктів" msgid "don't clone shallow repository" -msgstr "не клонувати неглибоке Ñховище" +msgstr "не клонувати поверхневе Ñховище" msgid "don't create a checkout" msgstr "не переходити на гілку" @@ -4202,6 +4293,9 @@ msgstr "" msgid "checkout <branch> instead of the remote's HEAD" msgstr "перейти до <гілки> заміÑть HEAD віддаленого Ñховища" +msgid "clone single revision <rev> and check out" +msgstr "клонувати одну ревізію <rev> Ñ– перейти на неї" + msgid "path to git-upload-pack on the remote" msgstr "шлÑÑ… до git-upload-pack на віддаленому Ñервері" @@ -4223,9 +4317,8 @@ msgstr "поглибити Ñ–Ñторію неглибокого клону, зРmsgid "clone only one branch, HEAD or --branch" msgstr "клонувати лише одну гілку, HEAD або --branch" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "" -"не клонувати жодних тегів Ñ– не Ñлідувати за ними під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼ÑƒÐ²Ð°Ð½ÑŒ пізніше" +msgid "clone tags, and make later fetches not to follow them" +msgstr "клонувати теги Ñ– більше не Ñлідкувати за ними" msgid "any cloned submodules will be shallow" msgstr "будь-Ñкі клоновані підмодулі будуть неглибокими" @@ -4269,95 +4362,8 @@ msgstr "uri" msgid "a URI for downloading bundles before fetching from origin remote" msgstr "URI Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÑ–Ð² перед отриманнÑм з віддаленого джерела" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "инфо: Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ запозичений обʼєкт Ð´Ð»Ñ \"%s\": %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ stat \"%s\"" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s Ñ–Ñнує Ñ– не Ñ” директорією" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "\"%s\" Ñ” Ñимвольним поÑиланнÑм, відмовлено в клонуванні з --local" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "не вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити перебір Ð´Ð»Ñ \"%s\"" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "Ñимвольне поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\" Ñ–Ñнує, не можу клонувати з --local" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ \"%s\"" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "неможливо перевірити жорÑтке поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\"" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "жорÑтке поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ñ€Ñ–Ð·Ð½ÑєтьÑÑ Ð²Ñ–Ð´ джерела в \"%s\"" - -#, c-format -msgid "failed to create link '%s'" -msgstr "не вдалоÑÑ Ñтворити поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\"" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "не вдалоÑÑ Ñкопіювати файл у \"%s\"" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ±Ñ€Ð°Ñ‚Ð¸ \"%s\"" - -#, c-format -msgid "done.\n" -msgstr "готово.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"ÐšÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð¾ уÑпішно, але не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¹Ñ‚Ð¸ на гілку.\n" -"Ви можете перевірити, що було додано за допомогою 'git status'\n" -"Ñ– повторити Ñпробу за допомогою 'git restore --source=HEAD :/'\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ віддалену гілку %s Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ." - -msgid "remote did not send all necessary objects" -msgstr "віддалене Ñховище не надіÑлало вÑÑ– необхідні обʼєкти" - -#, c-format -msgid "unable to update %s" -msgstr "не вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ %s" - -msgid "failed to initialize sparse-checkout" -msgstr "не вдалоÑÑ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ розріджений перехід" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "віддалений HEAD поÑилаєтьÑÑ Ð½Ð° неіÑнуючого рефа, неможливо перейти" - -msgid "unable to checkout working tree" -msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ Ñтан робочої директорії" - -msgid "unable to write parameters to config file" -msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати параметри до конфігураційного файлу" - -msgid "cannot repack to clean up" -msgstr "неможливо перепакувати, щоб очиÑтити" - -msgid "cannot unlink temporary alternates file" -msgstr "неможливо видалити тимчаÑовий файл запозичених обʼєктів" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<опції>] [--] <Ñховище> [<директоріÑ>]" msgid "Too many arguments." msgstr "Забагато аргументів." @@ -4463,6 +4469,10 @@ msgstr "Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ð³Ð¾ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð msgid "Remote branch %s not found in upstream %s" msgstr "Віддалену гілку %s не знайдено у першоджерельному Ñховищі %s" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Віддалена Ñ€ÐµÐ²Ñ–Ð·Ñ–Ñ %s не знайдена у першоджерельному Ñховищі %s" + msgid "You appear to have cloned an empty repository." msgstr "ЗдаєтьÑÑ, ви клонували порожнє Ñховище." @@ -4639,7 +4649,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4649,7 +4659,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<режим>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<режим>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <коміт> | --fixup [(amend|" "reword):]<коміт>]\n" " [-F <файл> | -m <допиÑ>] [--reset-author] [--allow-empty]\n" @@ -5214,7 +5224,7 @@ msgid "blob-id" msgstr "blob-id" msgid "read config from given blob object" -msgstr "прочитати конфігурацію з наданого blob-обʼєкту" +msgstr "читати конфігурацію з наданого blob-обʼєкту" msgid "Type" msgstr "Тип" @@ -6050,15 +6060,15 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "ЗапуÑтіть \"git remote set-head %s %s\", щоб відÑтежити зміни, або " "вÑтановіть\n" "\"remote.%s.followRemoteHEAD\" параметр конфігурації на інше значеннÑ\n" -"Ñкщо ви не хочете бачити це повідомленнÑ. Зокрема, Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¸\n" -"\"git config set remote.%s.followRemoteHEAD %s\" вимкне попередженнÑ\n" -"доки віддалений Ñервер не змінить HEAD на щоÑÑŒ інше." +"Ñкщо ви не хочете бачити це повідомленнÑ. Зокрема, виконаннÑ\n" +"\"git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s\"\n" +"вимкне попередженнÑ, доки віддалене Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð½Ðµ змінить HEAD на щоÑÑŒ інше." msgid "multiple branches detected, incompatible with --set-upstream" msgstr "виÑвлено кілька гілок, неÑуміÑних з --set-upstream" @@ -6740,6 +6750,9 @@ msgstr "примуÑово запуÑкати збирач ÑміттÑ, Ð½Ð°Ð²Ñ msgid "repack all other packs except the largest pack" msgstr "перепакувати вÑÑ– пакунки, крім найбільшого" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "Ð¿Ñ€ÐµÑ„Ñ–ÐºÑ Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÐ° з обрізаними обʼєктами" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ gc.logExpiry Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ %s" @@ -7120,7 +7133,7 @@ msgid "show the surrounding function" msgstr "показати навколишню функцію" msgid "read patterns from file" -msgstr "зчитувати шаблони з файлу" +msgstr "читати шаблони з файлу" msgid "match <pattern>" msgstr "зіÑтавлÑти <шаблон>" @@ -7196,7 +7209,7 @@ msgid "write the object into the object database" msgstr "запиÑати об’єкт до бази даних об’єктів" msgid "read the object from stdin" -msgstr "прочитати об’єкт з stdin" +msgstr "читати об’єкт з stdin" msgid "store file as is without filters" msgstr "зберегти файл Ñк Ñ” без фільтрів" @@ -7548,6 +7561,10 @@ msgid "Cannot come back to cwd" msgstr "Ðеможливо повернутиÑÑ Ð´Ð¾ поточної робочої директорії" #, c-format +msgid "bad --pack_header: %s" +msgstr "невірний --pack_header: %s" + +#, c-format msgid "bad %s" msgstr "невірний %s" @@ -8420,10 +8437,6 @@ msgstr "невідомий варіант Ñтратегії: -X%s" msgid "malformed input line: '%s'." msgstr "невірно Ñформований Ñ€Ñдок вводу: \"%s\"." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "неможливо продовжити злиттÑ; отримано брудний результат Ð´Ð»Ñ %d" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<опції>] [<коміт>...]" @@ -9094,7 +9107,7 @@ msgid "Removing note for object %s\n" msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð½Ð¾Ñ‚Ð°Ñ‚ÐºÐ¸ Ð´Ð»Ñ Ð¾Ð±Ê¼Ñ”ÐºÑ‚Ð° %s\n" msgid "read objects from stdin" -msgstr "зчитати обʼєкти з stdin" +msgstr "читати обʼєкти з stdin" msgid "load rewriting config for <command> (implies --stdin)" msgstr "" @@ -9216,7 +9229,7 @@ msgid "attempt to remove non-existent note is not an error" msgstr "Ñпроба видалити неіÑнуючу нотатку не Ñ” помилкою" msgid "read object names from the standard input" -msgstr "зчитати імена обʼєктів зі Ñтандартного вводу" +msgstr "читати імена обʼєктів зі Ñтандартного вводу" msgid "do not remove, show only" msgstr "не видалÑти, тільки показувати" @@ -9246,6 +9259,13 @@ msgstr "" "обʼєктів>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "неприпуÑтима --name-hash-version опціÑ: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "наразі --write-bitmap-index потребує --name-hash-version=1" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9481,7 +9501,7 @@ msgid "do not create an empty pack output" msgstr "не Ñтворювати вивід порожнього пакунка" msgid "read revision arguments from standard input" -msgstr "зчитувати аргументи ревізії зі Ñтандартного вводу" +msgstr "читати аргументи ревізії зі Ñтандартного вводу" msgid "limit the objects to those that are not yet packed" msgstr "обмежувати обʼєкти тільки тими, Ñкі ще не запаковані" @@ -9570,6 +9590,10 @@ msgstr "протокол" msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "вилучити вÑÑ– налаштовані uploadpack.blobpackfileuri з цим протоколом" +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"викориÑтовувати вказану name-hash функцію Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿ÑƒÐ²Ð°Ð½Ð½Ñ Ñхожих обʼєктів" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "глибина дельта ланцюжка %d занадто глибока, примуÑове %d" @@ -10826,8 +10850,8 @@ msgstr "не вказано журнал поÑилань Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð msgid "invalid ref format: %s" msgstr "неприпуÑтимий формат поÑиланнÑ: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<формат> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<формат> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -10838,6 +10862,9 @@ msgstr "вкажіть формат поÑиланнÑ, в Ñкий потріб msgid "perform a non-destructive dry-run" msgstr "виконати неруйнівний пробний запуÑк" +msgid "drop reflogs entirely during the migration" +msgstr "повніÑтю видалити журнал поÑилань під Ñ‡Ð°Ñ Ð¼Ñ–Ð³Ñ€Ð°Ñ†Ñ–Ñ—" + msgid "missing --ref-format=<format>" msgstr "відÑутній --ref-format=<формат>" @@ -11312,8 +11339,14 @@ msgstr "Ðе видалÑтиме вÑÑ– URL-адреÑи, що не Ñ” приз msgid "be verbose; must be placed before a subcommand" msgstr "розгорнутий вивід; має ÑтоÑти перед підкомандою" -msgid "git repack [<options>]" -msgstr "git repack [<опції>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<н>] [--depth=<н>] [--threads=<н>] [--keep-pack=<назва-пакунка>]\n" +"[--write-midx] [--name-hash-version=<н>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11388,6 +11421,10 @@ msgstr "передати --no-reuse-delta до git-pack-objects" msgid "pass --no-reuse-object to git-pack-objects" msgstr "передати --no-reuse-object до git-pack-objects" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "вказати верÑÑ–ÑŽ назви хешу Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿ÑƒÐ²Ð°Ð½Ð½Ñ Ñхожих обʼєктів за шлÑхом" + msgid "do not run git-update-server-info" msgstr "не запуÑкати git-update-server-info" @@ -11437,9 +11474,6 @@ msgstr "знайти геометричну прогреÑÑ–ÑŽ з факторо msgid "write a multi-pack index of the resulting packs" msgstr "запиÑати multi-pack-index результуючих пакунків" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "Ð¿Ñ€ÐµÑ„Ñ–ÐºÑ Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÐ° з обрізаними обʼєктами" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "Ð¿Ñ€ÐµÑ„Ñ–ÐºÑ Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÐ° з відфільтрованими обʼєктами" @@ -11656,9 +11690,6 @@ msgstr "тільки один шаблон може бути заданий з - msgid "need some commits to replay" msgstr "потрібні деÑкі коміти Ð´Ð»Ñ Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ" -msgid "--onto and --advance are incompatible" -msgstr "--onto та --advance неÑуміÑні" - msgid "all positive revisions given must be references" msgstr "вÑÑ– надані позитивні ревізії мають бути поÑиланнÑми" @@ -12135,7 +12166,7 @@ msgid "use stateless RPC protocol" msgstr "викориÑтовувати протокол RPC без Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñтану" msgid "read refs from stdin" -msgstr "прочитати поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð· stdin" +msgstr "читати поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð· stdin" msgid "print status from remote helper" msgstr "вивеÑти ÑÑ‚Ð°Ñ‚ÑƒÑ Ð· віддаленого помічника" @@ -13623,7 +13654,7 @@ msgid "with --stdin: input lines are terminated by null bytes" msgstr "з --stdin: вхідні Ñ€Ñдки завершуютьÑÑ Ð½ÑƒÐ»ÑŒÐ¾Ð²Ð¸Ð¼Ð¸ байтами" msgid "read list of paths to be updated from standard input" -msgstr "прочитати ÑпиÑок шлÑхів Ð´Ð»Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ñ– Ñтандартного вводу" +msgstr "читати ÑпиÑок шлÑхів Ð´Ð»Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ñ– Ñтандартного вводу" msgid "add entries from standard input to the index" msgstr "додати запиÑи зі Ñтандартного вводу до індекÑу" @@ -14335,8 +14366,11 @@ msgstr "Імпортувати GNU Arch Ñховище до Git" msgid "Create an archive of files from a named tree" msgstr "Створити архів файлів з названого дерева" +msgid "Download missing objects in a partial clone" +msgstr "Завантажити відÑутні обʼєкти у чаÑтковому клонуванні" + msgid "Use binary search to find the commit that introduced a bug" -msgstr "ВикориÑтати бінарний пошук, щоб знайти коміт, Ñкий Ð²Ð½Ñ–Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÑƒ" +msgstr "ВикориÑтати бінарний пошук, щоб знайти коміт, Ñкий ввів помилку" msgid "Show what revision and author last modified each line of a file" msgstr "Показати, Ñка Ñ€ÐµÐ²Ñ–Ð·Ñ–Ñ Ñ‚Ð° автор воÑтаннє змінювали кожен Ñ€Ñдок файлу" @@ -15728,7 +15762,7 @@ msgstr "помилка протоколу: неочікувані Ð·Ð´Ñ–Ð±Ð½Ð¾Ñ #, c-format msgid "protocol error: expected shallow sha-1, got '%s'" -msgstr "помилка протоколу: очікувалоÑÑŒ неглибоке sha-1, отримано \"%s\"" +msgstr "помилка протоколу: очікувалоÑÑŒ поверхневе sha-1, отримано \"%s\"" msgid "repository on the other end cannot be shallow" msgstr "Ñховище на іншому кінці не може бути неглибоким" @@ -16256,6 +16290,12 @@ msgstr "неприпуÑтимий аргумент до %s" msgid "invalid regex given to -I: '%s'" msgstr "неприпуÑтимий regex, переданий до -I: \"%s\"" +msgid "-G requires a non-empty argument" +msgstr "-G потребує непорожнього аргументу" + +msgid "-S requires a non-empty argument" +msgstr "-S потребує непорожнього аргументу" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ параметр опції --submodule: \"%s\"" @@ -17247,7 +17287,7 @@ msgstr "" #, c-format msgid "git: '%s' is not a git command. See 'git --help'." -msgstr "git: \"%s\" не Ñ” командою git. Ð”Ð¸Ð²Ñ–Ñ‚ÑŒÑ git --help." +msgstr "git: \"%s\" не Ñ” командою git. ДивітьÑÑ git --help." msgid "Uh oh. Your system reports no Git commands at all." msgstr "Ой-ой. Ваша ÑиÑтема повідомлÑÑ” про повну відÑутніÑть Git команд." @@ -18448,6 +18488,10 @@ msgid "unable to write file %s" msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати файл %s" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати файл %s, Ñкий поÑтійно зникає" + +#, c-format msgid "unable to set permission to '%s'" msgstr "не вдалоÑÑ Ð²Ñтановити дозволи Ð´Ð»Ñ \"%s\"" @@ -19020,6 +19064,52 @@ msgstr "невідомий перемикач \"%c\"" msgid "unknown non-ascii option in string: `%s'" msgstr "невідомий non-ascii параметр у Ñ€Ñдку: \"%s\"" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -19107,6 +19197,21 @@ msgid "failed to parse %s" msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ %s" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ð¹Ñ‚Ð¸ дочірні елементи дерева %s: не знайдено" + +#, c-format +msgid "failed to find object %s" +msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ обʼєкт %s" + +#, c-format +msgid "failed to find tag %s" +msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ тег %s" + +msgid "failed to setup revision walk" +msgstr "не вдалоÑÑ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ñ‚Ð¸ Ð¿Ñ€Ð¾Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ ревізіÑм" + +#, c-format msgid "Could not make %s writable by group" msgstr "Ðе вдалоÑÑ Ð·Ñ€Ð¾Ð±Ð¸Ñ‚Ð¸ %s доÑтупним Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу групою" @@ -19255,6 +19360,22 @@ msgstr "назва віддаленого promisor не може починатРmsgid "could not fetch %s from promisor remote" msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ %s з віддаленого promisor" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "відоме віддалене Ñховище з імʼÑм \"%s\" має URL \"%s\" заміÑть \"%s\"" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "невідоме Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ \"%s\" Ð´Ð»Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð° конфігурації \"%s\"" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "невідомий елемент \"%s\" з віддаленої інформації" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "прийнÑтий віддалений promisor \"%s\" не знайдено" + msgid "object-info: expected flush after arguments" msgstr "object-info: очікувавÑÑ flush піÑÐ»Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ñ–Ð²" @@ -20084,6 +20205,14 @@ msgid "invalid refspec '%s'" msgstr "неприпуÑтимий визначник поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\"" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "шаблон \"%s\" не має \"*\"" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "заміна \"%s\" не має \"*\"" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "неприпуÑтимі лапки у значенні push-опції: \"%s\"" @@ -20132,7 +20261,7 @@ msgstr "віддалений Ñервер надіÑлав неочікуванРmsgid "unable to rewind rpc post data - try increasing http.postBuffer" msgstr "" -"не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ñ‚Ð°Ñ‚Ð¸ вперед rpc post дані - Ñпробуйте збільшити " +"не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ñ‚Ð°Ñ‚Ð¸ вперед rpc post дані - Ñпробуйте збільшити " "http.postBuffer" #, c-format @@ -20207,8 +20336,31 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: невідома команда \"%s\" з git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ð³Ð¾ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð· \"%s/%s\", Ñкий номіновано на вилученнÑ.\n" +"\n" +"Якщо ви вÑе ще викориÑтовуєте директорію \"remotes/\", рекомендуєтьÑÑ\n" +"перейти віддалені Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð½Ð° оÑнові конфігурації:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"Якщо ви не можете цього зробити, будь лаÑка, дайте нам знати, чому ви вÑе ще " +"викориÑтовуєте Ñ—Ñ—\n" +"надіÑлавши лиÑта на адреÑу <git@vger.kernel.org>." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" -msgstr "ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ñ— конфігураціі не може починатиÑÑ Ð· \"/\": %s" +msgstr "Ñкорочене ім'Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ñ— конфігураціі не може починатиÑÑ Ð· \"/\": %s" msgid "more than one receivepack given, using the first" msgstr "надано більше одного пакунка Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ, викориÑтано перший" @@ -20241,14 +20393,6 @@ msgid "%s tracks both %s and %s" msgstr "%s відÑтежує Ñк %s, так Ñ– %s" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "ключ \"%s\" шаблону не міÑтив '*'" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ \"%s\" шаблону не міÑтить '*'" - -#, c-format msgid "src refspec %s does not match any" msgstr "визначник поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð¶ÐµÑ€ÐµÐ»Ð° %s не збігаєтьÑÑ Ð· жодним" @@ -22179,6 +22323,27 @@ msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "" "кількіÑть запиÑів у дереві кешу, Ñкі потрібно анулювати (за замовчуваннÑм 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <опції> -- <опції-ревізії>." + +msgid "toggle inclusion of blob objects" +msgstr "перемикач Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¾Ð±Ê¼Ñ”ÐºÑ‚Ñ–Ð² blob" + +msgid "toggle inclusion of commit objects" +msgstr "перемикач Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¾Ð±Ê¼Ñ”ÐºÑ‚Ñ–Ð² коміту" + +msgid "toggle inclusion of tag objects" +msgstr "перемикач Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¾Ð±Ê¼Ñ”ÐºÑ‚Ñ–Ð² тегів" + +msgid "toggle inclusion of tree objects" +msgstr "перемикач Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¾Ð±Ê¼Ñ”ÐºÑ‚Ñ–Ð² дерева" + +msgid "toggle pruning of uninteresting paths" +msgstr "перемикач Ð¾Ð±Ñ€Ñ–Ð·Ð°Ð½Ð½Ñ Ð½ÐµÑ†Ñ–ÐºÐ°Ð²Ð¸Ñ… шлÑхів" + +msgid "read a pattern list over stdin" +msgstr "читати ÑпиÑок шаблонів через stdin" + #, c-format msgid "commit %s is not marked reachable" msgstr "коміт %s не позначений Ñк доÑÑжний" @@ -22819,6 +22984,10 @@ msgstr "помилка: " msgid "warning: " msgstr "попередженнÑ: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() завершивÑÑ Ð½ÐµÐ²Ð´Ð°Ð»Ð¾ з помилкою \"%s\" (%d)\n" + msgid "Fetching objects" msgstr "ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¾Ð±Ê¼Ñ”ÐºÑ‚Ñ–Ð²" @@ -11,7 +11,7 @@ # VÅ© Tiến Hưng <newcomerminecraft@gmail.com>, 2024-2025. # --- # BẢNG THUẬT NGá»® / TERMINOLOGY -# Updated: 2024-07-26, git 2.46 +# Updated: 2025-03-06, git 2.49 # # Ghi chú: # - Bảng thuáºt ngữ nà y chưa hoà n thiện. @@ -59,15 +59,17 @@ # | (v.) rebase | cải tổ | # | (v.) squash | squash | # | (v.) amend | tu bổ | +# | (n.) revision | cải biên | +# | (n.) repo/repository | kho chứa | # | | | # | ... TODO ... | | # +------------------------------------------------------------------+ msgid "" msgstr "" -"Project-Id-Version: git 2.48\n" +"Project-Id-Version: git 2.49\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-23 18:57+0000\n" -"PO-Revision-Date: 2025-01-05 01:20+0700\n" +"POT-Creation-Date: 2025-03-05 22:57+0000\n" +"PO-Revision-Date: 2025-03-06 08:20+0700\n" "Last-Translator: VÅ© Tiến Hưng <newcomerminecraft@gmail.com>\n" "Language-Team: Vietnamese <https://github.com/Nekosha/git-po>\n" "Language: vi\n" @@ -1601,7 +1603,7 @@ msgid "" "git bisect cannot work properly in this case.\n" "Maybe you mistook %s and %s revs?\n" msgstr "" -"Má»™t số Ä‘iểm xét duyệt %s không phải tổ tiên cá»§a Ä‘iểm xét duyệt %s.\n" +"Má»™t số lần cải biên %s không phải tổ tiên cá»§a lần cải biên %s.\n" "git bisect không thể là m việc đúng trong trưá»ng hợp nà y.\n" "Liệu có phải bạn nhầm lẫn các Ä‘iểm %s và %s không?\n" @@ -1621,7 +1623,7 @@ msgstr "Äang bisect: gốc hòa trá»™n cần phải được kiểm tra\n" #, c-format msgid "a %s revision is needed" -msgstr "cần má»™t Ä‘iểm xét duyệt %s" +msgstr "cần lần cải biên %s" #, c-format msgid "could not create file '%s'" @@ -1661,7 +1663,7 @@ msgstr[0] "(cần khoảng chừng %d bước)" #, c-format msgid "Bisecting: %d revision left to test after this %s\n" msgid_plural "Bisecting: %d revisions left to test after this %s\n" -msgstr[0] "Bisecting: còn %d Ä‘iểm xét duyệt để kiểm tra %s\n" +msgstr[0] "Bisecting: còn %d lần cải biên để kiểm tra %s\n" msgid "--contents and --reverse do not blend well." msgstr "tùy chá»n --contents và --reverse không nên Ä‘i vá»›i nhau." @@ -1671,7 +1673,7 @@ msgstr "" "cùng sá» dụng --reverse và --first-parent cần chỉ định lần chuyển giao cuối" msgid "revision walk setup failed" -msgstr "cà i đặt việc di chuyển qua các Ä‘iểm xét duyệt gặp lá»—i" +msgstr "cà i đặt việc duyệt qua các lần cải biên gặp lá»—i" msgid "" "--reverse --first-parent together require range along first-parent chain" @@ -2371,6 +2373,18 @@ msgstr "git archive: lá»—i giao thức" msgid "git archive: expected a flush" msgstr "git archive: cần flush dữ liệu" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "không thể tải checkout thưa" + +msgid "Minimum number of objects to request at a time" +msgstr "Số đối tượng tối thiểu má»—i lần yêu cầu" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Chỉ lấy vỠđối tượng còn thiếu trong checkout thưa hiện tại" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -2441,7 +2455,7 @@ msgstr "Äối số bisect_write sai: %s" #, c-format msgid "couldn't get the oid of the rev '%s'" -msgstr "không thể lấy oid cá»§a Ä‘iểm xét duyệt '%s'" +msgstr "không thể lấy oid cá»§a lần cải biên '%s'" #, c-format msgid "couldn't open the file '%s'" @@ -2466,7 +2480,7 @@ msgid "" "You can use \"git bisect %s\" and \"git bisect %s\" for that." msgstr "" "Bạn cần bắt đầu bằng lệnh \"git bisect start\".\n" -"Bạn sau đó cần phải chỉ cho tôi Ãt nhất má»™t Ä‘iểm xét duyệt %s và má»™t %s.\n" +"Bạn sau đó cần phải chỉ cho tôi Ãt nhất má»™t lần cải biên %s và má»™t %s.\n" "Bạn có thể sá» dụng \"git bisect %s\" và \"git bisect %s\" cho chúng." #, c-format @@ -2526,7 +2540,7 @@ msgstr "không nháºn ra tuỳ chá»n: '%s'" #, c-format msgid "'%s' does not appear to be a valid revision" -msgstr "'%s' không có vẻ như là má»™t Ä‘iểm xét duyệt hợp lệ" +msgstr "'%s' không có vẻ như là má»™t lần cải biên hợp lệ" msgid "bad HEAD - I need a HEAD" msgstr "sai HEAD - Tôi cần má»™t HEAD" @@ -2587,11 +2601,11 @@ msgstr "bisect chạy gặp lá»—i: không đưa ra lệnh." #, c-format msgid "unable to verify %s on good revision" -msgstr "không thể xác nháºn '%s' trên Ä‘iểm xét duyệt tốt" +msgstr "không thể xác nháºn '%s' trên lần cải biên tốt" #, c-format msgid "bogus exit code %d for good revision" -msgstr "mã trả vá» %d bất thưá»ng cho Ä‘iểm xét duyệt tốt" +msgstr "mã trả vá» %d bất thưá»ng cho lần cải biên tốt" #, c-format msgid "bisect run failed: exit code %d from %s is < 0 or >= 128" @@ -2658,7 +2672,7 @@ msgstr "phải kết thúc bằng má»™t mà u" #, c-format msgid "cannot find revision %s to ignore" -msgstr "không thể tìm thấy Ä‘iểm xét duyệt %s để bá» qua" +msgstr "không thể tìm thấy lần cải biên %s để bá» qua" msgid "show blame entries as we find them, incrementally" msgstr "hiển thị các mục 'blame' theo thá»i gian, tăng dần" @@ -2717,7 +2731,7 @@ msgid "ignore <rev> when blaming" msgstr "bá» qua <rev> khi blame" msgid "ignore revisions from <file>" -msgstr "bá» qua các Ä‘iểm xét duyệt từ <táºp tin>" +msgstr "bá» qua các lần cải biên từ <táºp tin>" msgid "color redundant metadata from previous line differently" msgstr "tô mà u khác cho siêu dữ liệu dư thừa từ dòng trước" @@ -2730,7 +2744,7 @@ msgstr "tiêu thụ thêm tà i nguyên để tìm kiếm tốt hÆ¡n nữa" msgid "use revisions from <file> instead of calling git-rev-list" msgstr "" -"sá» dụng các Ä‘iểm xét duyệt (revision) từ <táºp tin> thay vì gá»i git-rev-list" +"sá» dụng các lần cải biên (revision) từ <táºp tin> thay vì gá»i git-rev-list" msgid "use <file>'s contents as the final image" msgstr "sá» dụng ná»™i dung cá»§a <táºp tin> như là ảnh cuối cùng" @@ -3114,10 +3128,6 @@ msgstr "" msgid "git version:\n" msgstr "phiên bản git:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() gặp lá»—i '%s' (%d)\n" - msgid "compiler info: " msgstr "thông tin trình biên dịch: " @@ -3710,7 +3720,7 @@ msgstr[0] "" "\n" msgid "internal error in revision walk" -msgstr "lá»—i ná»™i bá»™ trong khi di chuyển qua các Ä‘iểm xét duyệt" +msgstr "lá»—i ná»™i bá»™ trong khi di chuyển qua các lần cải biên" msgid "Previous HEAD position was" msgstr "Vị trà trước kia cá»§a HEAD là " @@ -4116,8 +4126,91 @@ msgstr "" "clean.requireForce được đặt thà nh true và không có tuỳ chá»n -f; từ chối dá»n " "dẹp" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<các tùy chá»n>] [--] <kho> [<t.mục>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "thông tin: không thể thêm thay thế cho '%s': %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "gặp lá»—i khi stat '%s'" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s có tồn tại nhưng lại không phải là má»™t thư mục" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' là liên kết má»m, từ chối sao chép vá»›i --local" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "gặp lá»—i khi bắt đầu lặp qua '%s'" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "liên kết má»m '%s' đã tồn tại, từ chối sao chép vá»›i --local" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "gặp lá»—i khi unlink '%s'" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "không thể kiểm tra liên kết cứng '%s'" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "liên kết cứng '%s' khác vá»›i nguồn" + +#, c-format +msgid "failed to create link '%s'" +msgstr "gặp lá»—i khi tạo liên kết má»m %s" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "gặp lá»—i khi sao chép táºp tin tá»›i '%s'" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "gặp lá»—i khi lặp qua '%s'" + +#, c-format +msgid "done.\n" +msgstr "hoà n tất.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Việc nhân bản thà nh công, nhưng checkout gặp lá»—i.\n" +"Kiểm tra xem cái gì đã được checkout bằng lệnh 'git status'\n" +"và thá» lại vá»›i lệnh 'git restore --source=HEAD :/'\n" + +msgid "remote did not send all necessary objects" +msgstr "máy chá»§ đã không gá»i tất cả các đối tượng cần thiết" + +#, c-format +msgid "unable to update %s" +msgstr "không thể cáºp nháºt %s" + +msgid "failed to initialize sparse-checkout" +msgstr "gặp lá»—i khi khởi tạo sparse-checkout" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "HEAD ở máy chá»§ chỉ đến ref không tồn tại, không thể checkout" + +msgid "unable to checkout working tree" +msgstr "không thể checkout cây là m việc" + +msgid "unable to write parameters to config file" +msgstr "không thể ghi các tham số và o táºp tin cấu hình" + +msgid "cannot repack to clean up" +msgstr "không thể đóng gói để dá»n dẹp" + +msgid "cannot unlink temporary alternates file" +msgstr "không thể bá» liên kết táºp tin thay thế tạm thá»i" msgid "don't clone shallow repository" msgstr "đừng nhân bản từ kho nông" @@ -4170,6 +4263,9 @@ msgstr "dùng <tên> thay cho 'origin' để theo dõi thượng nguồn" msgid "checkout <branch> instead of the remote's HEAD" msgstr "checkout <nhánh> thay cho HEAD cá»§a máy chá»§" +msgid "clone single revision <rev> and check out" +msgstr "nhân bản chỉ lần cải biên <rev> and check out" + msgid "path to git-upload-pack on the remote" msgstr "đưá»ng dẫn đến git-upload-pack trên máy chá»§" @@ -4191,10 +4287,8 @@ msgstr "là m sâu hÆ¡n lịch sá» cá»§a bản sao shallow, loại trừ tham ch msgid "clone only one branch, HEAD or --branch" msgstr "chỉ nhân bản má»™t nhánh, HEAD hoặc --branch" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "" -"đứng có nhân bản bất kỳ nhánh nà o, và là m cho những lần lấy vá» sau không " -"theo chúng nữa" +msgid "clone tags, and make later fetches not to follow them" +msgstr "nhân bản thẻ, và là m cho những lần lấy vá» sau không theo chúng nữa" msgid "any cloned submodules will be shallow" msgstr "má»i mô-Ä‘un-con nhân bản sẽ là shallow (nông)" @@ -4235,95 +4329,8 @@ msgstr "uri" msgid "a URI for downloading bundles before fetching from origin remote" msgstr "URI để tải xuống bundle trước khi lấy vá» từ máy chá»§ origin" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "thông tin: không thể thêm thay thế cho '%s': %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "gặp lá»—i khi stat '%s'" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s có tồn tại nhưng lại không phải là má»™t thư mục" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' là liên kết má»m, từ chối sao chép vá»›i --local" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "gặp lá»—i khi bắt đầu lặp qua '%s'" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "liên kết má»m '%s' đã tồn tại, từ chối sao chép vá»›i --local" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "gặp lá»—i khi unlink '%s'" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "không thể kiểm tra liên kết cứng '%s'" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "liên kết cứng '%s' khác vá»›i nguồn" - -#, c-format -msgid "failed to create link '%s'" -msgstr "gặp lá»—i khi tạo liên kết má»m %s" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "gặp lá»—i khi sao chép táºp tin tá»›i '%s'" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "gặp lá»—i khi lặp qua '%s'" - -#, c-format -msgid "done.\n" -msgstr "hoà n tất.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Việc nhân bản thà nh công, nhưng checkout gặp lá»—i.\n" -"Kiểm tra xem cái gì đã được checkout bằng lệnh 'git status'\n" -"và thá» lại vá»›i lệnh 'git restore --source=HEAD :/'\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Không tìm thấy nhánh máy chá»§ %s để nhân bản (clone)." - -msgid "remote did not send all necessary objects" -msgstr "máy chá»§ đã không gá»i tất cả các đối tượng cần thiết" - -#, c-format -msgid "unable to update %s" -msgstr "không thể cáºp nháºt %s" - -msgid "failed to initialize sparse-checkout" -msgstr "gặp lá»—i khi khởi tạo sparse-checkout" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "HEAD ở máy chá»§ chỉ đến ref không tồn tại, không thể checkout" - -msgid "unable to checkout working tree" -msgstr "không thể checkout cây là m việc" - -msgid "unable to write parameters to config file" -msgstr "không thể ghi các tham số và o táºp tin cấu hình" - -msgid "cannot repack to clean up" -msgstr "không thể đóng gói để dá»n dẹp" - -msgid "cannot unlink temporary alternates file" -msgstr "không thể bá» liên kết táºp tin thay thế tạm thá»i" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<các tùy chá»n>] [--] <kho> [<t.mục>]" msgid "Too many arguments." msgstr "Quá nhiá»u đối số." @@ -4430,6 +4437,10 @@ msgstr "trình váºn chuyển đã báo lá»—i" msgid "Remote branch %s not found in upstream %s" msgstr "Nhánh máy chá»§ %s không tìm thấy trong thượng nguồn %s" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Lần cải biên %s không tìm thấy trong thượng nguồn %s" + msgid "You appear to have cloned an empty repository." msgstr "Bạn hình như là đã nhân bản má»™t kho trống rá»—ng." @@ -4605,7 +4616,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: gặp lá»—i khi Ä‘á»c" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -5576,7 +5587,7 @@ msgstr "" #, c-format msgid "traversed %lu commits\n" -msgstr "đã xuyên %lu qua lần chuyển giao\n" +msgstr "đã chạy qua %lu lần chuyển giao\n" #, c-format msgid "found %i tags; gave up search at %s\n" @@ -6021,8 +6032,8 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Chạy 'git remote set-head %s %s' để là m theo thay đổi, hoặc đặt tuỳ chá»n\n" "'remote.%s.followRemoteHEAD' sang giá trị khác nếu bạn không muốn thấy\n" @@ -6073,7 +6084,7 @@ msgid "" "remote name from which new revisions should be fetched" msgstr "" "chưa chỉ ra kho chứa máy chá»§; xin hãy chỉ định hoặc là URL hoặc\n" -"tên máy chá»§ từ cái mà những Ä‘iểm xét duyệt má»›i có thể được fetch (lấy vá»)" +"tên máy chá»§ từ cái mà những lần cải biên má»›i có thể được fetch (lấy vá»)" msgid "you need to specify a tag name" msgstr "bạn cần chỉ định má»™t tên thẻ" @@ -6167,7 +6178,7 @@ msgid "specify fetch refmap" msgstr "chỉ ra refmap cần lấy vá»" msgid "revision" -msgstr "Ä‘iểm xét duyệt" +msgstr "lần cải biên" msgid "report that we have only objects reachable from this object" msgstr "báo rằng ta chỉ có các đối tượng tiếp cáºn được từ đối tượng nà y" @@ -6705,6 +6716,9 @@ msgstr "buá»™c gc chạy ngay cả khi có tiến trình gc khác Ä‘ang chạy" msgid "repack all other packs except the largest pack" msgstr "đóng gói lại tất cả các gói khác ngoại trừ gói lá»›n nhất" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "tiá»n tố cá»§a gói để lưu gói gồm những đối tượng đã loại bá»" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "gặp lá»—i khi Ä‘á»c giá trị gc.logExpiry %s" @@ -7113,7 +7127,7 @@ msgstr "--no-index hay --untracked không được sá» dụng cùng vá»›i revs" #, c-format msgid "unable to resolve revision: %s" -msgstr "không thể phân giải Ä‘iểm xét duyệt: %s" +msgstr "không thể phân giải lần cải biên: %s" msgid "--untracked not supported with --recurse-submodules" msgstr "tùy chá»n --untracked không được há»— trợ vá»›i --recurse-submodules" @@ -7491,6 +7505,10 @@ msgid "Cannot come back to cwd" msgstr "Không thể quay lại thư mục hiện hà nh" #, c-format +msgid "bad --pack_header: %s" +msgstr "--pack_header sai: %s" + +#, c-format msgid "bad %s" msgstr "%s sai" @@ -7758,10 +7776,10 @@ msgid "failed to find exact merge base" msgstr "gặp lá»—i khi tìm gốc hòa trá»™n chÃnh xác" msgid "base commit should be the ancestor of revision list" -msgstr "lần chuyển giao ná»n không là tổ tiên cá»§a danh sách Ä‘iểm xét duyệt" +msgstr "lần chuyển giao ná»n không là tổ tiên cá»§a danh sách lần cải biên" msgid "base commit shouldn't be in revision list" -msgstr "lần chuyển giao ná»n không được trong danh sách Ä‘iểm xét duyệt" +msgstr "lần chuyển giao ná»n không được trong danh sách lần cải biên" msgid "cannot get patch id" msgstr "không thể lấy mã bản vá" @@ -8356,10 +8374,6 @@ msgstr "không hiểu chiến lược: -X%s" msgid "malformed input line: '%s'." msgstr "dòng đầu và o sai quy cách: '%s'." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "không thể tiếp tục hoà trá»™n; kết quả không hoà n toà n %d" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<các tùy chá»n>] [<commit>...]" @@ -9187,6 +9201,13 @@ msgstr "" "sách-đối-tượng>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "tùy chá»n --name-hash-version không hợp lệ: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "--write-bitmap-index hiện cần --name-hash-version=1" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9363,7 +9384,7 @@ msgstr "không phải má»™t rev '%s'" #, c-format msgid "bad revision '%s'" -msgstr "Ä‘iểm xem xét sai '%s'" +msgstr "lần cải biên sai '%s'" msgid "unable to add recent objects" msgstr "không thể thêm các đối tượng má»›i dùng" @@ -9509,6 +9530,9 @@ msgstr "giao thức" msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "loại trừ bất kỳ cấu hình uploadpack.blobpackfileuri vá»›i giao thức nà y" +msgid "use the specified name-hash function to group similar objects" +msgstr "dùng hà m băm nà y để nhóm các đối tượng giống nhau" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "mức delta chain %d là quá sâu, buá»™c dùng %d" @@ -10261,7 +10285,7 @@ msgid "" msgstr "" "\n" "git gặp phải má»™t lá»—i trong khi Ä‘ang chuẩn bị các bản vá để diá»…n lại\n" -"những Ä‘iểm xét duyệt nà y:\n" +"những lần cải biên nà y:\n" "\n" " %s\n" "\n" @@ -10750,8 +10774,8 @@ msgstr "chưa chỉ ra reflog để xóa" msgid "invalid ref format: %s" msgstr "định dạng tham chiếu không hợp lệ: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<định dạng> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<định dạng> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -10762,6 +10786,9 @@ msgstr "chỉ định định dạng tham chiếu để chuyển đổi sang" msgid "perform a non-destructive dry-run" msgstr "chạy thá» mà không thay đổi gì" +msgid "drop reflogs entirely during the migration" +msgstr "bá» reflog khi chuyển đổi" + msgid "missing --ref-format=<format>" msgstr "thiếu --ref-format=<định dạng>" @@ -11216,8 +11243,14 @@ msgstr "Sẽ không xóa những địa chỉ URL không-push" msgid "be verbose; must be placed before a subcommand" msgstr "chi tiết; phải được đặt trước má»™t lệnh-con" -msgid "git repack [<options>]" -msgstr "git repack [<các tùy chá»n>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<tên-pack>]\n" +"[--write-midx] [--name-hash-version=<n>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11293,6 +11326,10 @@ msgstr "chuyển --no-reuse-delta cho git-pack-objects" msgid "pass --no-reuse-object to git-pack-objects" msgstr "chuyển --no-reuse-object cho git-pack-objects" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "phiên bản hà m băm để nhóm đối tượng giống nhau theo đưá»ng dẫn" + msgid "do not run git-update-server-info" msgstr "không chạy git-update-server-info" @@ -11341,9 +11378,6 @@ msgstr "tìm má»™t tiến trình hình há»c vá»›i hệ số <N>" msgid "write a multi-pack index of the resulting packs" msgstr "ghi chỉ mục 'multi-pack' cá»§a các gói kết quả" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "tiá»n tố cá»§a gói để lưu gói gồm những đối tượng đã loại bá»" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "tiá»n tố cá»§a gói để lưu gói gồm những đối tượng đã lá»c bá»" @@ -11560,11 +11594,8 @@ msgstr "chỉ được chỉ định má»™t mẫu cùng vá»›i tùy chá»n -l" msgid "need some commits to replay" msgstr "cần các chuyển giao để phát lại" -msgid "--onto and --advance are incompatible" -msgstr "--onto và --advance xung khắc" - msgid "all positive revisions given must be references" -msgstr "má»i Ä‘iểm xét duyệt cá»™ng thêm phải là tên tham chiếu" +msgstr "má»i lần cải biên cá»™ng thêm phải là tên tham chiếu" msgid "argument to --advance must be a reference" msgstr "tham số cho --advance phải là tham chiếu" @@ -11610,11 +11641,11 @@ msgid "" "some rev walking options will be overridden as '%s' bit in 'struct rev_info' " "will be forced" msgstr "" -"má»™t số tuỳ chá»n duyệt qua Ä‘iểm xét duyệt sẽ bị bá» qua do bit '%s' trong " +"má»™t số tuỳ chá»n duyệt qua lần cải biên sẽ bị bá» qua do bit '%s' trong " "'struct rev_info' bị ép báºt/tắt" msgid "error preparing revisions" -msgstr "gặp lá»—i khi chuẩn bị các Ä‘iểm xét duyệt" +msgstr "gặp lá»—i khi chuẩn bị các lần cải biên" msgid "replaying down to root commit is not supported yet!" msgstr "chưa há»— trợ phát lại đến lần chuyển giao gốc!" @@ -11709,7 +11740,7 @@ msgstr "chỉ ghi lại những đưá»ng dẫn thá»±c sá»± sẽ được thêm #, c-format msgid "Failed to resolve '%s' as a valid revision." -msgstr "Gặp lá»—i khi phân giải '%s' thà nh Ä‘iểm xét duyệt hợp lệ." +msgstr "Gặp lá»—i khi phân giải '%s' thà nh lần cải biên hợp lệ." #, c-format msgid "Failed to resolve '%s' as a valid tree." @@ -11742,7 +11773,7 @@ msgstr "" #, c-format msgid "Could not reset index file to revision '%s'." -msgstr "Không thể đặt lại (reset) chỉ mục thà nh Ä‘iểm xét duyệt '%s'." +msgstr "Không thể đặt lại (reset) chỉ mục thà nh lần cải biên '%s'." msgid "Could not write new index file." msgstr "Không thể ghi táºp tin chỉ mục má»›i." @@ -11784,7 +11815,7 @@ msgid "missing opt-spec before option flags" msgstr "thiếu opt-spec trước các tuỳ chá»n" msgid "Needed a single revision" -msgstr "Cần má»™t Ä‘iểm xét duyệt đơn" +msgstr "Cần má»™t lần cải biên đơn" msgid "" "git rev-parse --parseopt [<options>] -- [<args>...]\n" @@ -12160,7 +12191,7 @@ msgstr "không có tham chiếu nà o như thế %s" #, c-format msgid "cannot handle more than %d rev." msgid_plural "cannot handle more than %d revs." -msgstr[0] "không thể xá» lý nhiá»u hÆ¡n %d Ä‘iểm xét duyệt." +msgstr[0] "không thể xá» lý nhiá»u hÆ¡n %d lần cải biên." #, c-format msgid "'%s' is not a valid ref." @@ -12438,7 +12469,7 @@ msgstr "'%s' không phải là lần chuyển giao kiểu-stash" #, c-format msgid "Too many revisions specified:%s" -msgstr "Chỉ ra quá nhiá»u Ä‘iểm xét duyệt: %s" +msgstr "Chỉ ra quá nhiá»u lần cải biên: %s" msgid "No stash entries found." msgstr "Không tìm thấy các mục tạm cất (stash) nà o." @@ -12742,7 +12773,7 @@ msgstr "" "dẫn>]" msgid "could not fetch a revision for HEAD" -msgstr "không thể lấy vá» má»™t Ä‘iểm xem xét cho HEAD" +msgstr "không thể lấy vá» má»™t lần cải biên cho HEAD" #, c-format msgid "Synchronizing submodule url for '%s'\n" @@ -12977,8 +13008,7 @@ msgstr "" #, c-format msgid "Unable to find current revision in submodule path '%s'" -msgstr "" -"Không tìm thấy Ä‘iểm xét duyệt hiện hà nh trong đưá»ng dẫn mô-Ä‘un-con '%s'" +msgstr "Không tìm thấy lần cải biên hiện hà nh trong đưá»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Unable to fetch in submodule path '%s'" @@ -12986,7 +13016,7 @@ msgstr "Không thể lấy vá» trong đưá»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Unable to find %s revision in submodule path '%s'" -msgstr "Không tìm thấy Ä‘iểm xét duyệt %s trong đưá»ng dẫn mô-Ä‘un-con '%s'" +msgstr "Không tìm thấy lần cải biên %s trong đưá»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Failed to recurse into submodule path '%s'" @@ -13017,8 +13047,7 @@ msgid "use the 'rebase' update strategy" msgstr "dùng chiến lược hòa trá»™n 'rebase'" msgid "create a shallow clone truncated to the specified number of revisions" -msgstr "" -"tạo má»™t bản sao nông được cắt ngắn thà nh số lượng Ä‘iểm xét duyệt đã cho" +msgstr "tạo má»™t bản sao nông được cắt ngắn thà nh số lượng lần cải biên đã cho" msgid "parallel jobs" msgstr "công việc đồng thá»i" @@ -14190,6 +14219,9 @@ msgstr "Nháºp má»™t kho GNU Arch và o má»™t kho Git" msgid "Create an archive of files from a named tree" msgstr "Tạo má»™t kho nén các táºp tin từ cây là m việc có tên" +msgid "Download missing objects in a partial clone" +msgstr "Tải vá» các đối tượng còn thiếu khi nhân bản má»™t phần" + msgid "Use binary search to find the commit that introduced a bug" msgstr "Tìm kiếm dạng nhị phân để tìm ra lần chuyển giao nà o đưa ra lá»—i" @@ -14727,7 +14759,7 @@ msgid "Git Repository Layout" msgstr "Bố cục kho Git" msgid "Specifying revisions and ranges for Git" -msgstr "Chỉ định Ä‘iểm xét duyệt và vùng cho Git" +msgstr "Chỉ định lần cải biên và vùng cho Git" msgid "Mounting one repository inside another" msgstr "Gắn má»™t kho chứa và o trong má»™t cái khác" @@ -15482,7 +15514,7 @@ msgstr "tham chiếu '%s' không chỉ đến má»™t blob nà o cả" #, c-format msgid "unable to resolve config blob '%s'" -msgstr "không thể phân giải Ä‘iểm xét duyệt '%s'" +msgstr "không thể phân giải lần cải biên '%s'" msgid "unable to parse command-line config" msgstr "không thể Ä‘á»c cấu hình dòng lệnh" @@ -16106,6 +16138,12 @@ msgstr "tham số cho %s không hợp lệ" msgid "invalid regex given to -I: '%s'" msgstr "đưa cho -I biểu thức chÃnh quy không hợp lệ: '%s'" +msgid "-G requires a non-empty argument" +msgstr "-G cần má»™t tham số" + +msgid "-S requires a non-empty argument" +msgstr "-S cần má»™t tham số" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "gặp lá»—i khi Ä‘á»c đối số tùy chá»n --submodule: '%s'" @@ -18275,6 +18313,10 @@ msgid "unable to write file %s" msgstr "không thể ghi táºp tin %s" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "không thể ghi và o táºp tin biến mất liên tục %s" + +#, c-format msgid "unable to set permission to '%s'" msgstr "không thể đặt quyá»n thà nh '%s'" @@ -18735,7 +18777,7 @@ msgstr "checksum không hợp lệ" #, c-format msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>" -msgstr "vị trà mục xét duyệt không hợp lệ %<PRIu64>: %<PRIu32> != %<PRIu32>" +msgstr "vị trà mục cải biên không hợp lệ %<PRIu64>: %<PRIu32> != %<PRIu32>" msgid "multi-pack-index reverse-index chunk is the wrong size" msgstr "chunk chỉ mục ngược cá»§a chỉ mục Ä‘a gói có kÃch thước sai" @@ -18833,6 +18875,52 @@ msgstr "không hiểu tùy chá»n '%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "không hiểu tùy chá»n non-ascii trong chuá»—i: '%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -18920,6 +19008,21 @@ msgid "failed to parse %s" msgstr "gặp lá»—i khi Ä‘á»c cú pháp %s" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "gặp lá»—i khi duyệt nhánh cá»§a cây %s: không tìm thấy" + +#, c-format +msgid "failed to find object %s" +msgstr "gặp lá»—i khi tìm đối tượng '%s'." + +#, c-format +msgid "failed to find tag %s" +msgstr "gặp lá»—i khi tìm thẻ %s" + +msgid "failed to setup revision walk" +msgstr "gặp lá»—i khi thiết láºp duyệt lần cải biên" + +#, c-format msgid "Could not make %s writable by group" msgstr "Không thể là m %s được ghi bởi nhóm" @@ -19063,6 +19166,22 @@ msgstr "tên máy chá»§ promisor không thể bắt đầu bằng '/': %s" msgid "could not fetch %s from promisor remote" msgstr "không thể tải %s từ máy chá»§ promisor" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "có máy chá»§ '%s' nhưng vá»›i url '%s' thay vì '%s'" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "không hiểu giá trị '%s' cho cho cấu hình '%s'" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "không hiểu phần '%s' từ thông tin máy chá»§" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "không tìm thấy accepted promisor remote '%s'" + msgid "object-info: expected flush after arguments" msgstr "object-info: cần đẩy dữ liệu lên đĩa sau các tham số" @@ -19750,7 +19869,7 @@ msgid "refusing to update ref with bad name '%s'" msgstr "từ chối cáºp nháºt tham chiếu vá»›i tên sai '%s'" msgid "refusing to force and skip creation of reflog" -msgstr "từ chối bá» qua việc tạo log tham chiếu" +msgstr "từ chối bá» qua việc tạo reflog" #, c-format msgid "update_ref failed for ref '%s': %s" @@ -19884,6 +20003,14 @@ msgid "invalid refspec '%s'" msgstr "refspec không hợp lệ '%s'" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "giá trị '%s' không có '*'" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "thay thế '%s' không có '*'" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "sai trÃch dẫn trong giá trị push-option :'%s'" @@ -20003,6 +20130,27 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: không hiểu lệnh '%s' từ git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"Ä‘ang Ä‘á»c máy chá»§ từ \"%s/%s\", đã được đỠcỠđể loại bá».\n" +"Nếu bạn vẫn còn sá» dụng thư mục \"remotes\", chúng tôi khuyên bạn\n" +"hãy chuyển đổi sang sá» dụng máy chá»§ qua táºp tin cấu hình:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"Nếu bạn không thể đổi, hãy cho chúng tôi biết tại sao bạn cần nó\n" +"bằng cách gá»i e-mail đến <git@vger.kernel.org>." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "cấu hình viết tắt máy chá»§ không thể bắt đầu bằng '/': %s" @@ -20037,14 +20185,6 @@ msgid "%s tracks both %s and %s" msgstr "%s theo dõi cả %s và %s" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "khóa '%s' cá»§a mẫu k có '*'" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "giá trị '%s' cá»§a mẫu k có '*'" - -#, c-format msgid "src refspec %s does not match any" msgstr "refspec (đặc tả tham chiếu) nguồn %s không khá»›p bất kỳ cái gì" @@ -20317,7 +20457,7 @@ msgid "update the index with reused conflict resolution if possible" msgstr "cáºp nháºt chỉ mục vá»›i phân giải xung đột dùng lại nếu được" msgid "could not determine HEAD revision" -msgstr "không thể dò tìm Ä‘iểm xét duyệt HEAD" +msgstr "không thể dò tìm lần cải biên HEAD" #, c-format msgid "failed to find tree of %s" @@ -21456,10 +21596,10 @@ msgid "" "Use '--' to separate paths from revisions, like this:\n" "'git <command> [<revision>...] -- [<file>...]'" msgstr "" -"tham số chưa rõ rà ng '%s': chưa biết Ä‘iểm xét duyệt hay đưá»ng dẫn không " -"trong cây là m việc.\n" -"Dùng '--' để ngăn cách các đưá»ng dẫn khá»i Ä‘iểm xét duyệt, như thế nà y:\n" -"'git <lệnh> [<Ä‘iểm xét duyệt>...] -- [<táºp tin>...]'" +"tham số chưa rõ rà ng '%s': chưa biết lần cải biên hay đưá»ng dẫn không trong " +"cây là m việc.\n" +"Dùng '--' để ngăn cách các đưá»ng dẫn khá»i lần cải biên, như thế nà y:\n" +"'git <lệnh> [<lần cải biên>...] -- [<táºp tin>...]'" #, c-format msgid "option '%s' must come before non-option arguments" @@ -21471,9 +21611,9 @@ msgid "" "Use '--' to separate paths from revisions, like this:\n" "'git <command> [<revision>...] -- [<file>...]'" msgstr "" -"tham số chưa rõ rà ng '%s': cả Ä‘iểm xem xét và tên táºp tin.\n" -"Dùng '--' để ngăn cách các đưá»ng dẫn khá»i Ä‘iểm xem xét, như thế nà y:\n" -"'git <lệnh> [<Ä‘iểm xem xét>...] -- [<táºp tin>...]'" +"tham số chưa rõ rà ng '%s': cả lần cải biên và tên táºp tin.\n" +"Dùng '--' để ngăn cách các đưá»ng dẫn khá»i lần cải biên, như thế nà y:\n" +"'git <lệnh> [<lần cải biên>...] -- [<táºp tin>...]'" msgid "unable to set up work tree using invalid config" msgstr "không thể thiết láºp thư mục là m việc vá»›i cấu hình không hợp lệ" @@ -21935,6 +22075,27 @@ msgstr "dá»n cây nhá»› tạm trước má»—i chu kỳ" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "số mục cần huá»· trong câu nhá»› tạm (mặc định 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <tuỳ chá»n> -- <tuỳ chá»n cải biên>" + +msgid "toggle inclusion of blob objects" +msgstr "bao gồm các đối tượng blob" + +msgid "toggle inclusion of commit objects" +msgstr "bao gồm các đối tượng chuyển giao" + +msgid "toggle inclusion of tag objects" +msgstr "bao gồm các đối tượng thẻ" + +msgid "toggle inclusion of tree objects" +msgstr "bao gồm các đối tượng cây" + +msgid "toggle pruning of uninteresting paths" +msgstr "lược bá» những đưá»ng dẫn Ãt ý nghÄ©a" + +msgid "read a pattern list over stdin" +msgstr "Ä‘á»c các mẫu từ stdin" + #, c-format msgid "commit %s is not marked reachable" msgstr "lần chuyển giao %s chưa được đánh dấu là tiếp cáºn được" @@ -22579,6 +22740,10 @@ msgstr "lá»—i: " msgid "warning: " msgstr "cảnh báo: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() gặp lá»—i '%s' (%d)\n" + msgid "Fetching objects" msgstr "Äang lấy vá» các đối tượng" @@ -23536,3 +23701,21 @@ msgstr "Bá» qua %s vá»›i háºu tố sao lưu '%s'.\n" #, perl-format msgid "Do you really want to send %s? [y|N]: " msgstr "Bạn có thá»±c sá»± muốn gá»i %s? [y|N](có/KHÔNG): " + +#, c-format +#~ msgid "Could not find remote branch %s to clone." +#~ msgstr "Không tìm thấy nhánh máy chá»§ %s để nhân bản (clone)." + +#, c-format +#~ msgid "merging cannot continue; got unclean result of %d" +#~ msgstr "không thể tiếp tục hoà trá»™n; kết quả không hoà n toà n %d" + +#~ msgid "git repack [<options>]" +#~ msgstr "git repack [<các tùy chá»n>]" + +#~ msgid "--onto and --advance are incompatible" +#~ msgstr "--onto và --advance xung khắc" + +#, c-format +#~ msgid "key '%s' of pattern had no '*'" +#~ msgstr "khóa '%s' cá»§a mẫu k có '*'" diff --git a/po/zh_CN.po b/po/zh_CN.po index 12a0fb510b..5cde4011e7 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -93,6 +93,7 @@ # pack index | 包索引 # packfile | 包文件 # parent | 父æäº¤ +# partial clone | 部分克隆 # patch | è¡¥ä¸ # pathspec | è·¯å¾„è§„æ ¼ # pattern | æ¨¡å¼ @@ -154,8 +155,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2025-01-02 20:43+0800\n" -"PO-Revision-Date: 2025-01-05 19:01+0800\n" +"POT-Creation-Date: 2025-03-09 20:34+0800\n" +"PO-Revision-Date: 2025-03-12 14:47+0800\n" "Last-Translator: Teng Long <dyroneteng@gmail.com>\n" "Language-Team: GitHub <https://github.com/dyrone/git/>\n" "Language: zh_CN\n" @@ -2962,6 +2963,22 @@ msgstr "git archive:å议错误" msgid "git archive: expected a flush" msgstr "git archive:应有一个 flush 包" +#: builtin/backfill.c +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +#: builtin/backfill.c +msgid "problem loading sparse-checkout" +msgstr "åŠ è½½ç¨€ç–æ£€å‡ºæ—¶å‡ºçŽ°é—®é¢˜" + +#: builtin/backfill.c +msgid "Minimum number of objects to request at a time" +msgstr "啿¬¡è¯·æ±‚的最少对象数é‡" + +#: builtin/backfill.c +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "将缺少的对象é™åˆ¶åœ¨å½“å‰çš„ç¨€ç–æ£€å‡ºä¸" + #: builtin/bisect.c msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" @@ -3381,7 +3398,7 @@ msgstr "æ˜¾ç¤ºä½œè€…çš„é‚®ç®±è€Œä¸æ˜¯åå—(默认:关é—)" msgid "ignore whitespace differences" msgstr "忽略空白差异" -#: builtin/blame.c builtin/log.c +#: builtin/blame.c builtin/clone.c builtin/log.c msgid "rev" msgstr "版本" @@ -3803,8 +3820,8 @@ msgstr "HEAD 没有ä½äºŽ /refs/heads 之下ï¼" #: builtin/branch.c msgid "" -"branch with --recurse-submodules can only be used if submodule." -"propagateBranches is enabled" +"branch with --recurse-submodules can only be used if " +"submodule.propagateBranches is enabled" msgstr "" "带有 --recurse-submodules 的分支åªèƒ½åœ¨ submodule.propagateBranches å¯ç”¨æ—¶ä½¿ç”¨" @@ -3892,11 +3909,6 @@ msgid "git version:\n" msgstr "git 版本:\n" #: builtin/bugreport.c -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() 失败,错误为 '%s'(%d)\n" - -#: builtin/bugreport.c msgid "compiler info: " msgstr "编译器信æ¯ï¼š" @@ -5134,8 +5146,112 @@ msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "clean.requireForce 设置为 true 且未æä¾› -f é€‰é¡¹ï¼šæ‹’ç»æ‰§è¡Œæ¸…ç†åŠ¨ä½œ" #: builtin/clone.c -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<选项>] [--] <仓库> [<路径>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: ä¸èƒ½ä¸º '%s' æ·»åŠ ä¸€ä¸ªå¤‡ç”¨ï¼š%s\n" + +#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c +#, c-format +msgid "failed to stat '%s'" +msgstr "æ— æ³•å¯¹ '%s' 调用 stat" + +#: builtin/clone.c +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s å˜åœ¨ä¸”䏿˜¯ä¸€ä¸ªç›®å½•" + +#: builtin/clone.c +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' 为符å·é“¾æŽ¥ï¼Œæ‹’ç»ç”¨ --local 克隆" + +#: builtin/clone.c +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "æ— æ³•åœ¨ '%s' 上å¯åЍè¿ä»£å™¨" + +#: builtin/clone.c +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "符å·é“¾æŽ¥ '%s' å˜åœ¨ï¼Œæ‹’ç»ç”¨ --local 克隆" + +#: builtin/clone.c compat/precompose_utf8.c +#, c-format +msgid "failed to unlink '%s'" +msgstr "æ— æ³•åˆ é™¤ '%s'" + +#: builtin/clone.c +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "æ— æ³•æ£€æŸ¥ '%s' 处的硬链接" + +#: builtin/clone.c +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "硬链接与 '%s' å¤„çš„æ¥æºä¸åŒ" + +#: builtin/clone.c +#, c-format +msgid "failed to create link '%s'" +msgstr "æ— æ³•åˆ›å»ºé“¾æŽ¥ '%s'" + +#: builtin/clone.c +#, c-format +msgid "failed to copy file to '%s'" +msgstr "æ— æ³•æ‹·è´æ–‡ä»¶è‡³ '%s'" + +#: builtin/clone.c refs/files-backend.c +#, c-format +msgid "failed to iterate over '%s'" +msgstr "æ— æ³•åœ¨ '%s' 上è¿ä»£" + +#: builtin/clone.c +#, c-format +msgid "done.\n" +msgstr "完æˆã€‚\n" + +#: builtin/clone.c +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"克隆æˆåŠŸï¼Œä½†æ˜¯æ£€å‡ºå¤±è´¥ã€‚\n" +"您å¯ä»¥é€šè¿‡ 'git status' 检查哪些已被检出,然åŽä½¿ç”¨å‘½ä»¤\n" +"'git restore --source=HEAD :/' é‡è¯•\n" + +#: builtin/clone.c fetch-pack.c +msgid "remote did not send all necessary objects" +msgstr "远程没有å‘逿‰€æœ‰å¿…需的对象" + +#: builtin/clone.c +#, c-format +msgid "unable to update %s" +msgstr "ä¸èƒ½æ›´æ–° %s" + +#: builtin/clone.c +msgid "failed to initialize sparse-checkout" +msgstr "æ— æ³•åˆå§‹åŒ–ç¨€ç–æ£€å‡º" + +#: builtin/clone.c +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "远程 HEAD 指å‘一个ä¸å˜åœ¨çš„å¼•ç”¨ï¼Œæ— æ³•æ£€å‡º" + +#: builtin/clone.c +msgid "unable to checkout working tree" +msgstr "ä¸èƒ½æ£€å‡ºå·¥ä½œåŒº" + +#: builtin/clone.c +msgid "unable to write parameters to config file" +msgstr "æ— æ³•å°†å‚æ•°å†™å…¥é…置文件" + +#: builtin/clone.c +msgid "cannot repack to clean up" +msgstr "æ— æ³•æ‰§è¡Œ repack æ¥æ¸…ç†" + +#: builtin/clone.c +msgid "cannot unlink temporary alternates file" +msgstr "æ— æ³•åˆ é™¤ä¸´æ—¶çš„å¤‡ç”¨æ–‡ä»¶" #: builtin/clone.c msgid "don't clone shallow repository" @@ -5208,6 +5324,10 @@ msgid "checkout <branch> instead of the remote's HEAD" msgstr "检出 <分支> è€Œä¸æ˜¯è¿œç¨‹ HEAD" #: builtin/clone.c +msgid "clone single revision <rev> and check out" +msgstr "克隆å•个版本 <版本> 并检出" + +#: builtin/clone.c msgid "path to git-upload-pack on the remote" msgstr "远程 git-upload-pack 路径" @@ -5236,8 +5356,8 @@ msgid "clone only one branch, HEAD or --branch" msgstr "åªå…‹éš†ä¸€ä¸ªåˆ†æ”¯ã€HEAD 或 --branch" #: builtin/clone.c -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "ä¸è¦å…‹éš†ä»»ä½•æ ‡ç¾ï¼Œå¹¶ä¸”åŽç»èŽ·å–æ“作也ä¸ä¸‹è½½å®ƒä»¬" +msgid "clone tags, and make later fetches not to follow them" +msgstr "å…‹éš†æ ‡ç¾ï¼Œå¹¶åœ¨åŽç»èŽ·å–æ—¶ä¸è·Ÿéšå®ƒä»¬" #: builtin/clone.c msgid "any cloned submodules will be shallow" @@ -5294,117 +5414,8 @@ msgid "a URI for downloading bundles before fetching from origin remote" msgstr "用于在从 origin 远程获å–之å‰ä¸‹è½½å½’档包的 URI" #: builtin/clone.c -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: ä¸èƒ½ä¸º '%s' æ·»åŠ ä¸€ä¸ªå¤‡ç”¨ï¼š%s\n" - -#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c -#, c-format -msgid "failed to stat '%s'" -msgstr "æ— æ³•å¯¹ '%s' 调用 stat" - -#: builtin/clone.c -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s å˜åœ¨ä¸”䏿˜¯ä¸€ä¸ªç›®å½•" - -#: builtin/clone.c -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' 为符å·é“¾æŽ¥ï¼Œæ‹’ç»ç”¨ --local 克隆" - -#: builtin/clone.c -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "æ— æ³•åœ¨ '%s' 上å¯åЍè¿ä»£å™¨" - -#: builtin/clone.c -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "符å·é“¾æŽ¥ '%s' å˜åœ¨ï¼Œæ‹’ç»ç”¨ --local 克隆" - -#: builtin/clone.c compat/precompose_utf8.c -#, c-format -msgid "failed to unlink '%s'" -msgstr "æ— æ³•åˆ é™¤ '%s'" - -#: builtin/clone.c -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "æ— æ³•æ£€æŸ¥ '%s' 处的硬链接" - -#: builtin/clone.c -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "硬链接与 '%s' 处的æºä¸åŒ" - -#: builtin/clone.c -#, c-format -msgid "failed to create link '%s'" -msgstr "æ— æ³•åˆ›å»ºé“¾æŽ¥ '%s'" - -#: builtin/clone.c -#, c-format -msgid "failed to copy file to '%s'" -msgstr "æ— æ³•æ‹·è´æ–‡ä»¶è‡³ '%s'" - -#: builtin/clone.c refs/files-backend.c -#, c-format -msgid "failed to iterate over '%s'" -msgstr "æ— æ³•åœ¨ '%s' 上è¿ä»£" - -#: builtin/clone.c -#, c-format -msgid "done.\n" -msgstr "完æˆã€‚\n" - -#: builtin/clone.c -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"克隆æˆåŠŸï¼Œä½†æ˜¯æ£€å‡ºå¤±è´¥ã€‚\n" -"您å¯ä»¥é€šè¿‡ 'git status' 检查哪些已被检出,然åŽä½¿ç”¨å‘½ä»¤\n" -"'git restore --source=HEAD :/' é‡è¯•\n" - -#: builtin/clone.c -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "ä¸èƒ½å‘现è¦å…‹éš†çš„远程分支 %s。" - -#: builtin/clone.c fetch-pack.c -msgid "remote did not send all necessary objects" -msgstr "远程没有å‘逿‰€æœ‰å¿…需的对象" - -#: builtin/clone.c -#, c-format -msgid "unable to update %s" -msgstr "ä¸èƒ½æ›´æ–° %s" - -#: builtin/clone.c -msgid "failed to initialize sparse-checkout" -msgstr "æ— æ³•åˆå§‹åŒ–ç¨€ç–æ£€å‡º" - -#: builtin/clone.c -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "远程 HEAD 指å‘一个ä¸å˜åœ¨çš„å¼•ç”¨ï¼Œæ— æ³•æ£€å‡º" - -#: builtin/clone.c -msgid "unable to checkout working tree" -msgstr "ä¸èƒ½æ£€å‡ºå·¥ä½œåŒº" - -#: builtin/clone.c -msgid "unable to write parameters to config file" -msgstr "æ— æ³•å°†å‚æ•°å†™å…¥é…置文件" - -#: builtin/clone.c -msgid "cannot repack to clean up" -msgstr "æ— æ³•æ‰§è¡Œ repack æ¥æ¸…ç†" - -#: builtin/clone.c -msgid "cannot unlink temporary alternates file" -msgstr "æ— æ³•åˆ é™¤ä¸´æ—¶çš„ alternates 文件" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<选项>] [--] <仓库> [<目录>]" #: builtin/clone.c msgid "Too many arguments." @@ -5531,6 +5542,11 @@ msgid "Remote branch %s not found in upstream %s" msgstr "远程分支 %s 在上游 %s 未å‘现" #: builtin/clone.c +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "在上游 %2$s 未å‘现远程版本 %1$s" + +#: builtin/clone.c msgid "You appear to have cloned an empty repository." msgstr "您似乎克隆了一个空仓库。" @@ -5593,7 +5609,8 @@ msgstr "" "[no-]progress]\n" " <切分选项>" -#: builtin/commit-graph.c builtin/fetch.c builtin/log.c builtin/repack.c +#: builtin/commit-graph.c builtin/fetch.c builtin/gc.c builtin/log.c +#: builtin/repack.c msgid "dir" msgstr "目录" @@ -5751,7 +5768,7 @@ msgstr "git commit-treeï¼šæ— æ³•è¯»å–" #: builtin/commit.c msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -5761,7 +5778,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<模å¼>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<模å¼>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <æäº¤> | --fixup [(amend|" "reword):]<æäº¤>]\n" " [-F <文件> | -m <消æ¯>] [--reset-author] [--allow-empty]\n" @@ -7473,14 +7490,13 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" -"è¿è¡Œ 'git remote set-head %s %s' ä»¥è·Ÿéšæ›´æ”¹ï¼Œæˆ–者\n" -"å¦‚æžœæ‚¨ä¸æƒ³çœ‹åˆ°æ¤æ¶ˆæ¯ï¼Œåˆ™å°†'remote.%s.followRemoteHEAD' é…置选项设置为ä¸åŒçš„" -"值。\n" -"特别地,è¿è¡Œ 'git config set remote.%s.followRemoteHEAD %s' å°†ç¦ç”¨è¦å‘Šï¼Œç›´åˆ°" -"远程将 HEAD 更改为其他内容。\"" +"è¿è¡Œ 'git remote set-head %s %s' åŒæ¥å˜æ›´ï¼Œæˆ–通过é…置选项\n" +"'remote.%s.followRemoteHEAD' 设置为其他值以å±è”½æ¤æç¤ºã€‚具体å¯é€šè¿‡\n" +"è¿è¡Œå‘½ä»¤ 'git config remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"以ç¦ç”¨è¯¥è¦å‘Šï¼Œç›´åˆ°è¿œç¨‹å°† HEAD 更改为其他内容。" #: builtin/fetch.c msgid "multiple branches detected, incompatible with --set-upstream" @@ -7721,8 +7737,8 @@ msgstr "åè®®ä¸æ”¯æŒ --negotiate-only,退出" #: builtin/fetch.c msgid "" -"--filter can only be used with the remote configured in extensions." -"partialclone" +"--filter can only be used with the remote configured in " +"extensions.partialclone" msgstr "åªå¯ä»¥å°† --filter 用于在 extensions.partialclone ä¸é…置的远程仓库" #: builtin/fetch.c @@ -8328,6 +8344,10 @@ msgstr "强制执行 gc å³ä½¿å¦å¤–一个 gc æ£åœ¨æ‰§è¡Œ" msgid "repack all other packs except the largest pack" msgstr "é™¤äº†æœ€å¤§çš„åŒ…ä¹‹å¤–ï¼Œå¯¹æ‰€æœ‰å…¶å®ƒåŒ…æ–‡ä»¶é‡æ–°æ‰“包" +#: builtin/gc.c builtin/repack.c +msgid "pack prefix to store a pack containing pruned objects" +msgstr "用于å˜å‚¨ä¿®å‰ªå¯¹è±¡çš„包å‰ç¼€" + #: builtin/gc.c #, c-format msgid "failed to parse gc.logExpiry value %s" @@ -9327,6 +9347,11 @@ msgstr "æ— æ³•å®Œæˆ pack-objects æ¥é‡æ–°æ‰“包本地链接" msgid "Cannot come back to cwd" msgstr "æ— æ³•è¿”å›žå½“å‰å·¥ä½œç›®å½•" +#: builtin/index-pack.c builtin/unpack-objects.c +#, c-format +msgid "bad --pack_header: %s" +msgstr "错误的 --pack_header:%s" + #: builtin/index-pack.c #, c-format msgid "bad %s" @@ -10432,11 +10457,6 @@ msgstr "未知的ç–略选项:-X%s" msgid "malformed input line: '%s'." msgstr "æ ¼å¼é”™è¯¯çš„输入行:'%s'。" -#: builtin/merge-tree.c -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "åˆå¹¶æ— 法继ç»ï¼›å¾—到ä¸å¹²å‡€çš„结果 %d" - #: builtin/merge.c msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<选项>] [<æäº¤>...]" @@ -11454,6 +11474,15 @@ msgstr "git pack-objects [<选项>] <å‰ç¼€åç§°> [< <引用列表> | < <对象 #: builtin/pack-objects.c #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "æ— æ•ˆçš„ --name-hash-version 选项:%d" + +#: builtin/pack-objects.c +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "当å‰ï¼Œ--write-bitmap-index è¦æ±‚ --name-hash-version=1" + +#: builtin/pack-objects.c +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -11857,7 +11886,11 @@ msgstr "åè®®" #: builtin/pack-objects.c msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" -msgstr "使用æ¤å议排除任何已é…置的 uploadpack.blobpackfileuri" +msgstr "排除掉采用该å议的 uploadpack.blobpackfileuri é…置项" + +#: builtin/pack-objects.c +msgid "use the specified name-hash function to group similar objects" +msgstr "使用指定的å称哈希函数对相似的对象进行分组" #: builtin/pack-objects.c #, c-format @@ -12284,8 +12317,8 @@ msgid "" "upstream, see 'push.autoSetupRemote' in 'git help config'.\n" msgstr "" "\n" -"为了让没有追踪上游的分支自动é…置,å‚è§ 'git help config' ä¸çš„ push." -"autoSetupRemote。\n" +"为了让没有追踪上游的分支自动é…置,å‚è§ 'git help config' ä¸çš„ " +"push.autoSetupRemote。\n" #: builtin/push.c #, c-format @@ -13294,8 +13327,8 @@ msgid "invalid ref format: %s" msgstr "æ— æ•ˆçš„å¼•ç”¨æ ¼å¼ï¼š%s" #: builtin/refs.c -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<æ ¼å¼> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<æ ¼å¼> [--no-reflog] [--dry-run]" #: builtin/refs.c msgid "git refs verify [--strict] [--verbose]" @@ -13310,6 +13343,10 @@ msgid "perform a non-destructive dry-run" msgstr "进行éžç ´å性的试è¿è¡Œï¼ˆdry-run)" #: builtin/refs.c +msgid "drop reflogs entirely during the migration" +msgstr "在è¿ç§»æœŸé—´ä¸¢å¼ƒå¼•用日志" + +#: builtin/refs.c msgid "missing --ref-format=<format>" msgstr "缺少 --ref-format=<æ ¼å¼>" @@ -13881,8 +13918,14 @@ msgid "be verbose; must be placed before a subcommand" msgstr "冗长输出;必须置于å命令之å‰" #: builtin/repack.c -msgid "git repack [<options>]" -msgstr "git repack [<选项>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<包å>]\n" +"[--write-midx] [--name-hash-version=<n>]" #: builtin/repack.c msgid "" @@ -13975,6 +14018,11 @@ msgid "pass --no-reuse-object to git-pack-objects" msgstr "å‘ git-pack-objects ä¼ é€’å‚æ•° --no-reuse-object" #: builtin/repack.c +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "指定è¦ä½¿ç”¨çš„å称哈希算法,以实现按照路径对相似对象分组" + +#: builtin/repack.c msgid "do not run git-update-server-info" msgstr "ä¸è¿è¡Œ git-update-server-info" @@ -14039,10 +14087,6 @@ msgid "write a multi-pack index of the resulting packs" msgstr "写入结果包的多包索引" #: builtin/repack.c -msgid "pack prefix to store a pack containing pruned objects" -msgstr "储å˜è¢«æ¸…除的对象的包的å‰ç¼€" - -#: builtin/repack.c msgid "pack prefix to store a pack containing filtered out objects" msgstr "储å˜è¢«è¿‡æ»¤çš„对象的包的å‰ç¼€" @@ -14315,10 +14359,6 @@ msgid "need some commits to replay" msgstr "需è¦ä¸€äº›æäº¤æ¥é‡æ”¾" #: builtin/replay.c -msgid "--onto and --advance are incompatible" -msgstr "--onto å’Œ --advance ä¸å…¼å®¹" - -#: builtin/replay.c msgid "all positive revisions given must be references" msgstr "æä¾›çš„æ‰€æœ‰æ£å‘版本必须为引用" @@ -17546,6 +17586,10 @@ msgid "Create an archive of files from a named tree" msgstr "åŸºäºŽä¸€ä¸ªæŒ‡å®šçš„æ ‘åˆ›å»ºæ–‡ä»¶å˜æ¡£" #: command-list.h +msgid "Download missing objects in a partial clone" +msgstr "下载部分克隆ä¸ç¼ºå¤±çš„对象" + +#: command-list.h msgid "Use binary search to find the commit that introduced a bug" msgstr "通过二分查找定ä½å¼•å…¥ bug çš„æäº¤" @@ -18927,8 +18971,8 @@ msgid "" "remote URLs cannot be configured in file directly or indirectly included by " "includeIf.hasconfig:remote.*.url" msgstr "" -"远程 URL ä¸èƒ½åœ¨æ–‡ä»¶ä¸é…置,ä¸ç®¡ç›´æŽ¥åœ°è¿˜æ˜¯é€šè¿‡ includeIf.hasconfig:remote.*." -"url 间接地包å«ã€‚" +"远程 URL ä¸èƒ½åœ¨æ–‡ä»¶ä¸é…置,ä¸ç®¡ç›´æŽ¥åœ°è¿˜æ˜¯é€šè¿‡ " +"includeIf.hasconfig:remote.*.url 间接地包å«ã€‚" #: config.c #, c-format @@ -19926,6 +19970,14 @@ msgid "invalid regex given to -I: '%s'" msgstr "选项 -I çš„æ£åˆ™è¡¨è¾¾å¼æ— 效:'%s'" #: diff.c +msgid "-G requires a non-empty argument" +msgstr "-G 需è¦ä¸€ä¸ªéžç©ºå‚æ•°" + +#: diff.c +msgid "-S requires a non-empty argument" +msgstr "-S 需è¦ä¸€ä¸ªéžç©ºå‚æ•°" + +#: diff.c #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "æ— æ³•è§£æž --submodule é€‰é¡¹çš„å‚æ•°ï¼š'%s'" @@ -22430,7 +22482,7 @@ msgstr "æ— æ³•è¯»å–æ›¿ä»£æ–‡ä»¶" #: object-file.c msgid "unable to move new alternates file into place" -msgstr "æ— æ³•å°†æ–°çš„æ›¿ä»£æ–‡ä»¶ç§»åŠ¨åˆ°ä½" +msgstr "æ— æ³•å°†æ–°çš„å¤‡ç”¨æ–‡ä»¶ç§»åŠ¨åˆ°ä½" #: object-file.c #, c-format @@ -22553,6 +22605,11 @@ msgstr "æ— æ³•å†™æ–‡ä»¶ %s" #: object-file.c #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "æ— æ³•å†™å…¥å夿¶ˆå¤±çš„æ–‡ä»¶ %s" + +#: object-file.c +#, c-format msgid "unable to set permission to '%s'" msgstr "æ— æ³•ä¸º '%s' 设置æƒé™" @@ -23233,6 +23290,55 @@ msgstr "未知开关 `%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "å—ç¬¦ä¸²ä¸æœªçŸ¥çš„éž ascii å—符选项:`%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid " <%s>" +msgstr " <%s>" + #: parse-options.c msgid "..." msgstr "..." @@ -23336,6 +23442,25 @@ msgstr "对于 '%2$s' 的错误的布尔环境å–值 '%1$s'" msgid "failed to parse %s" msgstr "æ— æ³•è§£æž %s" +#: path-walk.c +#, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "æ— æ³•éåŽ†æ ‘ %s çš„å节点:未找到" + +#: path-walk.c +#, c-format +msgid "failed to find object %s" +msgstr "æ— æ³•æ‰¾åˆ°å¯¹è±¡ %s" + +#: path-walk.c +#, c-format +msgid "failed to find tag %s" +msgstr "æ— æ³•æ‰¾åˆ°æ ‡ç¾ %s" + +#: path-walk.c +msgid "failed to setup revision walk" +msgstr "æ— æ³•è®¾ç½®ç‰ˆæœ¬é历" + #: path.c #, c-format msgid "Could not make %s writable by group" @@ -23517,6 +23642,26 @@ msgstr "promisor 远程åç§°ä¸èƒ½ä»¥ '/' 开始:%s" msgid "could not fetch %s from promisor remote" msgstr "æ— æ³•ä»Žæ‰¿è¯ºè€…è¿œç¨‹èŽ·å– %s" +#: promisor-remote.c +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "已知远程å称为 '%s',但 url 为 '%s' è€Œä¸æ˜¯ '%s'" + +#: promisor-remote.c +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "é…置项 '%2$s' 为未知的å–值 '%1$s'" + +#: promisor-remote.c +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "远程信æ¯ä¸çš„æœªçŸ¥å…ƒç´ '%s'" + +#: promisor-remote.c +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "未找到已接å—的承诺者远程 '%s'" + #: protocol-caps.c msgid "object-info: expected flush after arguments" msgstr "object-infoï¼šåœ¨å‚æ•°ä¹‹åŽåº”有一个 flush" @@ -24484,6 +24629,16 @@ msgstr "引用å %s 是一个符å·å¼•ç”¨ï¼Œä¸æ”¯æŒå¤åˆ¶" msgid "invalid refspec '%s'" msgstr "æ— æ•ˆçš„å¼•ç”¨è§„æ ¼ï¼š'%s'" +#: refspec.c +#, c-format +msgid "pattern '%s' has no '*'" +msgstr "æ¨¡å¼ '%s' 没有 '*'" + +#: refspec.c +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "æ›¿æ¢ '%s' 没有 '*'" + #: remote-curl.c #, c-format msgid "invalid quoting in push-option value: '%s'" @@ -24637,6 +24792,28 @@ msgstr "remote-curl:未知的æ¥è‡ª git 的命令 '%s'" #: remote.c #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"æ£åœ¨ä»Ž \"%s/%s\" 读å–远程内容,该内容被æååˆ é™¤ã€‚\n" +"\n" +"å¦‚æžœä½ ä»ç„¶åœ¨ä½¿ç”¨ \"remotes/\" 目录,建议è¿ç§»ä¸ºåŸºäºŽé…置远程的方å¼ï¼š\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"å¦‚æžœä½ æ— æ³•è¿ç§»ï¼Œè¯·å‘é€ç”µå邮件至 <git@vger.kernel.org> å‘ŠçŸ¥æˆ‘ä»¬ä½ \n" +"ä»ç„¶éœ€è¦ä½¿ç”¨å®ƒçš„åŽŸå› ã€‚" + +#: remote.c +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "é…置的远程çŸåç§°ä¸èƒ½ä»¥ '/' 开始:%s" @@ -24680,16 +24857,6 @@ msgstr "%s åŒæ—¶è·Ÿè¸ª %s å’Œ %s" #: remote.c #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "模å¼çš„é”® '%s' 没有 '*'" - -#: remote.c -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "模å¼çš„值 '%s' 没有 '*'" - -#: remote.c -#, c-format msgid "src refspec %s does not match any" msgstr "æºå¼•ç”¨è§„æ ¼ %s 没有匹é…" @@ -26956,6 +27123,34 @@ msgstr "åœ¨æ¯æ¬¡è¿ä»£å‰æ¸…é™¤ç¼“å˜æ ‘" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "ç¼“å˜æ ‘䏿— 效化的æ¡ç›®æ•°é‡ï¼ˆé»˜è®¤ 0)" +#: t/helper/test-path-walk.c +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <选项> -- <版本选项>" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of blob objects" +msgstr "åˆ‡æ¢æ˜¯å¦åŒ…嫿•°æ®å¯¹è±¡" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of commit objects" +msgstr "åˆ‡æ¢æ˜¯å¦åŒ…å«æäº¤å¯¹è±¡" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tag objects" +msgstr "åˆ‡æ¢æ˜¯å¦åŒ…嫿 ‡ç¾å¯¹è±¡" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tree objects" +msgstr "åˆ‡æ¢æ˜¯å¦åŒ…嫿 ‘对象" + +#: t/helper/test-path-walk.c +msgid "toggle pruning of uninteresting paths" +msgstr "切æ¢å¯¹æ— 趣路径的修剪" + +#: t/helper/test-path-walk.c +msgid "read a pattern list over stdin" +msgstr "ä»Žæ ‡å‡†è¾“å…¥è¯»å–æ¨¡å¼åˆ—表" + #: t/helper/test-reach.c #, c-format msgid "commit %s is not marked reachable" @@ -27703,6 +27898,11 @@ msgstr "错误:" msgid "warning: " msgstr "è¦å‘Šï¼š" +#: version.c +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() 失败,错误为 '%s'(%d)\n" + #: walker.c msgid "Fetching objects" msgstr "æ£åœ¨èŽ·å–对象" diff --git a/po/zh_TW.po b/po/zh_TW.po index a61f544304..aa74d6537a 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -30,8 +30,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-28 13:16+0800\n" -"PO-Revision-Date: 2024-12-28 13:23+0800\n" +"POT-Creation-Date: 2025-03-09 10:39+0800\n" +"PO-Revision-Date: 2025-03-09 10:52+0800\n" "Last-Translator: Yi-Jyun Pan <pan93412@gmail.com>\n" "Language-Team: Chinese (Traditional) <http://weblate.slat.org/projects/git-" "po/git-cli/zh_Hant/>\n" @@ -2841,6 +2841,22 @@ msgstr "git archive:通訊å”定錯誤" msgid "git archive: expected a flush" msgstr "git archiveï¼šé æœŸæ”¶åˆ° flush å°åŒ…" +#: builtin/backfill.c +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +#: builtin/backfill.c +msgid "problem loading sparse-checkout" +msgstr "載入稀ç–簽出時發生å•題" + +#: builtin/backfill.c +msgid "Minimum number of objects to request at a time" +msgstr "一次請求的最å°ç‰©ä»¶æ•¸é‡" + +#: builtin/backfill.c +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "將缺少的物件é™åˆ¶æ–¼ç›®å‰çš„稀ç–簽出" + #: builtin/bisect.c msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" @@ -2872,22 +2888,22 @@ msgstr "git bisect run <cmd> [<arg>...]" #: builtin/bisect.c #, c-format msgid "cannot open file '%s' in mode '%s'" -msgstr "無法以「%2$sã€æ¨¡å¼é–‹å•Ÿã€Œ%1$sã€æª”案" +msgstr "無法以「%2$sã€æ¨¡å¼é–‹å•Ÿæª”案「%1$sã€" #: builtin/bisect.c #, c-format msgid "could not write to file '%s'" -msgstr "無法寫入「%sã€æª”案" +msgstr "無法寫入檔案「%sã€" #: builtin/bisect.c #, c-format msgid "cannot open file '%s' for reading" -msgstr "無法開啟「%sã€æª”案進行讀å–" +msgstr "無法開啟檔案「%sã€ä¾†è®€å–" #: builtin/bisect.c #, c-format msgid "'%s' is not a valid term" -msgstr "「%sã€ä¸æ˜¯æœ‰æ•ˆè¡“語" +msgstr "「%sã€ä¸æ˜¯æœ‰æ•ˆçš„術語" #: builtin/bisect.c #, c-format @@ -2917,7 +2933,7 @@ msgstr "「%sã€ä¸æ˜¯æœ‰æ•ˆçš„æäº¤" #, c-format msgid "" "could not check out original HEAD '%s'. Try 'git bisect reset <commit>'." -msgstr "無法簽出原始 HEAD「%sã€ã€‚請嘗試「git bisect reset <commit>ã€ã€‚" +msgstr "無法簽出原本的 HEAD「%sã€ã€‚請嘗試「git bisect reset <commit>ã€ã€‚" #: builtin/bisect.c #, c-format @@ -2937,7 +2953,7 @@ msgstr "無法開啟檔案「%sã€" #: builtin/bisect.c #, c-format msgid "Invalid command: you're currently in a %s/%s bisect" -msgstr "å‘½ä»¤ç„¡æ•ˆï¼šæ‚¨ç›®å‰æ£è™•於二分æœå°‹ %s/%s 的狀態" +msgstr "命令無效:您æ£è™•於二分æœå°‹ %s/%s 的狀態" #: builtin/bisect.c #, c-format @@ -3263,7 +3279,7 @@ msgstr "顯示作者信箱而éžå稱(é è¨å€¼ï¼šoff)" msgid "ignore whitespace differences" msgstr "忽略空白差異" -#: builtin/blame.c builtin/log.c +#: builtin/blame.c builtin/clone.c builtin/log.c msgid "rev" msgstr "rev" @@ -3776,11 +3792,6 @@ msgid "git version:\n" msgstr "git 版本:\n" #: builtin/bugreport.c -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() 失敗,錯誤:「%sã€(%d)\n" - -#: builtin/bugreport.c msgid "compiler info: " msgstr "ç·¨è¯å™¨è³‡è¨Šï¼š " @@ -5010,8 +5021,112 @@ msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "clean.requireForce 是 true 且未給定 -f é¸é …:拒絕清ç†" #: builtin/clone.c -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<options>] [--] <repo> [<dir>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: ä¸èƒ½ç‚ºã€Œ%sã€æ–°å¢žä¸€å€‹å‚™ç”¨ï¼š%s\n" + +#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c +#, c-format +msgid "failed to stat '%s'" +msgstr "å°ã€Œ%sã€å‘¼å« stat 失敗" + +#: builtin/clone.c +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s å˜åœ¨ä¸”䏿˜¯ç›®éŒ„" + +#: builtin/clone.c +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "「%sã€æ˜¯ç¬¦è™Ÿé€£çµï¼Œæ•…ä¸èƒ½ä½¿ç”¨ --local 複製" + +#: builtin/clone.c +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "無法在「%sã€ä¸Šå•Ÿå‹•è¿ä»£å™¨" + +#: builtin/clone.c +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "符號連çµã€Œ%sã€å·²å˜åœ¨ï¼Œæ‹’絕使用 --local 複製" + +#: builtin/clone.c compat/precompose_utf8.c +#, c-format +msgid "failed to unlink '%s'" +msgstr "無法刪除「%sã€" + +#: builtin/clone.c +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "ç„¡æ³•æª¢æŸ¥ä½æ–¼ã€Œ%sã€çš„硬連çµ" + +#: builtin/clone.c +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "硬連çµèˆ‡ä½æ–¼ã€Œ%sã€çš„來æºä¸åŒ" + +#: builtin/clone.c +#, c-format +msgid "failed to create link '%s'" +msgstr "建立連çµã€Œ%sã€å¤±æ•—" + +#: builtin/clone.c +#, c-format +msgid "failed to copy file to '%s'" +msgstr "複製檔案至「%sã€å¤±æ•—" + +#: builtin/clone.c refs/files-backend.c +#, c-format +msgid "failed to iterate over '%s'" +msgstr "無法在「%sã€ä¸Šè¿ä»£" + +#: builtin/clone.c +#, c-format +msgid "done.\n" +msgstr "完æˆã€‚\n" + +#: builtin/clone.c +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"複製æˆåŠŸï¼Œä½†æ˜¯ç°½å‡ºå¤±æ•—ã€‚\n" +"您å¯ä»¥é€éŽã€Œgit statusã€æª¢æŸ¥å“ªäº›å·²è¢«ç°½å‡ºï¼Œç„¶å¾Œä½¿ç”¨æŒ‡ä»¤\n" +"「git restore --source=HEAD :/ã€é‡è©¦\n" + +#: builtin/clone.c fetch-pack.c +msgid "remote did not send all necessary objects" +msgstr "é ç«¯æ²’æœ‰å‚³é€æ‰€æœ‰å¿…需的物件" + +#: builtin/clone.c +#, c-format +msgid "unable to update %s" +msgstr "ä¸èƒ½æ›´æ–° %s" + +#: builtin/clone.c +msgid "failed to initialize sparse-checkout" +msgstr "無法åˆå§‹åŒ–稀ç–簽出" + +#: builtin/clone.c +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "é 端 HEAD 指å‘ä¸å˜åœ¨çš„引用,無法簽出" + +#: builtin/clone.c +msgid "unable to checkout working tree" +msgstr "ä¸èƒ½ç°½å‡ºå·¥ä½œå€" + +#: builtin/clone.c +msgid "unable to write parameters to config file" +msgstr "ç„¡æ³•å°‡åƒæ•¸å¯«å…¥çµ„態檔案" + +#: builtin/clone.c +msgid "cannot repack to clean up" +msgstr "無法執行 repack 來清ç†" + +#: builtin/clone.c +msgid "cannot unlink temporary alternates file" +msgstr "ç„¡æ³•åˆªé™¤æš«å˜ alternates 檔案" #: builtin/clone.c msgid "don't clone shallow repository" @@ -5084,6 +5199,10 @@ msgid "checkout <branch> instead of the remote's HEAD" msgstr "簽出 <branch> è€Œä¸æ˜¯é 端 HEAD" #: builtin/clone.c +msgid "clone single revision <rev> and check out" +msgstr "複製單個修訂版 <rev> 並簽出" + +#: builtin/clone.c msgid "path to git-upload-pack on the remote" msgstr "é 端 git-upload-pack 路徑" @@ -5112,8 +5231,8 @@ msgid "clone only one branch, HEAD or --branch" msgstr "åªè¤‡è£½ä¸€å€‹åˆ†æ”¯ã€HEAD 或 --branch" #: builtin/clone.c -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "ä¸è¦è¤‡è£½ä»»ä½•標籤,之後å–得也ä¸è¦è¿½è¹¤é€™äº›æ¨™ç±¤" +msgid "clone tags, and make later fetches not to follow them" +msgstr "複製標籤,並使後續抓å–ä¸è¦è¿½è¹¤é€™äº›æ¨™ç±¤" #: builtin/clone.c msgid "any cloned submodules will be shallow" @@ -5170,117 +5289,8 @@ msgid "a URI for downloading bundles before fetching from origin remote" msgstr "在從 origin é 端抓å–å‰ï¼Œç”¨ä¾†ä¸‹è¼‰å¥—件包的 URI" #: builtin/clone.c -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: ä¸èƒ½ç‚º '%s' 新增一個備用:%s\n" - -#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c -#, c-format -msgid "failed to stat '%s'" -msgstr "å° '%s' å‘¼å« stat 失敗" - -#: builtin/clone.c -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s å˜åœ¨ä¸”䏿˜¯ä¸€å€‹ç›®éŒ„" - -#: builtin/clone.c -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "「%sã€æ˜¯å€‹ç¬¦è™Ÿé€£çµï¼Œæ•…ä¸èƒ½ä½¿ç”¨ --local 複製" - -#: builtin/clone.c -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "無法在 '%s' 上啟動疊代器" - -#: builtin/clone.c -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "「%sã€ç¬¦è™Ÿé€£çµå·²å˜åœ¨ï¼Œæ‹’絕使用 --local 複製" - -#: builtin/clone.c compat/precompose_utf8.c -#, c-format -msgid "failed to unlink '%s'" -msgstr "無法刪除「%sã€" - -#: builtin/clone.c -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "ç„¡æ³•æª¢æŸ¥ä½æ–¼ã€Œ%sã€çš„硬連çµ" - -#: builtin/clone.c -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "硬連çµèˆ‡ä½æ–¼ '%s' 的來æºä¸åŒ" - -#: builtin/clone.c -#, c-format -msgid "failed to create link '%s'" -msgstr "å»ºç«‹é€£çµ '%s' 失敗" - -#: builtin/clone.c -#, c-format -msgid "failed to copy file to '%s'" -msgstr "複製檔案至 '%s' 失敗" - -#: builtin/clone.c refs/files-backend.c -#, c-format -msgid "failed to iterate over '%s'" -msgstr "無法在 '%s' 上疊代" - -#: builtin/clone.c -#, c-format -msgid "done.\n" -msgstr "完æˆã€‚\n" - -#: builtin/clone.c -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"複製æˆåŠŸï¼Œä½†æ˜¯ç°½å‡ºå¤±æ•—ã€‚\n" -"您å¯ä»¥é€éŽ 'git status' 檢查哪些已被簽出,然後使用指令\n" -"'git restore --source=HEAD :/' é‡è©¦\n" - -#: builtin/clone.c -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "找ä¸åˆ°è¦è¤‡è£½çš„é 端分支 %s。" - -#: builtin/clone.c fetch-pack.c -msgid "remote did not send all necessary objects" -msgstr "é ç«¯æ²’æœ‰å‚³é€æ‰€æœ‰å¿…需的物件" - -#: builtin/clone.c -#, c-format -msgid "unable to update %s" -msgstr "ä¸èƒ½æ›´æ–° %s" - -#: builtin/clone.c -msgid "failed to initialize sparse-checkout" -msgstr "無法åˆå§‹åŒ–稀ç–簽出" - -#: builtin/clone.c -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "é 端 HEAD 指å‘一個ä¸å˜åœ¨çš„引用,無法簽出" - -#: builtin/clone.c -msgid "unable to checkout working tree" -msgstr "ä¸èƒ½ç°½å‡ºå·¥ä½œå€" - -#: builtin/clone.c -msgid "unable to write parameters to config file" -msgstr "ç„¡æ³•å°‡åƒæ•¸å¯«å…¥è¨å®šæª”案" - -#: builtin/clone.c -msgid "cannot repack to clean up" -msgstr "無法執行 repack 來清ç†" - -#: builtin/clone.c -msgid "cannot unlink temporary alternates file" -msgstr "ç„¡æ³•åˆªé™¤æš«å˜ alternates 檔案" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<options>] [--] <repo> [<dir>]" #: builtin/clone.c msgid "Too many arguments." @@ -5404,7 +5414,12 @@ msgstr "é ç«¯å‚³è¼¸å›žå ±éŒ¯èª¤" #: builtin/clone.c #, c-format msgid "Remote branch %s not found in upstream %s" -msgstr "é 端分支 %s 在上游 %s 未發ç¾" +msgstr "上游 %2$s 上找ä¸åˆ°é 端分支 %1$s" + +#: builtin/clone.c +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "上游 %2$s 上找ä¸åˆ°é 端修訂版 %1$s" #: builtin/clone.c msgid "You appear to have cloned an empty repository." @@ -5469,7 +5484,8 @@ msgstr "" "[no-]progress]\n" " <split-options>" -#: builtin/commit-graph.c builtin/fetch.c builtin/log.c builtin/repack.c +#: builtin/commit-graph.c builtin/fetch.c builtin/gc.c builtin/log.c +#: builtin/repack.c msgid "dir" msgstr "目錄" @@ -5626,8 +5642,19 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree:讀å–失敗" #: builtin/commit.c -msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +#| msgid "" +#| "git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +#| " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" +#| "reword):]<commit>]\n" +#| " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" +#| " [--allow-empty-message] [--no-verify] [-e] [--" +#| "author=<author>]\n" +#| " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" +#| " [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" +#| " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" +#| " [--] [<pathspec>...]" +msgid "" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -5637,7 +5664,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -7358,14 +7385,14 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" -"執行「git remote set-head %s %sã€ä»¥è¿½è¹¤é€™å€‹è®Šæ›´ï¼Œæˆ–者\n" -"å¦‚æžœæ‚¨ä¸æƒ³çœ‹åˆ°é€™å‰‡è¨Šæ¯ï¼Œè«‹å°‡ã€Œremote.%s.followRemoteHEADã€\n" -"組態é¸é …è¨å®šæˆä¸åŒçš„值。更具體些來說,執行\n" -"「git config set remote.%s.followRemoteHEAD %sã€æœƒåœç”¨é€™å€‹è¦å‘Šï¼Œ\n" -"直到é 端將 HEAD 變更為其他內容。" +"執行「git remote set-head %s %sã€ä¾†è·Ÿé€²æ¤å·®ç•°ï¼Œæˆ–者\n" +"å¦‚æžœæ‚¨ä¸æƒ³çœ‹åˆ°é€™å‰‡è¨Šæ¯ï¼Œè«‹å°‡ã€Œremote.%s.followRemoteHEADã€çµ„æ…‹é¸é …\n" +"è¨å®šæˆåˆ¥çš„值。更具體些來說,執行\n" +"「git config set remote.%s.followRemoteHEAD warn-if-not-branch-%sã€\n" +"會åœç”¨é€™å€‹è¦å‘Šï¼Œç›´åˆ°é 端將 HEAD 改為指å‘å…¶ä»–æ±è¥¿ã€‚" #: builtin/fetch.c msgid "multiple branches detected, incompatible with --set-upstream" @@ -8216,6 +8243,10 @@ msgstr "強制執行 gc å³ä½¿å¦å¤–一個 gc æ£åœ¨åŸ·è¡Œ" msgid "repack all other packs except the largest pack" msgstr "é™¤äº†æœ€å¤§çš„åŒ…ä¹‹å¤–ï¼Œå°æ‰€æœ‰å…¶å®ƒåŒ…釿–°æ‰“包" +#: builtin/gc.c builtin/repack.c +msgid "pack prefix to store a pack containing pruned objects" +msgstr "å°‡å‰ç¶´æ‰“包並儲å˜ç‚ºåŒ…å«å·²å‰ªé™¤ç‰©ä»¶çš„包" + #: builtin/gc.c #, c-format msgid "failed to parse gc.logExpiry value %s" @@ -9209,6 +9240,11 @@ msgstr "ç„¡æ³•çµæŸ pack-objects 來釿–°å°åŒ…" msgid "Cannot come back to cwd" msgstr "無法返回目å‰å·¥ä½œç›®éŒ„" +#: builtin/index-pack.c builtin/unpack-objects.c +#, c-format +msgid "bad --pack_header: %s" +msgstr "無效的 --pack_header:%s" + #: builtin/index-pack.c #, c-format msgid "bad %s" @@ -10311,11 +10347,6 @@ msgstr "未知的ç–ç•¥é¸é …:-X%s" msgid "malformed input line: '%s'." msgstr "æ ¼å¼éŒ¯èª¤çš„輸入行:'%s'。" -#: builtin/merge-tree.c -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "無法繼續åˆä½µï¼šå¾ž %d æ”¶åˆ°çš„çµæžœä¸ä¹¾æ·¨" - #: builtin/merge.c msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<é¸é …>] [<æäº¤>...]" @@ -11334,6 +11365,15 @@ msgstr "git pack-objects [<é¸é …>] <å‰ç¶´å稱> [< <引用列表> | < <物件 #: builtin/pack-objects.c #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "無效的 --name-hash-version é¸é …:%d" + +#: builtin/pack-objects.c +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "ç›®å‰ --write-bitmap-index éœ€è¦æŒ‡å®š --name-hash-version=1" + +#: builtin/pack-objects.c +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -11468,8 +11508,8 @@ msgid "" "value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-" "hash> <uri>' (got '%s')" msgstr "" -"uploadpack.blobpackfileuri çš„å€¼æ ¼å¼å¿…é ˆç‚º '<object-hash> <pack-hash> " -"<uri>' (收到 '%s')" +"uploadpack.blobpackfileuri çš„å€¼æ ¼å¼å¿…é ˆç‚ºã€Œ<object-hash> <pack-hash> <uri>ã€" +"(收到「%sã€ï¼‰" #: builtin/pack-objects.c #, c-format @@ -11740,6 +11780,10 @@ msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "排除任何è¨å®šéŽï¼Œä½¿ç”¨æ¤é€šè¨Šå”定的 uploadpack.blobpackfileuri" #: builtin/pack-objects.c +msgid "use the specified name-hash function to group similar objects" +msgstr "使用指定的å稱雜湊函å¼ä¾†ç‚ºç›¸ä¼¼ç‰©ä»¶åˆ†çµ„" + +#: builtin/pack-objects.c #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "增é‡éˆæ·±åº¦ %d 太深了,強制為 %d" @@ -13178,8 +13222,9 @@ msgid "invalid ref format: %s" msgstr "ç„¡æ•ˆçš„å¼•ç”¨æ ¼å¼ï¼š%s" #: builtin/refs.c -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<æ ¼å¼> [--dry-run]" +#| msgid "git refs migrate --ref-format=<format> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" #: builtin/refs.c msgid "git refs verify [--strict] [--verbose]" @@ -13194,6 +13239,10 @@ msgid "perform a non-destructive dry-run" msgstr "進行éžç ´å£žæ€§çš„試執行" #: builtin/refs.c +msgid "drop reflogs entirely during the migration" +msgstr "在é·ç§»éŽç¨‹ä¸å®Œå…¨æ‹‹æ£„ reflog" + +#: builtin/refs.c msgid "missing --ref-format=<format>" msgstr "缺少 --ref-format=<æ ¼å¼>" @@ -13764,8 +13813,14 @@ msgid "be verbose; must be placed before a subcommand" msgstr "è©³ç´°è¼¸å‡ºï¼›å¿…é ˆç½®æ–¼åæŒ‡ä»¤ä¹‹å‰" #: builtin/repack.c -msgid "git repack [<options>]" -msgstr "git repack [<é¸é …>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" #: builtin/repack.c msgid "" @@ -13858,6 +13913,11 @@ msgid "pass --no-reuse-object to git-pack-objects" msgstr "å‘ git-pack-objects 傳éžåƒæ•¸ --no-reuse-object" #: builtin/repack.c +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "指定è¦ç”¨ä¾†ä»¥è·¯å¾‘為相似物件分組的å稱雜湊版本" + +#: builtin/repack.c msgid "do not run git-update-server-info" msgstr "ä¸åŸ·è¡Œ git-update-server-info" @@ -13922,10 +13982,6 @@ msgid "write a multi-pack index of the resulting packs" msgstr "å¯«å…¥çµæžœåŒ…的多包索引" #: builtin/repack.c -msgid "pack prefix to store a pack containing pruned objects" -msgstr "å°è£å‰ç¶´ï¼Œå„²å˜ç‚ºåŒ…å«éŽæ™‚物件的套件包" - -#: builtin/repack.c msgid "pack prefix to store a pack containing filtered out objects" msgstr "å°‡å‰ç¶´é€²è¡ŒåŒ…è£ï¼Œå„²å˜ç‚ºåŒ…å«å·²éŽæ¿¾ç‰©ä»¶çš„å°è£" @@ -14198,10 +14254,6 @@ msgid "need some commits to replay" msgstr "需è¦ä¸€äº›æäº¤æ‰èƒ½é‡æ”¾" #: builtin/replay.c -msgid "--onto and --advance are incompatible" -msgstr "--onto å’Œ --advance ä¸ç›¸å®¹" - -#: builtin/replay.c msgid "all positive revisions given must be references" msgstr "æä¾›çš„æ‰€æœ‰æ£å‘ä¿®è¨‚é›†å¿…é ˆç‚ºå¼•ç”¨" @@ -17424,6 +17476,10 @@ msgid "Create an archive of files from a named tree" msgstr "基於命åéŽçš„æ¨¹å»ºç«‹æª”案å°å˜" #: command-list.h +msgid "Download missing objects in a partial clone" +msgstr "在部分複製ä¸ä¸‹è¼‰ç¼ºå°‘的物件" + +#: command-list.h msgid "Use binary search to find the commit that introduced a bug" msgstr "é€éŽäºŒåˆ†æœå°‹å®šä½å¼•å…¥ bug çš„æäº¤" @@ -18378,8 +18434,8 @@ msgstr "嘗試寫入æäº¤åœ–,但「core.commitGraphã€å·²åœç”¨" #: commit-graph.c #, c-format msgid "" -"attempting to write a commit-graph, but 'commitGraph." -"changedPathsVersion' (%d) is not supported" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" msgstr "嘗試寫入æäº¤åœ–ï¼Œä½†ä¸æ”¯æ´ã€ŒcommitGraph.changedPathsVersionã€ï¼ˆ%d)" #: commit-graph.c @@ -19791,6 +19847,14 @@ msgid "invalid regex given to -I: '%s'" msgstr "傳入 -I 的常è¦è¡¨ç¤ºå¼ç„¡æ•ˆï¼šã€Œ%sã€" #: diff.c +msgid "-G requires a non-empty argument" +msgstr "-G 需è¦éžç©ºç™½å¼•數" + +#: diff.c +msgid "-S requires a non-empty argument" +msgstr "-S 需è¦éžç©ºç™½å¼•數" + +#: diff.c #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "ç„¡æ³•è§£æž --submodule é¸é …çš„åƒæ•¸ï¼š'%s'" @@ -22419,6 +22483,11 @@ msgstr "無法寫檔案 %s" #: object-file.c #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "無法寫入é‡è¤‡æ¶ˆå¤±çš„æª”案 %s" + +#: object-file.c +#, c-format msgid "unable to set permission to '%s'" msgstr "無法為 '%s' è¨å®šæ¬Šé™" @@ -23100,6 +23169,55 @@ msgstr "未知開關 `%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "å—䏲䏿œªçŸ¥çš„éž ascii å—å…ƒé¸é …:`%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid " <%s>" +msgstr " <%s>" + #: parse-options.c msgid "..." msgstr "..." @@ -23203,6 +23321,25 @@ msgstr "「%2$sã€çš„「%1$sã€å¸ƒæž—環境值無效" msgid "failed to parse %s" msgstr "è§£æž %s 失敗" +#: path-walk.c +#, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "無法走訪樹 %s çš„å代:找ä¸åˆ°" + +#: path-walk.c +#, c-format +msgid "failed to find object %s" +msgstr "找ä¸åˆ°ç‰©ä»¶ %s" + +#: path-walk.c +#, c-format +msgid "failed to find tag %s" +msgstr "找ä¸åˆ°æ¨™ç±¤ %s" + +#: path-walk.c +msgid "failed to setup revision walk" +msgstr "無法è¨ç½®ä¿®è¨‚版走訪" + #: path.c #, c-format msgid "Could not make %s writable by group" @@ -23384,6 +23521,26 @@ msgstr "promisor é 端å稱ä¸èƒ½ä»¥ '/' 開始:%s" msgid "could not fetch %s from promisor remote" msgstr "無法從承諾者é ç«¯æŠ“å– %s" +#: promisor-remote.c +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "已知有é 端å為「%sã€ï¼Œä½†å…¶ URL 為「%sã€è€Œéžã€Œ%sã€" + +#: promisor-remote.c +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "「%2$sã€çµ„æ…‹é¸é …的值「%1$sã€æœªçŸ¥" + +#: promisor-remote.c +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "é ç«¯è³‡è¨Šçš„å…ƒç´ ã€Œ%sã€æœªçŸ¥" + +#: promisor-remote.c +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "找ä¸åˆ°æŽ¥å—的承諾者é 端「%sã€" + #: protocol-caps.c msgid "object-info: expected flush after arguments" msgstr "object-infoï¼šå¼•æ•¸å¾Œé æœŸè¦æœ‰ flush" @@ -24351,6 +24508,16 @@ msgstr "引用å稱 %s æ˜¯ç¬¦è™Ÿå¼•ç”¨ï¼Œä¸æ”¯æ´è¤‡è£½" msgid "invalid refspec '%s'" msgstr "ç„¡æ•ˆçš„å¼•ç”¨è¦æ ¼ï¼šã€Œ%sã€" +#: refspec.c +#, c-format +msgid "pattern '%s' has no '*'" +msgstr "ç¬¦åˆæ¨¡å¼ã€Œ%sã€ä¸æ²’有「*ã€" + +#: refspec.c +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "å–代文å—「%sã€ä¸æ²’有「*ã€" + #: remote-curl.c #, c-format msgid "invalid quoting in push-option value: '%s'" @@ -24504,6 +24671,28 @@ msgstr "remote-curl:未知的來自 git 的指令 '%s'" #: remote.c #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"æ£åœ¨è‡ªã€Œ%s/%sã€è®€å–é 端,該路徑已被標記為å³å°‡ç§»é™¤ã€‚\n" +"\n" +"如果您ä»åœ¨ä½¿ç”¨ã€Œremotes/ã€ç›®éŒ„ï¼Œå»ºè°æ‚¨é·ç§»è‡³åŸºæ–¼çµ„æ…‹çš„é 端:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"如果您無法é·ç§»ï¼Œè«‹å‘Šè¨´æˆ‘們您為何ä»éœ€ä½¿ç”¨æ¤åŠŸèƒ½ï¼Œ\n" +"請寄信至 <git@vger.kernel.org>。" + +#: remote.c +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "è¨å®šçš„é 端çŸå稱ä¸èƒ½ä»¥ '/' 開始:%s" @@ -24547,16 +24736,6 @@ msgstr "%s åŒæ™‚追蹤 %s å’Œ %s" #: remote.c #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "模å¼çš„éµ '%s' 沒有 '*'" - -#: remote.c -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "模å¼çš„值 '%s' 沒有 '*'" - -#: remote.c -#, c-format msgid "src refspec %s does not match any" msgstr "來æºå¼•ç”¨è¦æ ¼ %s 沒有符åˆé …ç›®" @@ -26824,6 +27003,34 @@ msgstr "æ¯æ¬¡è¿ä»£å‰æ¸…é™¤å¿«å–æ¨¹ç‹€ç‰©ä»¶" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "åœ¨å¿«å–æ¨¹ç‹€ç‰©ä»¶ä¸ï¼Œè¦ä½¿å¤±æ•ˆçš„é …ç›®æ•¸é‡ï¼ˆé è¨å€¼ç‚º 0)" +#: t/helper/test-path-walk.c +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <options> -- <revision-options>" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of blob objects" +msgstr "åˆ‡æ›æ˜¯å¦åŒ…å«è³‡æ–™ç‰©ä»¶" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of commit objects" +msgstr "åˆ‡æ›æ˜¯å¦åŒ…å«æäº¤ç‰©ä»¶" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tag objects" +msgstr "åˆ‡æ›æ˜¯å¦åŒ…嫿¨™ç±¤ç‰©ä»¶" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tree objects" +msgstr "åˆ‡æ›æ˜¯å¦åŒ…嫿¨¹ç‹€ç‰©ä»¶" + +#: t/helper/test-path-walk.c +msgid "toggle pruning of uninteresting paths" +msgstr "åˆ‡æ›æ˜¯å¦å‰ªé™¤ä¸é‡è¦è·¯å¾‘" + +#: t/helper/test-path-walk.c +msgid "read a pattern list over stdin" +msgstr "å¾žæ¨™æº–è¼¸å…¥è®€å–æ¨¡å¼æ¸…å–®" + #: t/helper/test-reach.c #, c-format msgid "commit %s is not marked reachable" @@ -27571,6 +27778,11 @@ msgstr "錯誤: " msgid "warning: " msgstr "è¦å‘Š: " +#: version.c +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() 失敗,錯誤:「%sã€(%d)\n" + #: walker.c msgid "Fetching objects" msgstr "æ£åœ¨æŠ“å–物件" @@ -28758,6 +28970,24 @@ msgid "Do you really want to send %s? [y|N]: " msgstr "您真的è¦å‚³é€ %s?[y|N]: " #, c-format +#~ msgid "Could not find remote branch %s to clone." +#~ msgstr "找ä¸åˆ°è¦è¤‡è£½çš„é 端分支 %s。" + +#, c-format +#~ msgid "merging cannot continue; got unclean result of %d" +#~ msgstr "無法繼續åˆä½µï¼šå¾ž %d æ”¶åˆ°çš„çµæžœä¸ä¹¾æ·¨" + +#~ msgid "git repack [<options>]" +#~ msgstr "git repack [<é¸é …>]" + +#~ msgid "--onto and --advance are incompatible" +#~ msgstr "--onto å’Œ --advance ä¸ç›¸å®¹" + +#, c-format +#~ msgid "key '%s' of pattern had no '*'" +#~ msgstr "模å¼çš„éµ '%s' 沒有 '*'" + +#, c-format #~ msgid "preferred pack (%s) is invalid" #~ msgstr "å好的å°åŒ… (%s) 無效" diff --git a/promisor-remote.c b/promisor-remote.c index c714f4f007..6a0a61382f 100644 --- a/promisor-remote.c +++ b/promisor-remote.c @@ -11,6 +11,8 @@ #include "strvec.h" #include "packfile.h" #include "environment.h" +#include "url.h" +#include "version.h" struct promisor_remote_config { struct promisor_remote *promisors; @@ -221,6 +223,18 @@ int repo_has_promisor_remote(struct repository *r) return !!repo_promisor_remote_find(r, NULL); } +int repo_has_accepted_promisor_remote(struct repository *r) +{ + struct promisor_remote *p; + + promisor_remote_init(r); + + for (p = r->promisor_remote_config->promisors; p; p = p->next) + if (p->accepted) + return 1; + return 0; +} + static int remove_fetched_oids(struct repository *repo, struct object_id **oids, int oid_nr, int to_free) @@ -292,3 +306,231 @@ all_fetched: if (to_free) free(remaining_oids); } + +static int allow_unsanitized(char ch) +{ + if (ch == ',' || ch == ';' || ch == '%') + return 0; + return ch > 32 && ch < 127; +} + +static void promisor_info_vecs(struct repository *repo, + struct strvec *names, + struct strvec *urls) +{ + struct promisor_remote *r; + + promisor_remote_init(repo); + + for (r = repo->promisor_remote_config->promisors; r; r = r->next) { + char *url; + char *url_key = xstrfmt("remote.%s.url", r->name); + + strvec_push(names, r->name); + strvec_push(urls, git_config_get_string(url_key, &url) ? NULL : url); + + free(url); + free(url_key); + } +} + +char *promisor_remote_info(struct repository *repo) +{ + struct strbuf sb = STRBUF_INIT; + int advertise_promisors = 0; + struct strvec names = STRVEC_INIT; + struct strvec urls = STRVEC_INIT; + + git_config_get_bool("promisor.advertise", &advertise_promisors); + + if (!advertise_promisors) + return NULL; + + promisor_info_vecs(repo, &names, &urls); + + if (!names.nr) + return NULL; + + for (size_t i = 0; i < names.nr; i++) { + if (i) + strbuf_addch(&sb, ';'); + strbuf_addstr(&sb, "name="); + strbuf_addstr_urlencode(&sb, names.v[i], allow_unsanitized); + if (urls.v[i]) { + strbuf_addstr(&sb, ",url="); + strbuf_addstr_urlencode(&sb, urls.v[i], allow_unsanitized); + } + } + + strvec_clear(&names); + strvec_clear(&urls); + + return strbuf_detach(&sb, NULL); +} + +/* + * Find first index of 'nicks' where there is 'nick'. 'nick' is + * compared case insensitively to the strings in 'nicks'. If not found + * 'nicks->nr' is returned. + */ +static size_t remote_nick_find(struct strvec *nicks, const char *nick) +{ + for (size_t i = 0; i < nicks->nr; i++) + if (!strcasecmp(nicks->v[i], nick)) + return i; + return nicks->nr; +} + +enum accept_promisor { + ACCEPT_NONE = 0, + ACCEPT_KNOWN_URL, + ACCEPT_KNOWN_NAME, + ACCEPT_ALL +}; + +static int should_accept_remote(enum accept_promisor accept, + const char *remote_name, const char *remote_url, + struct strvec *names, struct strvec *urls) +{ + size_t i; + + if (accept == ACCEPT_ALL) + return 1; + + i = remote_nick_find(names, remote_name); + + if (i >= names->nr) + /* We don't know about that remote */ + return 0; + + if (accept == ACCEPT_KNOWN_NAME) + return 1; + + if (accept != ACCEPT_KNOWN_URL) + BUG("Unhandled 'enum accept_promisor' value '%d'", accept); + + if (!strcmp(urls->v[i], remote_url)) + return 1; + + warning(_("known remote named '%s' but with url '%s' instead of '%s'"), + remote_name, urls->v[i], remote_url); + + return 0; +} + +static void filter_promisor_remote(struct repository *repo, + struct strvec *accepted, + const char *info) +{ + struct strbuf **remotes; + const char *accept_str; + enum accept_promisor accept = ACCEPT_NONE; + struct strvec names = STRVEC_INIT; + struct strvec urls = STRVEC_INIT; + + if (!git_config_get_string_tmp("promisor.acceptfromserver", &accept_str)) { + if (!*accept_str || !strcasecmp("None", accept_str)) + accept = ACCEPT_NONE; + else if (!strcasecmp("KnownUrl", accept_str)) + accept = ACCEPT_KNOWN_URL; + else if (!strcasecmp("KnownName", accept_str)) + accept = ACCEPT_KNOWN_NAME; + else if (!strcasecmp("All", accept_str)) + accept = ACCEPT_ALL; + else + warning(_("unknown '%s' value for '%s' config option"), + accept_str, "promisor.acceptfromserver"); + } + + if (accept == ACCEPT_NONE) + return; + + if (accept != ACCEPT_ALL) + promisor_info_vecs(repo, &names, &urls); + + /* Parse remote info received */ + + remotes = strbuf_split_str(info, ';', 0); + + for (size_t i = 0; remotes[i]; i++) { + struct strbuf **elems; + const char *remote_name = NULL; + const char *remote_url = NULL; + char *decoded_name = NULL; + char *decoded_url = NULL; + + strbuf_strip_suffix(remotes[i], ";"); + elems = strbuf_split(remotes[i], ','); + + for (size_t j = 0; elems[j]; j++) { + int res; + strbuf_strip_suffix(elems[j], ","); + res = skip_prefix(elems[j]->buf, "name=", &remote_name) || + skip_prefix(elems[j]->buf, "url=", &remote_url); + if (!res) + warning(_("unknown element '%s' from remote info"), + elems[j]->buf); + } + + if (remote_name) + decoded_name = url_percent_decode(remote_name); + if (remote_url) + decoded_url = url_percent_decode(remote_url); + + if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &names, &urls)) + strvec_push(accepted, decoded_name); + + strbuf_list_free(elems); + free(decoded_name); + free(decoded_url); + } + + strvec_clear(&names); + strvec_clear(&urls); + strbuf_list_free(remotes); +} + +char *promisor_remote_reply(const char *info) +{ + struct strvec accepted = STRVEC_INIT; + struct strbuf reply = STRBUF_INIT; + + filter_promisor_remote(the_repository, &accepted, info); + + if (!accepted.nr) + return NULL; + + for (size_t i = 0; i < accepted.nr; i++) { + if (i) + strbuf_addch(&reply, ';'); + strbuf_addstr_urlencode(&reply, accepted.v[i], allow_unsanitized); + } + + strvec_clear(&accepted); + + return strbuf_detach(&reply, NULL); +} + +void mark_promisor_remotes_as_accepted(struct repository *r, const char *remotes) +{ + struct strbuf **accepted_remotes = strbuf_split_str(remotes, ';', 0); + + for (size_t i = 0; accepted_remotes[i]; i++) { + struct promisor_remote *p; + char *decoded_remote; + + strbuf_strip_suffix(accepted_remotes[i], ";"); + decoded_remote = url_percent_decode(accepted_remotes[i]->buf); + + p = repo_promisor_remote_find(r, decoded_remote); + if (p) + p->accepted = 1; + else + warning(_("accepted promisor remote '%s' not found"), + decoded_remote); + + free(decoded_remote); + } + + strbuf_list_free(accepted_remotes); +} diff --git a/promisor-remote.h b/promisor-remote.h index 88cb599c39..263d331a55 100644 --- a/promisor-remote.h +++ b/promisor-remote.h @@ -9,11 +9,13 @@ struct object_id; * Promisor remote linked list * * Information in its fields come from remote.XXX config entries or - * from extensions.partialclone. + * from extensions.partialclone, except for 'accepted' which comes + * from protocol v2 capabilities exchange. */ struct promisor_remote { struct promisor_remote *next; char *partial_clone_filter; + unsigned int accepted : 1; const char name[FLEX_ARRAY]; }; @@ -32,4 +34,37 @@ void promisor_remote_get_direct(struct repository *repo, const struct object_id *oids, int oid_nr); +/* + * Prepare a "promisor-remote" advertisement by a server. + * Check the value of "promisor.advertise" and maybe the configured + * promisor remotes, if any, to prepare information to send in an + * advertisement. + * Return value is NULL if no promisor remote advertisement should be + * made. Otherwise it contains the names and urls of the advertised + * promisor remotes separated by ';'. See gitprotocol-v2(5). + */ +char *promisor_remote_info(struct repository *repo); + +/* + * Prepare a reply to a "promisor-remote" advertisement from a server. + * Check the value of "promisor.acceptfromserver" and maybe the + * configured promisor remotes, if any, to prepare the reply. + * Return value is NULL if no promisor remote from the server + * is accepted. Otherwise it contains the names of the accepted promisor + * remotes separated by ';'. See gitprotocol-v2(5). + */ +char *promisor_remote_reply(const char *info); + +/* + * Set the 'accepted' flag for some promisor remotes. Useful on the + * server side when some promisor remotes have been accepted by the + * client. + */ +void mark_promisor_remotes_as_accepted(struct repository *repo, const char *remotes); + +/* + * Has any promisor remote been accepted by the client? + */ +int repo_has_accepted_promisor_remote(struct repository *r); + #endif /* PROMISOR_REMOTE_H */ diff --git a/pseudo-merge.h b/pseudo-merge.h index 29df8a32ec..c9fbe9d312 100644 --- a/pseudo-merge.h +++ b/pseudo-merge.h @@ -101,7 +101,7 @@ void select_pseudo_merges(struct bitmap_writer *writer); /* * Represents a serialized view of a file containing pseudo-merge(s) - * (see Documentation/technical/bitmap-format.txt for a specification + * (see Documentation/technical/bitmap-format.adoc for a specification * of the format). */ struct pseudo_merge_map { diff --git a/reachable.c b/reachable.c index ecf7ccf504..9ee04c89ec 100644 --- a/reachable.c +++ b/reachable.c @@ -65,8 +65,10 @@ static void add_rebase_files(struct rev_info *revs) struct worktree **worktrees = get_worktrees(); for (struct worktree **wt = worktrees; *wt; wt++) { + char *wt_gitdir = get_worktree_git_dir(*wt); + strbuf_reset(&buf); - strbuf_addstr(&buf, get_worktree_git_dir(*wt)); + strbuf_addstr(&buf, wt_gitdir); strbuf_complete(&buf, '/'); len = buf.len; for (size_t i = 0; i < ARRAY_SIZE(path); i++) { @@ -74,6 +76,8 @@ static void add_rebase_files(struct rev_info *revs) strbuf_addstr(&buf, path[i]); add_one_file(buf.buf, revs); } + + free(wt_gitdir); } strbuf_release(&buf); free_worktrees(worktrees); diff --git a/read-cache.c b/read-cache.c index 7ef01c3806..e678c13e8f 100644 --- a/read-cache.c +++ b/read-cache.c @@ -3251,15 +3251,18 @@ static int clean_shared_index_files(const char *current_hex) while ((de = readdir(dir)) != NULL) { const char *sha1_hex; - const char *shared_index_path; + char *shared_index_path; if (!skip_prefix(de->d_name, "sharedindex.", &sha1_hex)) continue; if (!strcmp(sha1_hex, current_hex)) continue; - shared_index_path = git_path("%s", de->d_name); + + shared_index_path = repo_git_path(the_repository, "%s", de->d_name); if (should_delete_shared_index(shared_index_path) > 0 && unlink(shared_index_path)) warning_errno(_("unable to unlink: %s"), shared_index_path); + + free(shared_index_path); } closedir(dir); @@ -3271,6 +3274,7 @@ static int write_shared_index(struct index_state *istate, { struct split_index *si = istate->split_index; int ret, was_full = !istate->sparse_index; + char *path; move_cache_to_base_index(istate); convert_to_sparse(istate, 0); @@ -3286,18 +3290,20 @@ static int write_shared_index(struct index_state *istate, if (ret) return ret; - ret = adjust_shared_perm(get_tempfile_path(*temp)); + ret = adjust_shared_perm(the_repository, get_tempfile_path(*temp)); if (ret) { error(_("cannot fix permission bits on '%s'"), get_tempfile_path(*temp)); return ret; } - ret = rename_tempfile(temp, - git_path("sharedindex.%s", oid_to_hex(&si->base->oid))); + + path = repo_git_path(the_repository, "sharedindex.%s", oid_to_hex(&si->base->oid)); + ret = rename_tempfile(temp, path); if (!ret) { oidcpy(&si->base_oid, &si->base->oid); clean_shared_index_files(oid_to_hex(&si->base->oid)); } + free(path); return ret; } @@ -3378,9 +3384,12 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock, if (new_shared_index) { struct tempfile *temp; int saved_errno; + char *path; /* Same initial permissions as the main .git/index file */ - temp = mks_tempfile_sm(git_path("sharedindex_XXXXXX"), 0, 0666); + path = repo_git_path(the_repository, "sharedindex_XXXXXX"); + temp = mks_tempfile_sm(path, 0, 0666); + free(path); if (!temp) { ret = do_write_locked_index(istate, lock, flags, ~WRITE_SPLIT_INDEX_EXTENSION); @@ -3401,9 +3410,10 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock, /* Freshen the shared index only if the split-index was written */ if (!ret && !new_shared_index && !is_null_oid(&si->base_oid)) { - const char *shared_index = git_path("sharedindex.%s", - oid_to_hex(&si->base_oid)); + char *shared_index = repo_git_path(the_repository, "sharedindex.%s", + oid_to_hex(&si->base_oid)); freshen_shared_index(shared_index, 1); + free(shared_index); } out: @@ -1699,6 +1699,24 @@ struct ref_iterator *refs_ref_iterator_begin( enum do_for_each_ref_flags flags) { struct ref_iterator *iter; + struct strvec normalized_exclude_patterns = STRVEC_INIT; + + if (exclude_patterns) { + for (size_t i = 0; exclude_patterns[i]; i++) { + const char *pattern = exclude_patterns[i]; + size_t len = strlen(pattern); + if (!len) + continue; + + if (pattern[len - 1] == '/') + strvec_push(&normalized_exclude_patterns, pattern); + else + strvec_pushf(&normalized_exclude_patterns, "%s/", + pattern); + } + + exclude_patterns = normalized_exclude_patterns.v; + } if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) { static int ref_paranoia = -1; @@ -1719,6 +1737,8 @@ struct ref_iterator *refs_ref_iterator_begin( if (trim) iter = prefix_ref_iterator_begin(iter, "", trim); + strvec_clear(&normalized_exclude_patterns); + return iter; } @@ -2154,7 +2174,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo, if (!is_nonbare_repository_dir(&submodule_sb)) goto done; - if (submodule_to_gitdir(&submodule_sb, submodule)) + if (submodule_to_gitdir(repo, &submodule_sb, submodule)) goto done; subrepo = xmalloc(sizeof(*subrepo)); @@ -2192,8 +2212,8 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt) if (wt->id) { struct strbuf common_path = STRBUF_INIT; - strbuf_git_common_path(&common_path, wt->repo, - "worktrees/%s", wt->id); + repo_common_path_append(wt->repo, &common_path, + "worktrees/%s", wt->id); refs = ref_store_init(wt->repo, wt->repo->ref_storage_format, common_path.buf, REF_STORE_ALL_CAPS); strbuf_release(&common_path); @@ -3043,9 +3063,11 @@ int repo_migrate_ref_storage_format(struct repository *repo, if (ret < 0) goto done; - ret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data); - if (ret < 0) - goto done; + if (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) { + ret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data); + if (ret < 0) + goto done; + } ret = ref_transaction_commit(transaction, errbuf); if (ret < 0) @@ -577,7 +577,7 @@ int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_dat /* * Return 0 iff refname has the correct format for a refname according - * to the rules described in Documentation/git-check-ref-format.txt. + * to the rules described in Documentation/git-check-ref-format.adoc. * If REFNAME_ALLOW_ONELEVEL is set in flags, then accept one-level * reference names. If REFNAME_REFSPEC_PATTERN is set in flags, then * allow a single "*" wildcard character in the refspec. No leading or @@ -1143,8 +1143,11 @@ int is_pseudo_ref(const char *refname); * - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration * without touching the main repository. The result will be written into a * temporary ref storage directory. + * + * - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs. */ -#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0) +#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0) +#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1) /* * Migrate the ref storage format used by the repository to the diff --git a/refs/files-backend.c b/refs/files-backend.c index 29f08dced4..6c6e67dc1c 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1831,7 +1831,7 @@ static int log_ref_setup(struct files_ref_store *refs, } if (*logfd >= 0) - adjust_shared_perm(logfile); + adjust_shared_perm(the_repository, logfile); free(logfile); return 0; @@ -3488,8 +3488,8 @@ static int files_ref_store_create_on_disk(struct ref_store *ref_store, * they do not understand the reference format extension. */ strbuf_addf(&sb, "%s/refs", ref_store->gitdir); - safe_create_dir(sb.buf, 1); - adjust_shared_perm(sb.buf); + safe_create_dir(the_repository, sb.buf, 1); + adjust_shared_perm(the_repository, sb.buf); /* * There is no need to create directories for common refs when creating @@ -3501,11 +3501,11 @@ static int files_ref_store_create_on_disk(struct ref_store *ref_store, */ strbuf_reset(&sb); files_ref_path(refs, &sb, "refs/heads"); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); strbuf_reset(&sb); files_ref_path(refs, &sb, "refs/tags"); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); } strbuf_release(&sb); diff --git a/refs/packed-backend.c b/refs/packed-backend.c index a7b6f74b6e..813e5020e4 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -4,6 +4,7 @@ #include "../git-compat-util.h" #include "../config.h" #include "../dir.h" +#include "../fsck.h" #include "../gettext.h" #include "../hash.h" #include "../hex.h" @@ -299,14 +300,9 @@ struct snapshot_record { size_t len; }; -static int cmp_packed_ref_records(const void *v1, const void *v2, - void *cb_data) -{ - const struct snapshot *snapshot = cb_data; - const struct snapshot_record *e1 = v1, *e2 = v2; - const char *r1 = e1->start + snapshot_hexsz(snapshot) + 1; - const char *r2 = e2->start + snapshot_hexsz(snapshot) + 1; +static int cmp_packed_refname(const char *r1, const char *r2) +{ while (1) { if (*r1 == '\n') return *r2 == '\n' ? 0 : -1; @@ -321,6 +317,17 @@ static int cmp_packed_ref_records(const void *v1, const void *v2, } } +static int cmp_packed_ref_records(const void *v1, const void *v2, + void *cb_data) +{ + const struct snapshot *snapshot = cb_data; + const struct snapshot_record *e1 = v1, *e2 = v2; + const char *r1 = e1->start + snapshot_hexsz(snapshot) + 1; + const char *r2 = e2->start + snapshot_hexsz(snapshot) + 1; + + return cmp_packed_refname(r1, r2); +} + /* * Compare a snapshot record at `rec` to the specified NUL-terminated * refname. @@ -493,6 +500,21 @@ static void verify_buffer_safe(struct snapshot *snapshot) last_line, eof - last_line); } +/* + * When parsing the "packed-refs" file, we will parse it line by line. + * Because we know the start pointer of the refname and the next + * newline pointer, we could calculate the length of the refname by + * subtracting the two pointers. However, there is a corner case where + * the refname contains corrupted embedded NUL characters. And + * `check_refname_format()` will not catch this when the truncated + * refname is still a valid refname. To prevent this, we need to check + * whether the refname contains the NUL characters. + */ +static int refname_contains_nul(struct strbuf *refname) +{ + return !!memchr(refname->buf, '\0', refname->len); +} + #define SMALL_FILE_SIZE (32*1024) /* @@ -693,7 +715,7 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs) tmp = xmemdupz(snapshot->buf, eol - snapshot->buf); - if (!skip_prefix(tmp, "# pack-refs with:", (const char **)&p)) + if (!skip_prefix(tmp, "# pack-refs with: ", (const char **)&p)) die_invalid_line(refs->path, snapshot->buf, snapshot->eof - snapshot->buf); @@ -894,6 +916,9 @@ static int next_record(struct packed_ref_iterator *iter) strbuf_add(&iter->refname_buf, p, eol - p); iter->base.refname = iter->refname_buf.buf; + if (refname_contains_nul(&iter->refname_buf)) + die("packed refname contains embedded NULL: %s", iter->base.refname); + if (check_refname_format(iter->base.refname, REFNAME_ALLOW_ONELEVEL)) { if (!refname_is_safe(iter->base.refname)) die("packed refname is dangerous: %s", @@ -1748,15 +1773,329 @@ static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_s return empty_ref_iterator_begin(); } -static int packed_fsck(struct ref_store *ref_store UNUSED, - struct fsck_options *o UNUSED, +static int packed_fsck_ref_next_line(struct fsck_options *o, + unsigned long line_number, const char *start, + const char *eof, const char **eol) +{ + int ret = 0; + + *eol = memchr(start, '\n', eof - start); + if (!*eol) { + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + ret = fsck_report_ref(o, &report, + FSCK_MSG_PACKED_REF_ENTRY_NOT_TERMINATED, + "'%.*s' is not terminated with a newline", + (int)(eof - start), start); + + /* + * There is no newline but we still want to parse it to the end of + * the buffer. + */ + *eol = eof; + strbuf_release(&packed_entry); + } + + return ret; +} + +static int packed_fsck_ref_header(struct fsck_options *o, + const char *start, const char *eol, + unsigned int *sorted) +{ + struct string_list traits = STRING_LIST_INIT_NODUP; + char *tmp_line; + int ret = 0; + char *p; + + tmp_line = xmemdupz(start, eol - start); + if (!skip_prefix(tmp_line, "# pack-refs with: ", (const char **)&p)) { + struct fsck_ref_report report = { 0 }; + report.path = "packed-refs.header"; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_HEADER, + "'%.*s' does not start with '# pack-refs with: '", + (int)(eol - start), start); + goto cleanup; + } + + string_list_split_in_place(&traits, p, " ", -1); + *sorted = unsorted_string_list_has_string(&traits, "sorted"); + +cleanup: + free(tmp_line); + string_list_clear(&traits, 0); + return ret; +} + +static int packed_fsck_ref_peeled_line(struct fsck_options *o, + struct ref_store *ref_store, + unsigned long line_number, + const char *start, const char *eol) +{ + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + struct object_id peeled; + const char *p; + int ret = 0; + + /* + * Skip the '^' and parse the peeled oid. + */ + start++; + if (parse_oid_hex_algop(start, &peeled, &p, ref_store->repo->hash_algo)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "'%.*s' has invalid peeled oid", + (int)(eol - start), start); + goto cleanup; + } + + if (p != eol) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "has trailing garbage after peeled oid '%.*s'", + (int)(eol - p), p); + goto cleanup; + } + +cleanup: + strbuf_release(&packed_entry); + return ret; +} + +static int packed_fsck_ref_main_line(struct fsck_options *o, + struct ref_store *ref_store, + unsigned long line_number, + struct strbuf *refname, + const char *start, const char *eol) +{ + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + struct object_id oid; + const char *p; + int ret = 0; + + if (parse_oid_hex_algop(start, &oid, &p, ref_store->repo->hash_algo)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "'%.*s' has invalid oid", + (int)(eol - start), start); + goto cleanup; + } + + if (p == eol || !isspace(*p)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "has no space after oid '%s' but with '%.*s'", + oid_to_hex(&oid), (int)(eol - p), p); + goto cleanup; + } + + p++; + strbuf_reset(refname); + strbuf_add(refname, p, eol - p); + if (refname_contains_nul(refname)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "refname '%s' contains NULL binaries", + refname->buf); + } + + if (check_refname_format(refname->buf, 0)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_NAME, + "has bad refname '%s'", refname->buf); + } + +cleanup: + strbuf_release(&packed_entry); + return ret; +} + +static int packed_fsck_ref_sorted(struct fsck_options *o, + struct ref_store *ref_store, + const char *start, const char *eof) +{ + size_t hexsz = ref_store->repo->hash_algo->hexsz; + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + struct strbuf refname1 = STRBUF_INIT; + struct strbuf refname2 = STRBUF_INIT; + unsigned long line_number = 1; + const char *former = NULL; + const char *current; + const char *eol; + int ret = 0; + + if (*start == '#') { + eol = memchr(start, '\n', eof - start); + start = eol + 1; + line_number++; + } + + for (; start < eof; line_number++, start = eol + 1) { + eol = memchr(start, '\n', eof - start); + + if (*start == '^') + continue; + + if (!former) { + former = start + hexsz + 1; + continue; + } + + current = start + hexsz + 1; + if (cmp_packed_refname(former, current) >= 0) { + const char *err_fmt = + "refname '%s' is less than previous refname '%s'"; + + eol = memchr(former, '\n', eof - former); + strbuf_add(&refname1, former, eol - former); + eol = memchr(current, '\n', eof - current); + strbuf_add(&refname2, current, eol - current); + + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + ret = fsck_report_ref(o, &report, + FSCK_MSG_PACKED_REF_UNSORTED, + err_fmt, refname2.buf, refname1.buf); + goto cleanup; + } + former = current; + } + +cleanup: + strbuf_release(&packed_entry); + strbuf_release(&refname1); + strbuf_release(&refname2); + return ret; +} + +static int packed_fsck_ref_content(struct fsck_options *o, + struct ref_store *ref_store, + unsigned int *sorted, + const char *start, const char *eof) +{ + struct strbuf refname = STRBUF_INIT; + unsigned long line_number = 1; + const char *eol; + int ret = 0; + + ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol); + if (*start == '#') { + ret |= packed_fsck_ref_header(o, start, eol, sorted); + + start = eol + 1; + line_number++; + } + + while (start < eof) { + ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol); + ret |= packed_fsck_ref_main_line(o, ref_store, line_number, &refname, start, eol); + start = eol + 1; + line_number++; + if (start < eof && *start == '^') { + ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol); + ret |= packed_fsck_ref_peeled_line(o, ref_store, line_number, + start, eol); + start = eol + 1; + line_number++; + } + } + + strbuf_release(&refname); + return ret; +} + +static int packed_fsck(struct ref_store *ref_store, + struct fsck_options *o, struct worktree *wt) { + struct packed_ref_store *refs = packed_downcast(ref_store, + REF_STORE_READ, "fsck"); + struct strbuf packed_ref_content = STRBUF_INIT; + unsigned int sorted = 0; + struct stat st; + int ret = 0; + int fd = -1; if (!is_main_worktree(wt)) - return 0; + goto cleanup; - return 0; + if (o->verbose) + fprintf_ln(stderr, "Checking packed-refs file %s", refs->path); + + fd = open_nofollow(refs->path, O_RDONLY); + if (fd < 0) { + /* + * If the packed-refs file doesn't exist, there's nothing + * to check. + */ + if (errno == ENOENT) + goto cleanup; + + if (errno == ELOOP) { + struct fsck_ref_report report = { 0 }; + report.path = "packed-refs"; + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_FILETYPE, + "not a regular file but a symlink"); + goto cleanup; + } + + ret = error_errno(_("unable to open '%s'"), refs->path); + goto cleanup; + } else if (fstat(fd, &st) < 0) { + ret = error_errno(_("unable to stat '%s'"), refs->path); + goto cleanup; + } else if (!S_ISREG(st.st_mode)) { + struct fsck_ref_report report = { 0 }; + report.path = "packed-refs"; + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_FILETYPE, + "not a regular file"); + goto cleanup; + } + + if (strbuf_read(&packed_ref_content, fd, 0) < 0) { + ret = error_errno(_("unable to read '%s'"), refs->path); + goto cleanup; + } + + ret = packed_fsck_ref_content(o, ref_store, &sorted, packed_ref_content.buf, + packed_ref_content.buf + packed_ref_content.len); + if (!ret && sorted) + ret = packed_fsck_ref_sorted(o, ref_store, packed_ref_content.buf, + packed_ref_content.buf + packed_ref_content.len); + +cleanup: + if (fd >= 0) + close(fd); + strbuf_release(&packed_ref_content); + return ret; } struct ref_storage_be refs_be_packed = { diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index 7e90e13f74..771f50df38 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -380,7 +380,7 @@ static struct ref_store *reftable_be_init(struct repository *repo, default: BUG("unknown hash algorithm %d", repo->hash_algo->format_id); } - refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask); + refs->write_options.default_permissions = calc_shared_perm(the_repository, 0666 & ~mask); refs->write_options.disable_auto_compact = !git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1); refs->write_options.lock_timeout_ms = 100; @@ -470,21 +470,21 @@ static int reftable_be_create_on_disk(struct ref_store *ref_store, struct strbuf sb = STRBUF_INIT; strbuf_addf(&sb, "%s/reftable", refs->base.gitdir); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); strbuf_reset(&sb); strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir); write_file(sb.buf, "ref: refs/heads/.invalid"); - adjust_shared_perm(sb.buf); + adjust_shared_perm(the_repository, sb.buf); strbuf_reset(&sb); strbuf_addf(&sb, "%s/refs", refs->base.gitdir); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); strbuf_reset(&sb); strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir); write_file(sb.buf, "this repository uses the reftable format"); - adjust_shared_perm(sb.buf); + adjust_shared_perm(the_repository, sb.buf); strbuf_release(&sb); return 0; @@ -269,28 +269,28 @@ void refspec_ref_prefixes(const struct refspec *rs, } } -int match_name_with_pattern(const char *key, const char *name, - const char *value, char **result) +int match_refname_with_pattern(const char *pattern, const char *refname, + const char *replacement, char **result) { - const char *kstar = strchr(key, '*'); + const char *kstar = strchr(pattern, '*'); size_t klen; size_t ksuffixlen; size_t namelen; int ret; if (!kstar) - die(_("key '%s' of pattern had no '*'"), key); - klen = kstar - key; + die(_("pattern '%s' has no '*'"), pattern); + klen = kstar - pattern; ksuffixlen = strlen(kstar + 1); - namelen = strlen(name); - ret = !strncmp(name, key, klen) && namelen >= klen + ksuffixlen && - !memcmp(name + namelen - ksuffixlen, kstar + 1, ksuffixlen); - if (ret && value) { + namelen = strlen(refname); + ret = !strncmp(refname, pattern, klen) && namelen >= klen + ksuffixlen && + !memcmp(refname + namelen - ksuffixlen, kstar + 1, ksuffixlen); + if (ret && replacement) { struct strbuf sb = STRBUF_INIT; - const char *vstar = strchr(value, '*'); + const char *vstar = strchr(replacement, '*'); if (!vstar) - die(_("value '%s' of pattern has no '*'"), value); - strbuf_add(&sb, value, vstar - value); - strbuf_add(&sb, name + klen, namelen - klen - ksuffixlen); + die(_("replacement '%s' has no '*'"), replacement); + strbuf_add(&sb, replacement, vstar - replacement); + strbuf_add(&sb, refname + klen, namelen - klen - ksuffixlen); strbuf_addstr(&sb, vstar + 1); *result = strbuf_detach(&sb, NULL); } @@ -301,7 +301,7 @@ static int refspec_match(const struct refspec_item *refspec, const char *name) { if (refspec->pattern) - return match_name_with_pattern(refspec->src, name, NULL, NULL); + return match_refname_with_pattern(refspec->src, name, NULL, NULL); return !strcmp(refspec->src, name); } @@ -352,7 +352,7 @@ static int refspec_find_negative_match(struct refspec *rs, struct refspec_item * const char *key = refspec->dst ? refspec->dst : refspec->src; const char *value = refspec->src; - if (match_name_with_pattern(key, needle, value, &expn_name)) + if (match_refname_with_pattern(key, needle, value, &expn_name)) string_list_append_nodup(&reversed, expn_name); } else if (refspec->matching) { /* For the special matching refspec, any query should match */ @@ -397,7 +397,7 @@ void refspec_find_all_matches(struct refspec *rs, if (!refspec->dst || refspec->negative) continue; if (refspec->pattern) { - if (match_name_with_pattern(key, needle, value, result)) + if (match_refname_with_pattern(key, needle, value, result)) string_list_append_nodup(results, *result); } else if (!strcmp(needle, key)) { string_list_append(results, value); @@ -426,7 +426,7 @@ int refspec_find_match(struct refspec *rs, struct refspec_item *query) if (!refspec->dst || refspec->negative) continue; if (refspec->pattern) { - if (match_name_with_pattern(key, needle, value, result)) { + if (match_refname_with_pattern(key, needle, value, result)) { query->force = refspec->force; return 0; } @@ -75,11 +75,12 @@ void refspec_ref_prefixes(const struct refspec *rs, int refname_matches_negative_refspec_item(const char *refname, struct refspec *rs); /* - * Checks whether a name matches a pattern and optionally generates a result. - * Returns 1 if the name matches the pattern, 0 otherwise. + * Checks if a refname matches a globbing refspec pattern. + * If replacement is provided, computes the corresponding mapped refname. + * Returns 1 if refname matches pattern, 0 otherwise. */ -int match_name_with_pattern(const char *key, const char *name, - const char *value, char **result); +int match_refname_with_pattern(const char *pattern, const char *refname, + const char *replacement, char **result); /* * Queries a refspec for a match and updates the query item. diff --git a/reftable/reader.c b/reftable/reader.c index 3f2e4b2800..24bae50ac2 100644 --- a/reftable/reader.c +++ b/reftable/reader.c @@ -666,6 +666,8 @@ done: reftable_block_done(&footer); reftable_block_done(&header); if (err) { + if (r) + reftable_free(r->name); reftable_free(r); block_source_close(source); } @@ -321,10 +321,11 @@ static void read_remotes_file(struct remote_state *remote_state, struct remote *remote) { struct strbuf buf = STRBUF_INIT; - FILE *f = fopen_or_warn(git_path("remotes/%s", remote->name), "r"); + FILE *f = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "remotes/%s", remote->name), "r"); if (!f) - return; + goto out; warn_about_deprecated_remote_type("remotes", remote); @@ -343,8 +344,10 @@ static void read_remotes_file(struct remote_state *remote_state, else if (skip_prefix(buf.buf, "Pull:", &v)) refspec_append(&remote->fetch, skip_spaces(v)); } - strbuf_release(&buf); fclose(f); + +out: + strbuf_release(&buf); } static void read_branches_file(struct remote_state *remote_state, @@ -352,20 +355,19 @@ static void read_branches_file(struct remote_state *remote_state, { char *frag, *to_free = NULL; struct strbuf buf = STRBUF_INIT; - FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r"); + FILE *f = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "branches/%s", remote->name), "r"); if (!f) - return; + goto out; warn_about_deprecated_remote_type("branches", remote); strbuf_getline_lf(&buf, f); fclose(f); strbuf_trim(&buf); - if (!buf.len) { - strbuf_release(&buf); - return; - } + if (!buf.len) + goto out; remote->configured_in_repo = 1; remote->origin = REMOTE_BRANCHES; @@ -393,6 +395,7 @@ static void read_branches_file(struct remote_state *remote_state, refspec_appendf(&remote->push, "HEAD:refs/heads/%s", frag); remote->fetch_tags = 1; /* always auto-follow */ +out: strbuf_release(&buf); free(to_free); } @@ -1322,9 +1325,9 @@ static char *get_ref_match(const struct refspec *rs, const struct ref *ref, const char *dst_side = item->dst ? item->dst : item->src; int match; if (direction == FROM_SRC) - match = match_name_with_pattern(item->src, ref->name, dst_side, &name); + match = match_refname_with_pattern(item->src, ref->name, dst_side, &name); else - match = match_name_with_pattern(dst_side, ref->name, item->src, &name); + match = match_refname_with_pattern(dst_side, ref->name, item->src, &name); if (match) { matching_refs = i; break; @@ -1942,7 +1945,7 @@ static struct ref *get_expanded_map(const struct ref *remote_refs, if (strchr(ref->name, '^')) continue; /* a dereference item */ - if (match_name_with_pattern(refspec->src, ref->name, + if (match_refname_with_pattern(refspec->src, ref->name, refspec->dst, &expn_name) && !ignore_symref_update(expn_name, &scratch)) { struct ref *cpy = copy_ref(ref); diff --git a/repo-settings.c b/repo-settings.c index 9d16d5399e..67e9cfd2e6 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -4,6 +4,7 @@ #include "repository.h" #include "midx.h" #include "pack-objects.h" +#include "setup.h" static void repo_cfg_bool(struct repository *r, const char *key, int *dest, int def) @@ -21,7 +22,6 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest, void prepare_repo_settings(struct repository *r) { - const struct repo_settings defaults = REPO_SETTINGS_INIT; int experimental; int value; const char *strval; @@ -35,7 +35,7 @@ void prepare_repo_settings(struct repository *r) if (r->settings.initialized) return; - memcpy(&r->settings, &defaults, sizeof(defaults)); + repo_settings_clear(r); r->settings.initialized++; /* Booleans config or default, cascades to other settings */ @@ -143,6 +143,14 @@ void prepare_repo_settings(struct repository *r) r->settings.packed_git_limit = ulongval; } +void repo_settings_clear(struct repository *r) +{ + struct repo_settings empty = REPO_SETTINGS_INIT; + FREE_AND_NULL(r->settings.fsmonitor); + FREE_AND_NULL(r->settings.hooks_path); + r->settings = empty; +} + enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo) { const char *value; @@ -167,3 +175,35 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo) &repo->settings.warn_ambiguous_refs, 1); return repo->settings.warn_ambiguous_refs; } + +const char *repo_settings_get_hooks_path(struct repository *repo) +{ + if (!repo->settings.hooks_path) + repo_config_get_pathname(repo, "core.hookspath", &repo->settings.hooks_path); + return repo->settings.hooks_path; +} + +int repo_settings_get_shared_repository(struct repository *repo) +{ + if (!repo->settings.shared_repository_initialized) { + const char *var = "core.sharedrepository"; + const char *value; + if (!repo_config_get_value(repo, var, &value)) + repo->settings.shared_repository = git_config_perm(var, value); + else + repo->settings.shared_repository = PERM_UMASK; + repo->settings.shared_repository_initialized = 1; + } + return repo->settings.shared_repository; +} + +void repo_settings_set_shared_repository(struct repository *repo, int value) +{ + repo->settings.shared_repository = value; + repo->settings.shared_repository_initialized = 1; +} + +void repo_settings_reset_shared_repository(struct repository *repo) +{ + repo->settings.shared_repository_initialized = 0; +} diff --git a/repo-settings.h b/repo-settings.h index 93ea0c3274..ddc11967e0 100644 --- a/repo-settings.h +++ b/repo-settings.h @@ -37,6 +37,9 @@ struct repo_settings { int pack_use_bitmap_boundary_traversal; int pack_use_multi_pack_reuse; + int shared_repository; + int shared_repository_initialized; + /* * Does this repository have core.useReplaceRefs=true (on by * default)? This provides a repository-scoped version of this @@ -61,8 +64,11 @@ struct repo_settings { size_t delta_base_cache_limit; size_t packed_git_window_size; size_t packed_git_limit; + + char *hooks_path; }; #define REPO_SETTINGS_INIT { \ + .shared_repository = -1, \ .index_version = -1, \ .core_untracked_cache = UNTRACKED_CACHE_KEEP, \ .fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \ @@ -73,10 +79,18 @@ struct repo_settings { } void prepare_repo_settings(struct repository *r); +void repo_settings_clear(struct repository *r); /* Read the value for "core.logAllRefUpdates". */ enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo); /* Read the value for "core.warnAmbiguousRefs". */ int repo_settings_get_warn_ambiguous_refs(struct repository *repo); +/* Read the value for "core.hooksPath". */ +const char *repo_settings_get_hooks_path(struct repository *repo); + +/* Read, set or reset the value for "core.sharedRepository". */ +int repo_settings_get_shared_repository(struct repository *repo); +void repo_settings_set_shared_repository(struct repository *repo, int value); +void repo_settings_reset_shared_repository(struct repository *repo); #endif /* REPO_SETTINGS_H */ diff --git a/repository.c b/repository.c index 1a6a62bbd0..6cbaf2e3da 100644 --- a/repository.c +++ b/repository.c @@ -312,8 +312,8 @@ int repo_submodule_init(struct repository *subrepo, struct strbuf worktree = STRBUF_INIT; int ret = 0; - strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", path); - strbuf_repo_worktree_path(&worktree, superproject, "%s", path); + repo_worktree_path_append(superproject, &gitdir, "%s/.git", path); + repo_worktree_path_append(superproject, &worktree, "%s", path); if (repo_init(subrepo, gitdir.buf, worktree.buf)) { /* @@ -380,7 +380,7 @@ void repo_clear(struct repository *repo) parsed_object_pool_clear(repo->parsed_objects); FREE_AND_NULL(repo->parsed_objects); - FREE_AND_NULL(repo->settings.fsmonitor); + repo_settings_clear(repo); if (repo->config) { git_configset_clear(repo->config); @@ -91,16 +91,18 @@ static void assign_variant(struct rerere_id *id) id->variant = variant; } -const char *rerere_path(const struct rerere_id *id, const char *file) +const char *rerere_path(struct strbuf *buf, const struct rerere_id *id, const char *file) { if (!file) - return git_path("rr-cache/%s", rerere_id_hex(id)); + return repo_git_path_replace(the_repository, buf, "rr-cache/%s", + rerere_id_hex(id)); if (id->variant <= 0) - return git_path("rr-cache/%s/%s", rerere_id_hex(id), file); + return repo_git_path_replace(the_repository, buf, "rr-cache/%s/%s", + rerere_id_hex(id), file); - return git_path("rr-cache/%s/%s.%d", - rerere_id_hex(id), file, id->variant); + return repo_git_path_replace(the_repository, buf, "rr-cache/%s/%s.%d", + rerere_id_hex(id), file, id->variant); } static int is_rr_file(const char *name, const char *filename, int *variant) @@ -125,8 +127,12 @@ static int is_rr_file(const char *name, const char *filename, int *variant) static void scan_rerere_dir(struct rerere_dir *rr_dir) { struct dirent *de; - DIR *dir = opendir(git_path("rr-cache/%s", rr_dir->name)); + char *path; + DIR *dir; + path = repo_git_path(the_repository, "rr-cache/%s", rr_dir->name); + dir = opendir(path); + free(path); if (!dir) return; while ((de = readdir(dir)) != NULL) { @@ -624,9 +630,10 @@ static int try_merge(struct index_state *istate, { enum ll_merge_result ret; mmfile_t base = {NULL, 0}, other = {NULL, 0}; + struct strbuf buf = STRBUF_INIT; - if (read_mmfile(&base, rerere_path(id, "preimage")) || - read_mmfile(&other, rerere_path(id, "postimage"))) { + if (read_mmfile(&base, rerere_path(&buf, id, "preimage")) || + read_mmfile(&other, rerere_path(&buf, id, "postimage"))) { ret = LL_MERGE_CONFLICT; } else { /* @@ -637,6 +644,7 @@ static int try_merge(struct index_state *istate, istate, NULL); } + strbuf_release(&buf); free(base.ptr); free(other.ptr); @@ -657,6 +665,7 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c { FILE *f; int ret; + struct strbuf buf = STRBUF_INIT; mmfile_t cur = {NULL, 0}; mmbuffer_t result = {NULL, 0}; @@ -664,8 +673,8 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c * Normalize the conflicts in path and write it out to * "thisimage" temporary file. */ - if ((handle_file(istate, path, NULL, rerere_path(id, "thisimage")) < 0) || - read_mmfile(&cur, rerere_path(id, "thisimage"))) { + if ((handle_file(istate, path, NULL, rerere_path(&buf, id, "thisimage")) < 0) || + read_mmfile(&cur, rerere_path(&buf, id, "thisimage"))) { ret = 1; goto out; } @@ -678,9 +687,9 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c * A successful replay of recorded resolution. * Mark that "postimage" was used to help gc. */ - if (utime(rerere_path(id, "postimage"), NULL) < 0) + if (utime(rerere_path(&buf, id, "postimage"), NULL) < 0) warning_errno(_("failed utime() on '%s'"), - rerere_path(id, "postimage")); + rerere_path(&buf, id, "postimage")); /* Update "path" with the resolution */ f = fopen(path, "w"); @@ -694,6 +703,7 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c out: free(cur.ptr); free(result.ptr); + strbuf_release(&buf); return ret; } @@ -720,9 +730,11 @@ static void update_paths(struct repository *r, struct string_list *update) static void remove_variant(struct rerere_id *id) { - unlink_or_warn(rerere_path(id, "postimage")); - unlink_or_warn(rerere_path(id, "preimage")); + struct strbuf buf = STRBUF_INIT; + unlink_or_warn(rerere_path(&buf, id, "postimage")); + unlink_or_warn(rerere_path(&buf, id, "preimage")); id->collection->status[id->variant] = 0; + strbuf_release(&buf); } /* @@ -739,6 +751,7 @@ static void do_rerere_one_path(struct index_state *istate, const char *path = rr_item->string; struct rerere_id *id = rr_item->util; struct rerere_dir *rr_dir = id->collection; + struct strbuf buf = STRBUF_INIT; int variant; variant = id->variant; @@ -746,12 +759,12 @@ static void do_rerere_one_path(struct index_state *istate, /* Has the user resolved it already? */ if (variant >= 0) { if (!handle_file(istate, path, NULL, NULL)) { - copy_file(rerere_path(id, "postimage"), path, 0666); + copy_file(rerere_path(&buf, id, "postimage"), path, 0666); id->collection->status[variant] |= RR_HAS_POSTIMAGE; fprintf_ln(stderr, _("Recorded resolution for '%s'."), path); free_rerere_id(rr_item); rr_item->util = NULL; - return; + goto out; } /* * There may be other variants that can cleanly @@ -787,22 +800,25 @@ static void do_rerere_one_path(struct index_state *istate, path); free_rerere_id(rr_item); rr_item->util = NULL; - return; + goto out; } /* None of the existing one applies; we need a new variant */ assign_variant(id); variant = id->variant; - handle_file(istate, path, NULL, rerere_path(id, "preimage")); + handle_file(istate, path, NULL, rerere_path(&buf, id, "preimage")); if (id->collection->status[variant] & RR_HAS_POSTIMAGE) { - const char *path = rerere_path(id, "postimage"); + const char *path = rerere_path(&buf, id, "postimage"); if (unlink(path)) die_errno(_("cannot unlink stray '%s'"), path); id->collection->status[variant] &= ~RR_HAS_POSTIMAGE; } id->collection->status[variant] |= RR_HAS_PREIMAGE; fprintf_ln(stderr, _("Recorded preimage for '%s'"), path); + +out: + strbuf_release(&buf); } static int do_plain_rerere(struct repository *r, @@ -810,6 +826,7 @@ static int do_plain_rerere(struct repository *r, { struct string_list conflict = STRING_LIST_INIT_DUP; struct string_list update = STRING_LIST_INIT_DUP; + struct strbuf buf = STRBUF_INIT; int i; find_conflict(r, &conflict); @@ -843,7 +860,7 @@ static int do_plain_rerere(struct repository *r, string_list_insert(rr, path)->util = id; /* Ensure that the directory exists. */ - mkdir_in_gitdir(rerere_path(id, NULL)); + mkdir_in_gitdir(rerere_path(&buf, id, NULL)); } for (i = 0; i < rr->nr; i++) @@ -854,6 +871,7 @@ static int do_plain_rerere(struct repository *r, string_list_clear(&conflict, 0); string_list_clear(&update, 0); + strbuf_release(&buf); return write_rr(rr, fd); } @@ -1033,6 +1051,7 @@ static int rerere_forget_one_path(struct index_state *istate, struct rerere_id *id; unsigned char hash[GIT_MAX_RAWSZ]; int ret; + struct strbuf buf = STRBUF_INIT; struct string_list_item *item; /* @@ -1056,8 +1075,8 @@ static int rerere_forget_one_path(struct index_state *istate, if (!has_rerere_resolution(id)) continue; - handle_cache(istate, path, hash, rerere_path(id, "thisimage")); - if (read_mmfile(&cur, rerere_path(id, "thisimage"))) { + handle_cache(istate, path, hash, rerere_path(&buf, id, "thisimage")); + if (read_mmfile(&cur, rerere_path(&buf, id, "thisimage"))) { free(cur.ptr); error(_("failed to update conflicted state in '%s'"), path); goto fail_exit; @@ -1074,7 +1093,7 @@ static int rerere_forget_one_path(struct index_state *istate, goto fail_exit; } - filename = rerere_path(id, "postimage"); + filename = rerere_path(&buf, id, "postimage"); if (unlink(filename)) { if (errno == ENOENT) error(_("no remembered resolution for '%s'"), path); @@ -1088,7 +1107,7 @@ static int rerere_forget_one_path(struct index_state *istate, * conflict in the working tree, run us again to record * the postimage. */ - handle_cache(istate, path, hash, rerere_path(id, "preimage")); + handle_cache(istate, path, hash, rerere_path(&buf, id, "preimage")); fprintf_ln(stderr, _("Updated preimage for '%s'"), path); /* @@ -1099,9 +1118,11 @@ static int rerere_forget_one_path(struct index_state *istate, free_rerere_id(item); item->util = id; fprintf(stderr, _("Forgot resolution for '%s'\n"), path); + strbuf_release(&buf); return 0; fail_exit: + strbuf_release(&buf); free(id); return -1; } @@ -1147,16 +1168,26 @@ int rerere_forget(struct repository *r, struct pathspec *pathspec) static timestamp_t rerere_created_at(struct rerere_id *id) { + struct strbuf buf = STRBUF_INIT; struct stat st; + timestamp_t ret; + + ret = stat(rerere_path(&buf, id, "preimage"), &st) ? (time_t) 0 : st.st_mtime; - return stat(rerere_path(id, "preimage"), &st) ? (time_t) 0 : st.st_mtime; + strbuf_release(&buf); + return ret; } static timestamp_t rerere_last_used_at(struct rerere_id *id) { + struct strbuf buf = STRBUF_INIT; struct stat st; + timestamp_t ret; + + ret = stat(rerere_path(&buf, id, "postimage"), &st) ? (time_t) 0 : st.st_mtime; - return stat(rerere_path(id, "postimage"), &st) ? (time_t) 0 : st.st_mtime; + strbuf_release(&buf); + return ret; } /* @@ -1164,9 +1195,11 @@ static timestamp_t rerere_last_used_at(struct rerere_id *id) */ static void unlink_rr_item(struct rerere_id *id) { - unlink_or_warn(rerere_path(id, "thisimage")); + struct strbuf buf = STRBUF_INIT; + unlink_or_warn(rerere_path(&buf, id, "thisimage")); remove_variant(id); id->collection->status[id->variant] = 0; + strbuf_release(&buf); } static void prune_one(struct rerere_id *id, @@ -1205,6 +1238,7 @@ void rerere_gc(struct repository *r, struct string_list *rr) timestamp_t now = time(NULL); timestamp_t cutoff_noresolve = now - 15 * 86400; timestamp_t cutoff_resolve = now - 60 * 86400; + struct strbuf buf = STRBUF_INIT; if (setup_rerere(r, rr, 0) < 0) return; @@ -1214,7 +1248,7 @@ void rerere_gc(struct repository *r, struct string_list *rr) repo_config_get_expiry_in_days(the_repository, "gc.rerereunresolved", &cutoff_noresolve, now); git_config(git_default_config, NULL); - dir = opendir(git_path("rr-cache")); + dir = opendir(repo_git_path_replace(the_repository, &buf, "rr-cache")); if (!dir) die_errno(_("unable to open rr-cache directory")); /* Collect stale conflict IDs ... */ @@ -1243,9 +1277,12 @@ void rerere_gc(struct repository *r, struct string_list *rr) /* ... and then remove the empty directories */ for (i = 0; i < to_remove.nr; i++) - rmdir(git_path("rr-cache/%s", to_remove.items[i].string)); + rmdir(repo_git_path_replace(the_repository, &buf, + "rr-cache/%s", to_remove.items[i].string)); + string_list_clear(&to_remove, 0); rollback_lock_file(&write_lock); + strbuf_release(&buf); } /* @@ -1264,10 +1301,14 @@ void rerere_clear(struct repository *r, struct string_list *merge_rr) for (i = 0; i < merge_rr->nr; i++) { struct rerere_id *id = merge_rr->items[i].util; + struct strbuf buf = STRBUF_INIT; + if (!has_rerere_resolution(id)) { unlink_rr_item(id); - rmdir(rerere_path(id, NULL)); + rmdir(rerere_path(&buf, id, NULL)); } + + strbuf_release(&buf); } unlink_or_warn(git_path_merge_rr(r)); rollback_lock_file(&write_lock); @@ -32,7 +32,8 @@ int repo_rerere(struct repository *, int); * path to that filesystem entity. With "file" specified with NULL, * return the path to the directory that houses these files. */ -const char *rerere_path(const struct rerere_id *, const char *file); +const char *rerere_path(struct strbuf *buf, const struct rerere_id *, + const char *file); int rerere_forget(struct repository *, struct pathspec *); int rerere_remaining(struct repository *, struct string_list *); void rerere_clear(struct repository *, struct string_list *); diff --git a/revision.c b/revision.c index 474fa1e767..c4390f0938 100644 --- a/revision.c +++ b/revision.c @@ -1874,15 +1874,20 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags) for (p = worktrees; *p; p++) { struct worktree *wt = *p; struct index_state istate = INDEX_STATE_INIT(revs->repo); + char *wt_gitdir; if (wt->is_current) continue; /* current index already taken care of */ + wt_gitdir = get_worktree_git_dir(wt); + if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"), - get_worktree_git_dir(wt)) > 0) + wt_gitdir) > 0) do_add_index_objects_to_pending(revs, &istate, flags); + discard_index(&istate); + free(wt_gitdir); } free_worktrees(worktrees); } diff --git a/sequencer.c b/sequencer.c index 407ee4e90f..ad0ab75c8d 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2510,9 +2510,15 @@ static int do_pick_commit(struct repository *r, *check_todo = !!(flags & EDIT_MSG); if (!res && reword) { fast_forward_edit: - res = run_git_commit(NULL, opts, EDIT_MSG | - VERIFY_MSG | AMEND_MSG | - (flags & ALLOW_EMPTY)); + /* + * To reword we amend the commit we just + * picked or fast-forwarded. As the commit has + * already been picked we want to use the same + * set of commit flags regardless of how we + * got here. + */ + flags = EDIT_MSG | VERIFY_MSG | AMEND_MSG | ALLOW_EMPTY; + res = run_git_commit(NULL, opts, flags); *check_todo = 1; } } @@ -10,6 +10,7 @@ #include "upload-pack.h" #include "bundle-uri.h" #include "trace2.h" +#include "promisor-remote.h" static int advertise_sid = -1; static int advertise_object_info = -1; @@ -29,6 +30,26 @@ static int agent_advertise(struct repository *r UNUSED, return 1; } +static int promisor_remote_advertise(struct repository *r, + struct strbuf *value) +{ + if (value) { + char *info = promisor_remote_info(r); + if (!info) + return 0; + strbuf_addstr(value, info); + free(info); + } + return 1; +} + +static void promisor_remote_receive(struct repository *r, + const char *remotes) +{ + mark_promisor_remotes_as_accepted(r, remotes); +} + + static int object_format_advertise(struct repository *r, struct strbuf *value) { @@ -155,6 +176,11 @@ static struct protocol_capability capabilities[] = { .advertise = bundle_uri_advertise, .command = bundle_uri_command, }, + { + .name = "promisor-remote", + .advertise = promisor_remote_advertise, + .receive = promisor_remote_receive, + }, }; void protocol_v2_advertise_capabilities(struct repository *r) diff --git a/server-info.c b/server-info.c index 31c3fdc118..1ca0e00d51 100644 --- a/server-info.c +++ b/server-info.c @@ -125,7 +125,7 @@ static int update_info_file(struct repository *r, char *path, uic.cur_fp = NULL; if (uic_is_stale(&uic)) { - if (adjust_shared_perm(get_tempfile_path(f)) < 0) + if (adjust_shared_perm(r, get_tempfile_path(f)) < 0) goto out; if (rename_tempfile(&f, path) < 0) goto out; @@ -792,7 +792,7 @@ int upgrade_repository_format(int target_version) struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT; int ret; - strbuf_git_common_path(&sb, the_repository, "config"); + repo_common_path_append(the_repository, &sb, "config"); read_repository_format(&repo_fmt, sb.buf); strbuf_release(&sb); @@ -1822,7 +1822,7 @@ const char *setup_git_directory_gently(int *nongit_ok) * * Regardless of the state of nongit_ok, startup_info->prefix and * the GIT_PREFIX environment variable must always match. For details - * see Documentation/config/alias.txt. + * see Documentation/config/alias.adoc. */ if (nongit_ok && *nongit_ok) startup_info->have_repository = 0; @@ -2088,7 +2088,7 @@ static void copy_templates_1(struct strbuf *path, struct strbuf *template_path, * with the way the namespace under .git/ is organized, should * be really carefully chosen. */ - safe_create_dir(path->buf, 1); + safe_create_dir(the_repository, path->buf, 1); while ((de = readdir(dir)) != NULL) { struct stat st_git, st_template; int exists = 0; @@ -2242,7 +2242,7 @@ void initialize_repository_version(int hash_algo, struct strbuf config = STRBUF_INIT; struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT; - strbuf_git_common_path(&config, the_repository, "config"); + repo_common_path_append(the_repository, &config, "config"); read_repository_format(&repo_fmt, config.buf); if (repo_fmt.v1_only_extensions.nr) @@ -2264,7 +2264,7 @@ static int is_reinit(void) char junk[2]; int ret; - git_path_buf(&buf, "HEAD"); + repo_git_path_replace(the_repository, &buf, "HEAD"); ret = !access(buf.buf, R_OK) || readlink(buf.buf, junk, sizeof(junk) - 1) != -1; strbuf_release(&buf); return ret; @@ -2316,8 +2316,7 @@ static int create_default_files(const char *template_path, int init_shared_repository) { struct stat st1; - struct strbuf buf = STRBUF_INIT; - char *path; + struct strbuf path = STRBUF_INIT; int reinit; int filemode; const char *work_tree = repo_get_work_tree(the_repository); @@ -2333,7 +2332,7 @@ static int create_default_files(const char *template_path, */ copy_templates(template_path); git_config_clear(); - reset_shared_repository(); + repo_settings_reset_shared_repository(the_repository); git_config(git_default_config, NULL); reinit = is_reinit(); @@ -2343,7 +2342,8 @@ static int create_default_files(const char *template_path, * values we might have just re-read from the config. */ if (init_shared_repository != -1) - set_shared_repository(init_shared_repository); + repo_settings_set_shared_repository(the_repository, + init_shared_repository); is_bare_repository_cfg = !work_tree; @@ -2351,21 +2351,21 @@ static int create_default_files(const char *template_path, * We would have created the above under user's umask -- under * shared-repository settings, we would need to fix them up. */ - if (get_shared_repository()) { - adjust_shared_perm(repo_get_git_dir(the_repository)); + if (repo_settings_get_shared_repository(the_repository)) { + adjust_shared_perm(the_repository, repo_get_git_dir(the_repository)); } initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, reinit); /* Check filemode trustability */ - path = git_path_buf(&buf, "config"); + repo_git_path_replace(the_repository, &path, "config"); filemode = TEST_FILEMODE; - if (TEST_FILEMODE && !lstat(path, &st1)) { + if (TEST_FILEMODE && !lstat(path.buf, &st1)) { struct stat st2; - filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) && - !lstat(path, &st2) && + filemode = (!chmod(path.buf, st1.st_mode ^ S_IXUSR) && + !lstat(path.buf, &st2) && st1.st_mode != st2.st_mode && - !chmod(path, st1.st_mode)); + !chmod(path.buf, st1.st_mode)); if (filemode && !reinit && (st1.st_mode & S_IXUSR)) filemode = 0; } @@ -2384,24 +2384,24 @@ static int create_default_files(const char *template_path, if (!reinit) { /* Check if symlink is supported in the work tree */ - path = git_path_buf(&buf, "tXXXXXX"); - if (!close(xmkstemp(path)) && - !unlink(path) && - !symlink("testing", path) && - !lstat(path, &st1) && + repo_git_path_replace(the_repository, &path, "tXXXXXX"); + if (!close(xmkstemp(path.buf)) && + !unlink(path.buf) && + !symlink("testing", path.buf) && + !lstat(path.buf, &st1) && S_ISLNK(st1.st_mode)) - unlink(path); /* good */ + unlink(path.buf); /* good */ else git_config_set("core.symlinks", "false"); /* Check if the filesystem is case-insensitive */ - path = git_path_buf(&buf, "CoNfIg"); - if (!access(path, F_OK)) + repo_git_path_replace(the_repository, &path, "CoNfIg"); + if (!access(path.buf, F_OK)) git_config_set("core.ignorecase", "true"); probe_utf8_pathname_composition(); } - strbuf_release(&buf); + strbuf_release(&path); return reinit; } @@ -2413,15 +2413,15 @@ static void create_object_directory(void) strbuf_addstr(&path, repo_get_object_directory(the_repository)); baselen = path.len; - safe_create_dir(path.buf, 1); + safe_create_dir(the_repository, path.buf, 1); strbuf_setlen(&path, baselen); strbuf_addstr(&path, "/pack"); - safe_create_dir(path.buf, 1); + safe_create_dir(the_repository, path.buf, 1); strbuf_setlen(&path, baselen); strbuf_addstr(&path, "/info"); - safe_create_dir(path.buf, 1); + safe_create_dir(the_repository, path.buf, 1); strbuf_release(&path); } @@ -2592,7 +2592,7 @@ int init_db(const char *git_dir, const char *real_git_dir, */ git_config(platform_core_config, NULL); - safe_create_dir(git_dir, 0); + safe_create_dir(the_repository, git_dir, 0); reinit = create_default_files(template_dir, original_git_dir, &repo_fmt, init_shared_repository); @@ -2602,7 +2602,7 @@ int init_db(const char *git_dir, const char *real_git_dir, initial_branch, flags & INIT_DB_QUIET); create_object_directory(); - if (get_shared_repository()) { + if (repo_settings_get_shared_repository(the_repository)) { char buf[10]; /* We do not spell "group" and such, so that * the configuration can be read by older version @@ -2610,12 +2610,12 @@ int init_db(const char *git_dir, const char *real_git_dir, * and compatibility values for PERM_GROUP and * PERM_EVERYBODY. */ - if (get_shared_repository() < 0) + if (repo_settings_get_shared_repository(the_repository) < 0) /* force to the mode value */ - xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository()); - else if (get_shared_repository() == PERM_GROUP) + xsnprintf(buf, sizeof(buf), "0%o", -repo_settings_get_shared_repository(the_repository)); + else if (repo_settings_get_shared_repository(the_repository) == PERM_GROUP) xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP); - else if (get_shared_repository() == PERM_EVERYBODY) + else if (repo_settings_get_shared_repository(the_repository) == PERM_EVERYBODY) xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY); else BUG("invalid value for shared_repository"); @@ -2627,12 +2627,12 @@ int init_db(const char *git_dir, const char *real_git_dir, int len = strlen(git_dir); if (reinit) - printf(get_shared_repository() + printf(repo_settings_get_shared_repository(the_repository) ? _("Reinitialized existing shared Git repository in %s%s\n") : _("Reinitialized existing Git repository in %s%s\n"), git_dir, len && git_dir[len-1] != '/' ? "/" : ""); else - printf(get_shared_repository() + printf(repo_settings_get_shared_repository(the_repository) ? _("Initialized empty shared Git repository in %s%s\n") : _("Initialized empty Git repository in %s%s\n"), git_dir, len && git_dir[len-1] != '/' ? "/" : ""); @@ -364,7 +364,9 @@ const char *setup_temporary_shallow(const struct oid_array *extra) struct strbuf sb = STRBUF_INIT; if (write_shallow_commits(&sb, 0, extra)) { - temp = xmks_tempfile(git_path("shallow_XXXXXX")); + char *path = repo_git_path(the_repository, "shallow_XXXXXX"); + temp = xmks_tempfile(path); + free(path); if (write_in_full(temp->fd, sb.buf, sb.len) < 0 || close_tempfile_gently(temp) < 0) diff --git a/simple-ipc.h b/simple-ipc.h index 3916eaf70d..701e005cb8 100644 --- a/simple-ipc.h +++ b/simple-ipc.h @@ -2,7 +2,7 @@ #define GIT_SIMPLE_IPC_H /* - * See Documentation/technical/api-simple-ipc.txt + * See Documentation/technical/api-simple-ipc.adoc */ enum ipc_active_state { diff --git a/submodule.c b/submodule.c index b361076c5b..0530e8cf24 100644 --- a/submodule.c +++ b/submodule.c @@ -536,7 +536,8 @@ static struct repository *open_submodule(const char *path) struct strbuf sb = STRBUF_INIT; struct repository *out = xmalloc(sizeof(*out)); - if (submodule_to_gitdir(&sb, path) || repo_init(out, sb.buf, NULL)) { + if (submodule_to_gitdir(the_repository, &sb, path) || + repo_init(out, sb.buf, NULL)) { strbuf_release(&sb); free(out); return NULL; @@ -1315,7 +1316,7 @@ static int repo_has_absorbed_submodules(struct repository *r) int ret; struct strbuf buf = STRBUF_INIT; - strbuf_repo_git_path(&buf, r, "modules/"); + repo_git_path_append(r, &buf, "modules/"); ret = file_exists(buf.buf) && !is_empty_dir(buf.buf); strbuf_release(&buf); return ret; @@ -2572,7 +2573,8 @@ int get_superproject_working_tree(struct strbuf *buf) * Put the gitdir for a submodule (given relative to the main * repository worktree) into `buf`, or return -1 on error. */ -int submodule_to_gitdir(struct strbuf *buf, const char *submodule) +int submodule_to_gitdir(struct repository *repo, + struct strbuf *buf, const char *submodule) { const struct submodule *sub; const char *git_dir; @@ -2592,14 +2594,13 @@ int submodule_to_gitdir(struct strbuf *buf, const char *submodule) strbuf_addstr(buf, git_dir); } if (!is_git_directory(buf->buf)) { - sub = submodule_from_path(the_repository, null_oid(), - submodule); + sub = submodule_from_path(repo, null_oid(), submodule); if (!sub) { ret = -1; goto cleanup; } strbuf_reset(buf); - submodule_name_to_gitdir(buf, the_repository, sub->name); + submodule_name_to_gitdir(buf, repo, sub->name); } cleanup: @@ -2629,6 +2630,6 @@ void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r, * administrators can explicitly set. Nothing has been decided, * so for now, just append the name at the end of the path. */ - strbuf_repo_git_path(buf, r, "modules/"); + repo_git_path_append(r, buf, "modules/"); strbuf_addstr(buf, submodule_name); } diff --git a/submodule.h b/submodule.h index 4deb1b5f84..db980c1d08 100644 --- a/submodule.h +++ b/submodule.h @@ -136,7 +136,8 @@ int push_unpushed_submodules(struct repository *r, * path of that submodule in 'buf'. Return -1 on error or when the * submodule is not initialized. */ -int submodule_to_gitdir(struct strbuf *buf, const char *submodule); +int submodule_to_gitdir(struct repository *repo, + struct strbuf *buf, const char *submodule); /* * Given a submodule name, create a path to where the submodule's gitdir lives diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh index 6e3bcc4aec..6cb0ff11de 100755 --- a/t/aggregate-results.sh +++ b/t/aggregate-results.sh @@ -44,7 +44,7 @@ then tr -s "," "\n" | grep -v '^$' | sort -u | - paste -s -d ' ') + paste -s -d ' ' -) if test -n "$unique_missing_prereq" then printf "\nmissing prereq: $unique_missing_prereq\n\n" diff --git a/t/helper/meson.build b/t/helper/meson.build index 1d6154ce97..d2cabaa2bc 100644 --- a/t/helper/meson.build +++ b/t/helper/meson.build @@ -80,14 +80,14 @@ test_tool_sources = [ test_tool = executable('test-tool', sources: test_tool_sources, - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], ) bin_wrappers += test_tool test_dependencies += test_tool test_fake_ssh = executable('test-fake-ssh', sources: 'test-fake-ssh.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], ) bin_wrappers += test_fake_ssh test_dependencies += test_fake_ssh diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 1cc05f043a..e00fce592b 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -75,11 +75,10 @@ static const char **get_store(const char **argv, struct ref_store **refs) *refs = get_main_ref_store(the_repository); } else if (skip_prefix(argv[0], "submodule:", &gitdir)) { struct strbuf sb = STRBUF_INIT; - int ret; - ret = strbuf_git_path_submodule(&sb, gitdir, "objects/"); - if (ret) - die("strbuf_git_path_submodule failed: %d", ret); + if (!repo_submodule_path_append(the_repository, + &sb, gitdir, "objects/")) + die("computing submodule path failed"); add_to_alternates_memory(sb.buf); strbuf_release(&sb); diff --git a/t/helper/test-rot13-filter.c b/t/helper/test-rot13-filter.c index ff407b575c..722b1cbe77 100644 --- a/t/helper/test-rot13-filter.c +++ b/t/helper/test-rot13-filter.c @@ -1,6 +1,6 @@ /* * Example implementation for the Git filter protocol version 2 - * See Documentation/gitattributes.txt, section "Filter Protocol" + * See Documentation/gitattributes.adoc, section "Filter Protocol" * * Usage: test-tool rot13-filter [--always-delay] --log=<path> <capabilities> * diff --git a/t/interop/Makefile b/t/interop/Makefile index 6911c2915a..4ff4ed0616 100644 --- a/t/interop/Makefile +++ b/t/interop/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +all:: + # Import tree-wide shared Makefile behavior and libraries include ../../shared.mak @@ -8,7 +11,7 @@ SHELL_PATH ?= $(SHELL) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) T = $(sort $(wildcard i[0-9][0-9][0-9][0-9]-*.sh)) -all: $(T) +all:: $(T) $(T): @echo "*** $@ ***"; '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) diff --git a/t/lib-gettext.sh b/t/lib-gettext.sh index 7a734c6973..b3dd68b0b9 100644 --- a/t/lib-gettext.sh +++ b/t/lib-gettext.sh @@ -7,7 +7,7 @@ . ./test-lib.sh GIT_TEXTDOMAINDIR="$GIT_TEST_TEXTDOMAINDIR" -GIT_PO_PATH="$GIT_TEST_POPATH" +GIT_PO_PATH="$GIT_SOURCE_DIR/po" export GIT_TEXTDOMAINDIR GIT_PO_PATH if test -n "$GIT_TEST_INSTALLED" diff --git a/t/meson.build b/t/meson.build index 780939d49f..8b3aed14ea 100644 --- a/t/meson.build +++ b/t/meson.build @@ -4,6 +4,9 @@ clar_test_suites = [ 'unit-tests/u-hash.c', 'unit-tests/u-hashmap.c', 'unit-tests/u-mem-pool.c', + 'unit-tests/u-oid-array.c', + 'unit-tests/u-oidmap.c', + 'unit-tests/u-oidtree.c', 'unit-tests/u-prio-queue.c', 'unit-tests/u-reftable-tree.c', 'unit-tests/u-strbuf.c', @@ -14,6 +17,7 @@ clar_test_suites = [ clar_sources = [ 'unit-tests/clar/clar.c', 'unit-tests/unit-test.c', + 'unit-tests/lib-oid.c' ] clar_decls_h = custom_target( @@ -43,14 +47,11 @@ clar_sources += custom_target( clar_unit_tests = executable('unit-tests', sources: clar_sources + clar_test_suites, - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], ) test('unit-tests', clar_unit_tests) unit_test_programs = [ - 'unit-tests/t-oid-array.c', - 'unit-tests/t-oidmap.c', - 'unit-tests/t-oidtree.c', 'unit-tests/t-reftable-basics.c', 'unit-tests/t-reftable-block.c', 'unit-tests/t-reftable-merged.c', @@ -68,11 +69,10 @@ foreach unit_test_program : unit_test_programs unit_test = executable(unit_test_name, sources: [ 'unit-tests/test-lib.c', - 'unit-tests/lib-oid.c', 'unit-tests/lib-reftable.c', unit_test_program, ], - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], ) test(unit_test_name, unit_test, workdir: meson.current_source_dir(), @@ -500,6 +500,7 @@ integration_tests = [ 't4067-diff-partial-clone.sh', 't4068-diff-symmetric-merge-base.sh', 't4069-remerge-diff.sh', + 't4070-diff-pairs.sh', 't4100-apply-stat.sh', 't4101-apply-nonl.sh', 't4102-apply-rename.sh', @@ -729,6 +730,7 @@ integration_tests = [ 't5703-upload-pack-ref-in-want.sh', 't5704-protocol-violations.sh', 't5705-session-id-in-capabilities.sh', + 't5710-promisor-remote-capability.sh', 't5730-protocol-v2-bundle-uri-file.sh', 't5731-protocol-v2-bundle-uri-git.sh', 't5732-protocol-v2-bundle-uri-http.sh', diff --git a/t/perf/Makefile b/t/perf/Makefile index e4808aebed..9b3090c4ed 100644 --- a/t/perf/Makefile +++ b/t/perf/Makefile @@ -1,10 +1,13 @@ +# The default target of this Makefile is... +all:: + # Import tree-wide shared Makefile behavior and libraries include ../../shared.mak -include ../../config.mak export GIT_TEST_OPTIONS -all: test-lint perf +all:: test-lint perf perf: pre-clean ./run diff --git a/t/t0091-bugreport.sh b/t/t0091-bugreport.sh index e11d819b62..e38ca7a901 100755 --- a/t/t0091-bugreport.sh +++ b/t/t0091-bugreport.sh @@ -47,7 +47,8 @@ test_expect_success 'sanity check "System Info" section' ' # This is bound to differ from environment to environment, # so we just do some rather high-level checks. grep "uname: ." system && - grep "compiler info: ." system + grep "compiler info: ." system && + grep "zlib." system ' test_expect_success 'dies if file with same name as report already exists' ' diff --git a/t/t0450-txt-doc-vs-help.sh b/t/t0450-txt-doc-vs-help.sh index 853101b86e..2f7504ae7e 100755 --- a/t/t0450-txt-doc-vs-help.sh +++ b/t/t0450-txt-doc-vs-help.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='assert (unbuilt) Documentation/*.txt and -h output +test_description='assert (unbuilt) Documentation/*.adoc and -h output Run this with --debug to see a summary of where we still fail to make the two versions consistent with one another.' @@ -11,11 +11,11 @@ test_expect_success 'setup: list of builtins' ' git --list-cmds=builtins >builtins ' -test_expect_success 'list of txt and help mismatches is sorted' ' - sort -u "$TEST_DIRECTORY"/t0450/txt-help-mismatches >expect && - if ! test_cmp expect "$TEST_DIRECTORY"/t0450/txt-help-mismatches +test_expect_success 'list of adoc and help mismatches is sorted' ' + sort -u "$TEST_DIRECTORY"/t0450/adoc-help-mismatches >expect && + if ! test_cmp expect "$TEST_DIRECTORY"/t0450/adoc-help-mismatches then - BUG "please keep the list of txt and help mismatches sorted" + BUG "please keep the list of adoc and help mismatches sorted" fi ' @@ -40,20 +40,20 @@ help_to_synopsis () { echo "$out" } -builtin_to_txt () { - echo "$GIT_BUILD_DIR/Documentation/git-$1.txt" +builtin_to_adoc () { + echo "$GIT_BUILD_DIR/Documentation/git-$1.adoc" } -txt_to_synopsis () { +adoc_to_synopsis () { builtin="$1" && out_dir="out/$builtin" && - out="$out_dir/txt.synopsis" && + out="$out_dir/adoc.synopsis" && if test -f "$out" then echo "$out" && return 0 fi && - b2t="$(builtin_to_txt "$builtin")" && + b2t="$(builtin_to_adoc "$builtin")" && sed -n \ -E '/^\[(verse|synopsis)\]$/,/^$/ { /^$/d; @@ -109,29 +109,29 @@ do fi ' - txt="$(builtin_to_txt "$builtin")" && - preq="$(echo BUILTIN_TXT_$builtin | tr '[:lower:]-' '[:upper:]_')" && + adoc="$(builtin_to_adoc "$builtin")" && + preq="$(echo BUILTIN_ADOC_$builtin | tr '[:lower:]-' '[:upper:]_')" && - if test -f "$txt" + if test -f "$adoc" then test_set_prereq "$preq" fi && - # *.txt output assertions - test_expect_success "$preq" "$builtin *.txt SYNOPSIS has dashed labels" ' - check_dashed_labels "$(txt_to_synopsis "$builtin")" + # *.adoc output assertions + test_expect_success "$preq" "$builtin *.adoc SYNOPSIS has dashed labels" ' + check_dashed_labels "$(adoc_to_synopsis "$builtin")" ' - # *.txt output consistency assertions + # *.adoc output consistency assertions result= - if grep -q "^$builtin$" "$TEST_DIRECTORY"/t0450/txt-help-mismatches + if grep -q "^$builtin$" "$TEST_DIRECTORY"/t0450/adoc-help-mismatches then result=failure else result=success fi && test_expect_$result "$preq" "$builtin -h output and SYNOPSIS agree" ' - t2s="$(txt_to_synopsis "$builtin")" && + t2s="$(adoc_to_synopsis "$builtin")" && if test "$builtin" = "merge-tree" then test_when_finished "rm -f t2s.new" && @@ -140,17 +140,17 @@ do fi && h2s="$(help_to_synopsis "$builtin")" && - # The *.txt and -h use different spacing for the + # The *.adoc and -h use different spacing for the # alignment of continued usage output, normalize it. - align_after_nl "$builtin" <"$t2s" >txt && + align_after_nl "$builtin" <"$t2s" >adoc && align_after_nl "$builtin" <"$h2s" >help && - test_cmp txt help + test_cmp adoc help ' - if test_have_prereq "$preq" && test -e txt && test -e help + if test_have_prereq "$preq" && test -e adoc && test -e help then test_debug ' - if test_cmp txt help >cmp 2>/dev/null + if test_cmp adoc help >cmp 2>/dev/null then echo "=== DONE: $builtin ===" else @@ -161,7 +161,7 @@ do # Not in test_expect_success in case --run is being # used with --debug - rm -f txt help tmp 2>/dev/null + rm -f adoc help tmp 2>/dev/null fi done <builtins diff --git a/t/t0450/txt-help-mismatches b/t/t0450/adoc-help-mismatches index c4a15fd0cb..c4a15fd0cb 100644 --- a/t/t0450/txt-help-mismatches +++ b/t/t0450/adoc-help-mismatches diff --git a/t/t0602-reffiles-fsck.sh b/t/t0602-reffiles-fsck.sh index d4a08b823b..9d1dc2144c 100755 --- a/t/t0602-reffiles-fsck.sh +++ b/t/t0602-reffiles-fsck.sh @@ -14,222 +14,229 @@ test_expect_success 'ref name should be checked' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - - git commit --allow-empty -m initial && - git checkout -b default-branch && - git tag default-tag && - git tag multi_hierarchy/default-tag && - - cp $branch_dir_prefix/default-branch $branch_dir_prefix/@ && - git refs verify 2>err && - test_must_be_empty err && - rm $branch_dir_prefix/@ && - - cp $tag_dir_prefix/default-tag $tag_dir_prefix/tag-1.lock && - git refs verify 2>err && - rm $tag_dir_prefix/tag-1.lock && - test_must_be_empty err && - - cp $tag_dir_prefix/default-tag $tag_dir_prefix/.lock && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/tags/.lock: badRefName: invalid refname format - EOF - rm $tag_dir_prefix/.lock && - test_cmp expect err && - - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname" && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/$refname: badRefName: invalid refname format - EOF - rm "$branch_dir_prefix/$refname" && - test_cmp expect err || return 1 - done && + ( + cd repo && - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - cp $tag_dir_prefix/default-tag "$tag_dir_prefix/$refname" && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/tags/$refname: badRefName: invalid refname format - EOF - rm "$tag_dir_prefix/$refname" && - test_cmp expect err || return 1 - done && + git commit --allow-empty -m initial && + git checkout -b default-branch && + git tag default-tag && + git tag multi_hierarchy/default-tag && - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - cp $tag_dir_prefix/multi_hierarchy/default-tag "$tag_dir_prefix/multi_hierarchy/$refname" && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/tags/multi_hierarchy/$refname: badRefName: invalid refname format - EOF - rm "$tag_dir_prefix/multi_hierarchy/$refname" && - test_cmp expect err || return 1 - done && + cp $branch_dir_prefix/default-branch $branch_dir_prefix/@ && + git refs verify 2>err && + test_must_be_empty err && + rm $branch_dir_prefix/@ && + + cp $tag_dir_prefix/default-tag $tag_dir_prefix/tag-1.lock && + git refs verify 2>err && + rm $tag_dir_prefix/tag-1.lock && + test_must_be_empty err && - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - mkdir "$branch_dir_prefix/$refname" && - cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname/default-branch" && + cp $tag_dir_prefix/default-tag $tag_dir_prefix/.lock && test_must_fail git refs verify 2>err && cat >expect <<-EOF && - error: refs/heads/$refname/default-branch: badRefName: invalid refname format + error: refs/tags/.lock: badRefName: invalid refname format EOF - rm -r "$branch_dir_prefix/$refname" && - test_cmp expect err || return 1 - done + rm $tag_dir_prefix/.lock && + test_cmp expect err && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/$refname: badRefName: invalid refname format + EOF + rm "$branch_dir_prefix/$refname" && + test_cmp expect err || return 1 + done && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + cp $tag_dir_prefix/default-tag "$tag_dir_prefix/$refname" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/tags/$refname: badRefName: invalid refname format + EOF + rm "$tag_dir_prefix/$refname" && + test_cmp expect err || return 1 + done && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + cp $tag_dir_prefix/multi_hierarchy/default-tag "$tag_dir_prefix/multi_hierarchy/$refname" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/tags/multi_hierarchy/$refname: badRefName: invalid refname format + EOF + rm "$tag_dir_prefix/multi_hierarchy/$refname" && + test_cmp expect err || return 1 + done && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + mkdir "$branch_dir_prefix/$refname" && + cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname/default-branch" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/$refname/default-branch: badRefName: invalid refname format + EOF + rm -r "$branch_dir_prefix/$refname" && + test_cmp expect err || return 1 + done + ) ' test_expect_success 'ref name check should be adapted into fsck messages' ' test_when_finished "rm -rf repo" && git init repo && branch_dir_prefix=.git/refs/heads && - cd repo && - git commit --allow-empty -m initial && - git checkout -b branch-1 && - - cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && - git -c fsck.badRefName=warn refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/.branch-1: badRefName: invalid refname format - EOF - rm $branch_dir_prefix/.branch-1 && - test_cmp expect err && - - cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && - git -c fsck.badRefName=ignore refs verify 2>err && - test_must_be_empty err + ( + cd repo && + git commit --allow-empty -m initial && + git checkout -b branch-1 && + + cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && + git -c fsck.badRefName=warn refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/.branch-1: badRefName: invalid refname format + EOF + rm $branch_dir_prefix/.branch-1 && + test_cmp expect err && + + cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && + git -c fsck.badRefName=ignore refs verify 2>err && + test_must_be_empty err + ) ' test_expect_success 'ref name check should work for multiple worktrees' ' test_when_finished "rm -rf repo" && git init repo && - - cd repo && - test_commit initial && - git checkout -b branch-1 && - test_commit second && - git checkout -b branch-2 && - test_commit third && - git checkout -b branch-3 && - git worktree add ./worktree-1 branch-1 && - git worktree add ./worktree-2 branch-2 && - worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && - worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && - ( - cd worktree-1 && - git update-ref refs/worktree/branch-4 refs/heads/branch-3 - ) && - ( - cd worktree-2 && - git update-ref refs/worktree/branch-4 refs/heads/branch-3 - ) && - - cp $worktree1_refdir_prefix/branch-4 $worktree1_refdir_prefix/'\'' branch-5'\'' && - cp $worktree2_refdir_prefix/branch-4 $worktree2_refdir_prefix/'\''~branch-6'\'' && - - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format - error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format - EOF - sort err >sorted_err && - test_cmp expect sorted_err && - - for worktree in "worktree-1" "worktree-2" - do + cd repo && + test_commit initial && + git checkout -b branch-1 && + test_commit second && + git checkout -b branch-2 && + test_commit third && + git checkout -b branch-3 && + git worktree add ./worktree-1 branch-1 && + git worktree add ./worktree-2 branch-2 && + worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && + worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + ( - cd $worktree && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format - error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format - EOF - sort err >sorted_err && - test_cmp expect sorted_err || return 1 - ) - done + cd worktree-1 && + git update-ref refs/worktree/branch-4 refs/heads/branch-3 + ) && + ( + cd worktree-2 && + git update-ref refs/worktree/branch-4 refs/heads/branch-3 + ) && + + cp $worktree1_refdir_prefix/branch-4 $worktree1_refdir_prefix/'\'' branch-5'\'' && + cp $worktree2_refdir_prefix/branch-4 $worktree2_refdir_prefix/'\''~branch-6'\'' && + + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format + error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format + EOF + sort err >sorted_err && + test_cmp expect sorted_err && + + for worktree in "worktree-1" "worktree-2" + do + ( + cd $worktree && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format + error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format + EOF + sort err >sorted_err && + test_cmp expect sorted_err || return 1 + ) + done + ) ' test_expect_success 'regular ref content should be checked (individual)' ' test_when_finished "rm -rf repo" && git init repo && branch_dir_prefix=.git/refs/heads && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && - git refs verify 2>err && - test_must_be_empty err && + git refs verify 2>err && + test_must_be_empty err && - for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$branch_dir_prefix/branch-bad && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/branch-bad: badRefContent: $bad_content - EOF - rm $branch_dir_prefix/branch-bad && - test_cmp expect err || return 1 - done && + for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$branch_dir_prefix/branch-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/branch-bad: badRefContent: $bad_content + EOF + rm $branch_dir_prefix/branch-bad && + test_cmp expect err || return 1 + done && - for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$branch_dir_prefix/a/b/branch-bad && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/a/b/branch-bad: badRefContent: $bad_content - EOF - rm $branch_dir_prefix/a/b/branch-bad && - test_cmp expect err || return 1 - done && - - printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end - EOF - rm $branch_dir_prefix/branch-no-newline && - test_cmp expect err && - - for trailing_content in " garbage" " more garbage" - do - printf "%s" "$(git rev-parse main)$trailing_content" >$branch_dir_prefix/branch-garbage && + for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$branch_dir_prefix/a/b/branch-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/a/b/branch-bad: badRefContent: $bad_content + EOF + rm $branch_dir_prefix/a/b/branch-bad && + test_cmp expect err || return 1 + done && + + printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && git refs verify 2>err && cat >expect <<-EOF && - warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end EOF - rm $branch_dir_prefix/branch-garbage && - test_cmp expect err || return 1 - done && + rm $branch_dir_prefix/branch-no-newline && + test_cmp expect err && - printf "%s\n\n\n" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse main)$trailing_content" >$branch_dir_prefix/branch-garbage && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + EOF + rm $branch_dir_prefix/branch-garbage && + test_cmp expect err || return 1 + done && + printf "%s\n\n\n" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' - '\'' - EOF - rm $branch_dir_prefix/branch-garbage-special && - test_cmp expect err && - printf "%s\n\n\n garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' + '\'' + EOF + rm $branch_dir_prefix/branch-garbage-special && + test_cmp expect err && + + printf "%s\n\n\n garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' - garbage'\'' - EOF - rm $branch_dir_prefix/branch-garbage-special && - test_cmp expect err + garbage'\'' + EOF + rm $branch_dir_prefix/branch-garbage-special && + test_cmp expect err + ) ' test_expect_success 'regular ref content should be checked (aggregate)' ' @@ -237,99 +244,103 @@ test_expect_success 'regular ref content should be checked (aggregate)' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && - - bad_content_1=$(git rev-parse main)x && - bad_content_2=xfsazqfxcadas && - bad_content_3=Xfsazqfxcadas && - printf "%s" $bad_content_1 >$tag_dir_prefix/tag-bad-1 && - printf "%s" $bad_content_2 >$tag_dir_prefix/tag-bad-2 && - printf "%s" $bad_content_3 >$branch_dir_prefix/a/b/branch-bad && - printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && - printf "%s garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage && - - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/a/b/branch-bad: badRefContent: $bad_content_3 - error: refs/tags/tag-bad-1: badRefContent: $bad_content_1 - error: refs/tags/tag-bad-2: badRefContent: $bad_content_2 - warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' - warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end - EOF - sort err >sorted_err && - test_cmp expect sorted_err + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + bad_content_1=$(git rev-parse main)x && + bad_content_2=xfsazqfxcadas && + bad_content_3=Xfsazqfxcadas && + printf "%s" $bad_content_1 >$tag_dir_prefix/tag-bad-1 && + printf "%s" $bad_content_2 >$tag_dir_prefix/tag-bad-2 && + printf "%s" $bad_content_3 >$branch_dir_prefix/a/b/branch-bad && + printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && + printf "%s garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage && + + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/a/b/branch-bad: badRefContent: $bad_content_3 + error: refs/tags/tag-bad-1: badRefContent: $bad_content_1 + error: refs/tags/tag-bad-2: badRefContent: $bad_content_2 + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' + warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end + EOF + sort err >sorted_err && + test_cmp expect sorted_err + ) ' test_expect_success 'textual symref content should be checked (individual)' ' test_when_finished "rm -rf repo" && git init repo && branch_dir_prefix=.git/refs/heads && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + for good_referent in "refs/heads/branch" "HEAD" + do + printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + git refs verify 2>err && + rm $branch_dir_prefix/branch-good && + test_must_be_empty err || return 1 + done && + + for bad_referent in "refs/heads/.branch" "refs/heads/~branch" "refs/heads/?branch" + do + printf "ref: %s\n" $bad_referent >$branch_dir_prefix/branch-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/branch-bad: badReferentName: points to invalid refname '\''$bad_referent'\'' + EOF + rm $branch_dir_prefix/branch-bad && + test_cmp expect err || return 1 + done && - for good_referent in "refs/heads/branch" "HEAD" - do - printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline && git refs verify 2>err && - rm $branch_dir_prefix/branch-good && - test_must_be_empty err || return 1 - done && + cat >expect <<-EOF && + warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end + EOF + rm $branch_dir_prefix/branch-no-newline && + test_cmp expect err && - for bad_referent in "refs/heads/.branch" "refs/heads/~branch" "refs/heads/?branch" - do - printf "ref: %s\n" $bad_referent >$branch_dir_prefix/branch-bad && - test_must_fail git refs verify 2>err && + printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-trailing-1 && + test_cmp expect err && + + printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-trailing-2 && + test_cmp expect err && + + printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && + git refs verify 2>err && cat >expect <<-EOF && - error: refs/heads/branch-bad: badReferentName: points to invalid refname '\''$bad_referent'\'' - EOF - rm $branch_dir_prefix/branch-bad && - test_cmp expect err || return 1 - done && - - printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end - EOF - rm $branch_dir_prefix/branch-no-newline && - test_cmp expect err && - - printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-trailing-1 && - test_cmp expect err && - - printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-trailing-2 && - test_cmp expect err && - - printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-trailing-3 && - test_cmp expect err && - - printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-complicated && - test_cmp expect err + warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-trailing-3 && + test_cmp expect err && + + printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-complicated && + test_cmp expect err + ) ' test_expect_success 'textual symref content should be checked (aggregate)' ' @@ -337,32 +348,34 @@ test_expect_success 'textual symref content should be checked (aggregate)' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && - - printf "ref: refs/heads/branch\n" >$branch_dir_prefix/branch-good && - printf "ref: HEAD\n" >$branch_dir_prefix/branch-head && - printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline-1 && - printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && - printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && - printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && - printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && - printf "ref: refs/heads/.branch\n" >$branch_dir_prefix/branch-bad-1 && - - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/branch-bad-1: badReferentName: points to invalid refname '\''refs/heads/.branch'\'' - warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/branch-no-newline-1: refMissingNewline: misses LF at the end - EOF - sort err >sorted_err && - test_cmp expect sorted_err + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + printf "ref: refs/heads/branch\n" >$branch_dir_prefix/branch-good && + printf "ref: HEAD\n" >$branch_dir_prefix/branch-head && + printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline-1 && + printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && + printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && + printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && + printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && + printf "ref: refs/heads/.branch\n" >$branch_dir_prefix/branch-bad-1 && + + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/branch-bad-1: badReferentName: points to invalid refname '\''refs/heads/.branch'\'' + warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/branch-no-newline-1: refMissingNewline: misses LF at the end + EOF + sort err >sorted_err && + test_cmp expect sorted_err + ) ' test_expect_success 'the target of the textual symref should be checked' ' @@ -370,230 +383,490 @@ test_expect_success 'the target of the textual symref should be checked' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + for good_referent in "refs/heads/branch" "HEAD" "refs/tags/tag" + do + printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + git refs verify 2>err && + rm $branch_dir_prefix/branch-good && + test_must_be_empty err || return 1 + done && + + for nonref_referent in "refs-back/heads/branch" "refs-back/tags/tag" "reflogs/refs/heads/branch" + do + printf "ref: %s\n" $nonref_referent >$branch_dir_prefix/branch-bad-1 && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-bad-1: symrefTargetIsNotARef: points to non-ref target '\''$nonref_referent'\'' + EOF + rm $branch_dir_prefix/branch-bad-1 && + test_cmp expect err || return 1 + done + ) +' + +test_expect_success SYMLINKS 'symlink symref content should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + branch_dir_prefix=.git/refs/heads && + tag_dir_prefix=.git/refs/tags && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && - for good_referent in "refs/heads/branch" "HEAD" "refs/tags/tag" - do - printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + ln -sf ./main $branch_dir_prefix/branch-symbolic-good && git refs verify 2>err && - rm $branch_dir_prefix/branch-good && - test_must_be_empty err || return 1 - done && + cat >expect <<-EOF && + warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $branch_dir_prefix/branch-symbolic-good && + test_cmp expect err && - for nonref_referent in "refs-back/heads/branch" "refs-back/tags/tag" "reflogs/refs/heads/branch" - do - printf "ref: %s\n" $nonref_referent >$branch_dir_prefix/branch-bad-1 && + ln -sf ../../logs/branch-escape $branch_dir_prefix/branch-symbolic && git refs verify 2>err && cat >expect <<-EOF && - warning: refs/heads/branch-bad-1: symrefTargetIsNotARef: points to non-ref target '\''$nonref_referent'\'' + warning: refs/heads/branch-symbolic: symlinkRef: use deprecated symbolic link for symref + warning: refs/heads/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' + EOF + rm $branch_dir_prefix/branch-symbolic && + test_cmp expect err && + + ln -sf ./"branch " $branch_dir_prefix/branch-symbolic-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-symbolic-bad: symlinkRef: use deprecated symbolic link for symref + error: refs/heads/branch-symbolic-bad: badReferentName: points to invalid refname '\''refs/heads/branch '\'' + EOF + rm $branch_dir_prefix/branch-symbolic-bad && + test_cmp expect err && + + ln -sf ./".tag" $tag_dir_prefix/tag-symbolic-1 && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/tags/tag-symbolic-1: symlinkRef: use deprecated symbolic link for symref + error: refs/tags/tag-symbolic-1: badReferentName: points to invalid refname '\''refs/tags/.tag'\'' EOF - rm $branch_dir_prefix/branch-bad-1 && - test_cmp expect err || return 1 - done + rm $tag_dir_prefix/tag-symbolic-1 && + test_cmp expect err + ) ' -test_expect_success SYMLINKS 'symlink symref content should be checked' ' +test_expect_success SYMLINKS 'symlink symref content should be checked (worktree)' ' test_when_finished "rm -rf repo" && git init repo && - branch_dir_prefix=.git/refs/heads && - tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && - - ln -sf ./main $branch_dir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $branch_dir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../logs/branch-escape $branch_dir_prefix/branch-symbolic && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic: symlinkRef: use deprecated symbolic link for symref - warning: refs/heads/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' - EOF - rm $branch_dir_prefix/branch-symbolic && - test_cmp expect err && - - ln -sf ./"branch " $branch_dir_prefix/branch-symbolic-bad && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic-bad: symlinkRef: use deprecated symbolic link for symref - error: refs/heads/branch-symbolic-bad: badReferentName: points to invalid refname '\''refs/heads/branch '\'' - EOF - rm $branch_dir_prefix/branch-symbolic-bad && - test_cmp expect err && - - ln -sf ./".tag" $tag_dir_prefix/tag-symbolic-1 && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/tags/tag-symbolic-1: symlinkRef: use deprecated symbolic link for symref - error: refs/tags/tag-symbolic-1: badReferentName: points to invalid refname '\''refs/tags/.tag'\'' - EOF - rm $tag_dir_prefix/tag-symbolic-1 && - test_cmp expect err + ( + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git branch branch-3 && + git worktree add ./worktree-1 branch-2 && + git worktree add ./worktree-2 branch-3 && + main_worktree_refdir_prefix=.git/refs/heads && + worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && + worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + + ( + cd worktree-1 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + ( + cd worktree-2 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + + ln -sf ../../../../refs/heads/good-branch $worktree1_refdir_prefix/branch-symbolic-good && + git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $worktree1_refdir_prefix/branch-symbolic-good && + test_cmp expect err && + + ln -sf ../../../../worktrees/worktree-1/good-branch $worktree2_refdir_prefix/branch-symbolic-good && + git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-2/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $worktree2_refdir_prefix/branch-symbolic-good && + test_cmp expect err && + + ln -sf ../../worktrees/worktree-2/good-branch $main_worktree_refdir_prefix/branch-symbolic-good && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $main_worktree_refdir_prefix/branch-symbolic-good && + test_cmp expect err && + + ln -sf ../../../../logs/branch-escape $worktree1_refdir_prefix/branch-symbolic && + git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symlinkRef: use deprecated symbolic link for symref + warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' + EOF + rm $worktree1_refdir_prefix/branch-symbolic && + test_cmp expect err && + + for bad_referent_name in ".tag" "branch " + do + ln -sf ./"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-1/refs/worktree/$bad_referent_name'\'' + EOF + rm $worktree1_refdir_prefix/bad-symbolic && + test_cmp expect err && + + ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + EOF + rm $worktree1_refdir_prefix/bad-symbolic && + test_cmp expect err && + + ln -sf ./"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-2/refs/worktree/$bad_referent_name'\'' + EOF + rm $worktree2_refdir_prefix/bad-symbolic && + test_cmp expect err && + + ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + EOF + rm $worktree2_refdir_prefix/bad-symbolic && + test_cmp expect err || return 1 + done + ) ' -test_expect_success SYMLINKS 'symlink symref content should be checked (worktree)' ' +test_expect_success 'ref content checks should work with worktrees' ' test_when_finished "rm -rf repo" && git init repo && - cd repo && - test_commit default && - git branch branch-1 && - git branch branch-2 && - git branch branch-3 && - git worktree add ./worktree-1 branch-2 && - git worktree add ./worktree-2 branch-3 && - main_worktree_refdir_prefix=.git/refs/heads && - worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && - worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && - - ( - cd worktree-1 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && ( - cd worktree-2 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && - - ln -sf ../../../../refs/heads/good-branch $worktree1_refdir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $worktree1_refdir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../../../worktrees/worktree-1/good-branch $worktree2_refdir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-2/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $worktree2_refdir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../worktrees/worktree-2/good-branch $main_worktree_refdir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $main_worktree_refdir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../../../logs/branch-escape $worktree1_refdir_prefix/branch-symbolic && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symlinkRef: use deprecated symbolic link for symref - warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' - EOF - rm $worktree1_refdir_prefix/branch-symbolic && - test_cmp expect err && - - for bad_referent_name in ".tag" "branch " - do - ln -sf ./"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && - test_must_fail git refs verify 2>err && + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git branch branch-3 && + git worktree add ./worktree-1 branch-2 && + git worktree add ./worktree-2 branch-3 && + worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && + worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + + ( + cd worktree-1 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + ( + cd worktree-2 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + + for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$worktree1_refdir_prefix/bad-branch-1 && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-1/refs/worktree/bad-branch-1: badRefContent: $bad_content + EOF + rm $worktree1_refdir_prefix/bad-branch-1 && + test_cmp expect err || return 1 + done && + + for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$worktree2_refdir_prefix/bad-branch-2 && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-2/refs/worktree/bad-branch-2: badRefContent: $bad_content + EOF + rm $worktree2_refdir_prefix/bad-branch-2 && + test_cmp expect err || return 1 + done && + + printf "%s" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-no-newline && + git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-1/refs/worktree/$bad_referent_name'\'' + warning: worktrees/worktree-1/refs/worktree/branch-no-newline: refMissingNewline: misses LF at the end EOF - rm $worktree1_refdir_prefix/bad-symbolic && + rm $worktree1_refdir_prefix/branch-no-newline && test_cmp expect err && - ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && - test_must_fail git refs verify 2>err && + printf "%s garbage" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-garbage && + git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + warning: worktrees/worktree-1/refs/worktree/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' EOF - rm $worktree1_refdir_prefix/bad-symbolic && - test_cmp expect err && + rm $worktree1_refdir_prefix/branch-garbage && + test_cmp expect err + ) +' - ln -sf ./"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && +test_expect_success SYMLINKS 'the filetype of packed-refs should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git branch branch-3 && + git pack-refs --all && + + mv .git/packed-refs .git/packed-refs-back && + ln -sf packed-refs-back .git/packed-refs && test_must_fail git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-2/refs/worktree/$bad_referent_name'\'' + error: packed-refs: badRefFiletype: not a regular file but a symlink EOF - rm $worktree2_refdir_prefix/bad-symbolic && + rm .git/packed-refs && test_cmp expect err && - ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && + mkdir .git/packed-refs && test_must_fail git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + error: packed-refs: badRefFiletype: not a regular file EOF - rm $worktree2_refdir_prefix/bad-symbolic && - test_cmp expect err || return 1 - done + rm -r .git/packed-refs && + test_cmp expect err + ) ' -test_expect_success 'ref content checks should work with worktrees' ' +test_expect_success 'packed-refs header should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + + git refs verify 2>err && + test_must_be_empty err && + + for bad_header in "# pack-refs wit: peeled fully-peeled sorted " \ + "# pack-refs with traits: peeled fully-peeled sorted " \ + "# pack-refs with a: peeled fully-peeled" \ + "# pack-refs with:peeled fully-peeled sorted" + do + printf "%s\n" "$bad_header" >.git/packed-refs && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: packed-refs.header: badPackedRefHeader: '\''$bad_header'\'' does not start with '\''# pack-refs with: '\'' + EOF + rm .git/packed-refs && + test_cmp expect err || return 1 + done + ) +' + +test_expect_success 'packed-refs missing header should not be reported' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + + printf "$(git rev-parse HEAD) refs/heads/main\n" >.git/packed-refs && + git refs verify 2>err && + test_must_be_empty err + ) +' + +test_expect_success 'packed-refs unknown traits should not be reported' ' test_when_finished "rm -rf repo" && git init repo && - cd repo && - test_commit default && - git branch branch-1 && - git branch branch-2 && - git branch branch-3 && - git worktree add ./worktree-1 branch-2 && - git worktree add ./worktree-2 branch-3 && - worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && - worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + ( + cd repo && + test_commit default && + + printf "# pack-refs with: peeled fully-peeled sorted foo\n" >.git/packed-refs && + git refs verify 2>err && + test_must_be_empty err + ) +' +test_expect_success 'packed-refs content should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && ( - cd worktree-1 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git tag -a annotated-tag-1 -m tag-1 && + git tag -a annotated-tag-2 -m tag-2 && + + branch_1_oid=$(git rev-parse branch-1) && + branch_2_oid=$(git rev-parse branch-2) && + tag_1_oid=$(git rev-parse annotated-tag-1) && + tag_2_oid=$(git rev-parse annotated-tag-2) && + tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) && + tag_2_peeled_oid=$(git rev-parse annotated-tag-2^{}) && + short_oid=$(printf "%s" $tag_1_peeled_oid | cut -c 1-4) && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $short_oid refs/heads/branch-1 + ${branch_1_oid}x + $branch_2_oid refs/heads/bad-branch + $branch_2_oid refs/heads/branch. + $tag_1_oid refs/tags/annotated-tag-3 + ^$short_oid + $tag_2_oid refs/tags/annotated-tag-4. + ^$tag_2_peeled_oid garbage + EOF + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: packed-refs line 2: badPackedRefEntry: '\''$short_oid refs/heads/branch-1'\'' has invalid oid + error: packed-refs line 3: badPackedRefEntry: has no space after oid '\''$branch_1_oid'\'' but with '\''x'\'' + error: packed-refs line 4: badRefName: has bad refname '\'' refs/heads/bad-branch'\'' + error: packed-refs line 5: badRefName: has bad refname '\''refs/heads/branch.'\'' + error: packed-refs line 7: badPackedRefEntry: '\''$short_oid'\'' has invalid peeled oid + error: packed-refs line 8: badRefName: has bad refname '\''refs/tags/annotated-tag-4.'\'' + error: packed-refs line 9: badPackedRefEntry: has trailing garbage after peeled oid '\'' garbage'\'' + EOF + test_cmp expect err + ) +' + +test_expect_success 'packed-ref with sorted trait should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && ( - cd worktree-2 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git tag -a annotated-tag-1 -m tag-1 && + branch_1_oid=$(git rev-parse branch-1) && + branch_2_oid=$(git rev-parse branch-2) && + tag_1_oid=$(git rev-parse annotated-tag-1) && + tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) && + refname1="refs/heads/main" && + refname2="refs/heads/foo" && + refname3="refs/tags/foo" && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + EOF + git refs verify 2>err && + rm .git/packed-refs && + test_must_be_empty err && - for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$worktree1_refdir_prefix/bad-branch-1 && + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $branch_2_oid $refname1 + EOF + git refs verify 2>err && + rm .git/packed-refs && + test_must_be_empty err && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $branch_2_oid $refname1 + $branch_1_oid $refname2 + $tag_1_oid $refname3 + EOF test_must_fail git refs verify 2>err && cat >expect <<-EOF && - error: worktrees/worktree-1/refs/worktree/bad-branch-1: badRefContent: $bad_content + error: packed-refs line 3: packedRefUnsorted: refname '\''$refname2'\'' is less than previous refname '\''$refname1'\'' EOF - rm $worktree1_refdir_prefix/bad-branch-1 && - test_cmp expect err || return 1 - done && + rm .git/packed-refs && + test_cmp expect err && - for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$worktree2_refdir_prefix/bad-branch-2 && + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $tag_1_oid $refname3 + ^$tag_1_peeled_oid + $branch_2_oid $refname2 + EOF test_must_fail git refs verify 2>err && cat >expect <<-EOF && - error: worktrees/worktree-2/refs/worktree/bad-branch-2: badRefContent: $bad_content - EOF - rm $worktree2_refdir_prefix/bad-branch-2 && - test_cmp expect err || return 1 - done && - - printf "%s" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-no-newline && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-no-newline: refMissingNewline: misses LF at the end - EOF - rm $worktree1_refdir_prefix/branch-no-newline && - test_cmp expect err && - - printf "%s garbage" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-garbage && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' - EOF - rm $worktree1_refdir_prefix/branch-garbage && - test_cmp expect err + error: packed-refs line 4: packedRefUnsorted: refname '\''$refname2'\'' is less than previous refname '\''$refname3'\'' + EOF + rm .git/packed-refs && + test_cmp expect err + ) +' + +test_expect_success 'packed-ref without sorted trait should not be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git tag -a annotated-tag-1 -m tag-1 && + branch_1_oid=$(git rev-parse branch-1) && + branch_2_oid=$(git rev-parse branch-2) && + tag_1_oid=$(git rev-parse annotated-tag-1) && + tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) && + refname1="refs/heads/main" && + refname2="refs/heads/foo" && + refname3="refs/tags/foo" && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled + $branch_2_oid $refname1 + $branch_1_oid $refname2 + EOF + git refs verify 2>err && + test_must_be_empty err + ) +' + +test_expect_success '--[no-]references option should apply to fsck' ' + test_when_finished "rm -rf repo" && + git init repo && + branch_dir_prefix=.git/refs/heads && + ( + cd repo && + test_commit default && + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage && + git fsck 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + EOF + rm $branch_dir_prefix/branch-garbage && + test_cmp expect err || return 1 + done && + + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage && + git fsck --references 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + EOF + rm $branch_dir_prefix/branch-garbage && + test_cmp expect err || return 1 + done && + + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage && + git fsck --no-references 2>err && + rm $branch_dir_prefix/branch-garbage && + test_must_be_empty err || return 1 + done + ) ' test_done diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh index 4618ffc108..002a75dee8 100755 --- a/t/t0610-reftable-basics.sh +++ b/t/t0610-reftable-basics.sh @@ -14,6 +14,13 @@ export GIT_TEST_DEFAULT_REF_FORMAT INVALID_OID=$(test_oid 001) +test_expect_success 'pack-refs does not crash with -h' ' + test_expect_code 129 git pack-refs -h >usage && + test_grep "[Uu]sage: git pack-refs " usage && + test_expect_code 129 nongit git pack-refs -h >usage && + test_grep "[Uu]sage: git pack-refs " usage +' + test_expect_success 'init: creates basic reftable structures' ' test_when_finished "rm -rf repo" && git init repo && diff --git a/t/t1419-exclude-refs.sh b/t/t1419-exclude-refs.sh index c04eeb7211..04797aee59 100755 --- a/t/t1419-exclude-refs.sh +++ b/t/t1419-exclude-refs.sh @@ -46,6 +46,10 @@ test_expect_success 'setup' ' echo "create refs/heads/$name/$i $base" || return 1 done || return 1 done >in && + for i in 5 6 7 + do + echo "create refs/heads/bar/4/$i $base" || return 1 + done >>in && echo "delete refs/heads/main" >>in && git update-ref --stdin <in && @@ -99,9 +103,17 @@ test_expect_success 'adjacent, non-overlapping excluded regions' ' esac ' -test_expect_success 'overlapping excluded regions' ' +test_expect_success 'non-directory excluded regions' ' for_each_ref__exclude refs/heads refs/heads/ba refs/heads/baz >actual 2>perf && - for_each_ref refs/heads/foo refs/heads/quux >expect && + for_each_ref refs/heads/bar refs/heads/foo refs/heads/quux >expect && + + test_cmp expect actual && + assert_jumps 1 perf +' + +test_expect_success 'overlapping excluded regions' ' + for_each_ref__exclude refs/heads refs/heads/bar refs/heads/bar/4 >actual 2>perf && + for_each_ref refs/heads/baz refs/heads/foo refs/heads/quux >expect && test_cmp expect actual && assert_jumps 1 perf @@ -155,4 +167,14 @@ test_expect_success 'meta-characters are discarded' ' assert_no_jumps perf ' +test_expect_success 'empty string exclude pattern is ignored' ' + git update-ref refs/heads/loose $(git rev-parse refs/heads/foo/1) && + + for_each_ref__exclude refs/heads "" >actual 2>perf && + for_each_ref >expect && + + test_cmp expect actual && + assert_no_jumps perf +' + test_done diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh index a6d9b35a46..2ab97e1b7d 100755 --- a/t/t1460-refs-migrate.sh +++ b/t/t1460-refs-migrate.sh @@ -9,14 +9,21 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME # Migrate the provided repository from one format to the other and # verify that the references and logs are migrated over correctly. -# Usage: test_migration <repo> <format> <skip_reflog_verify> +# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]] # <repo> is the relative path to the repo to be migrated. # <format> is the ref format to be migrated to. -# <skip_reflog_verify> (true or false) whether to skip reflog verification. +# <skip_reflog_verify> (default: false) whether to skip reflog verification. +# <options...> are other options be passed directly to 'git refs migrate'. test_migration () { repo=$1 && format=$2 && - skip_reflog_verify=${3:-false} && + shift 2 && + skip_reflog_verify=false && + if test $# -ge 1 + then + skip_reflog_verify=$1 + shift + fi && git -C "$repo" for-each-ref --include-root-refs \ --format='%(refname) %(objectname) %(symref)' >expect && if ! $skip_reflog_verify @@ -25,7 +32,7 @@ test_migration () { git -C "$repo" reflog list >expect_log_list fi && - git -C "$repo" refs migrate --ref-format="$2" && + git -C "$repo" refs migrate --ref-format="$format" "$@" && git -C "$repo" for-each-ref --include-root-refs \ --format='%(refname) %(objectname) %(symref)' >actual && @@ -241,6 +248,19 @@ do test_cmp expect.reflog actual.reflog ) ' + + test_expect_success "$from_format -> $to_format: skip reflog with --skip-reflog" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + # we see that the repository contains reflogs. + git -C repo reflog --all >reflogs && + test_line_count = 2 reflogs && + test_migration repo "$to_format" true --no-reflog && + # there should be no reflogs post migration. + git -C repo reflog --all >reflogs && + test_must_be_empty reflogs + ' done done diff --git a/t/t2006-checkout-index-basic.sh b/t/t2006-checkout-index-basic.sh index bac231b167..fedd2cc097 100755 --- a/t/t2006-checkout-index-basic.sh +++ b/t/t2006-checkout-index-basic.sh @@ -21,6 +21,13 @@ test_expect_success 'checkout-index -h in broken repository' ' test_grep "[Uu]sage" broken/usage ' +test_expect_success 'checkout-index does not crash with -h' ' + test_expect_code 129 git checkout-index -h >usage && + test_grep "[Uu]sage: git checkout-index " usage && + test_expect_code 129 nongit git checkout-index -h >usage && + test_grep "[Uu]sage: git checkout-index " usage +' + test_expect_success 'checkout-index reports errors (cmdline)' ' test_must_fail git checkout-index -- does-not-exist 2>stderr && test_grep not.in.the.cache stderr diff --git a/t/t3004-ls-files-basic.sh b/t/t3004-ls-files-basic.sh index a1078f8701..4034a5a59f 100755 --- a/t/t3004-ls-files-basic.sh +++ b/t/t3004-ls-files-basic.sh @@ -34,6 +34,13 @@ test_expect_success 'ls-files -h in corrupt repository' ' test_grep "[Uu]sage: git ls-files " broken/usage ' +test_expect_success 'ls-files does not crash with -h' ' + test_expect_code 129 git ls-files -h >usage && + test_grep "[Uu]sage: git ls-files " usage && + test_expect_code 129 nongit git ls-files -h >usage && + test_grep "[Uu]sage: git ls-files " usage +' + test_expect_success SYMLINKS 'ls-files with absolute paths to symlinks' ' mkdir subs && ln -s nosuch link && diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index ecfc02062c..2aee9789a2 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -791,6 +791,20 @@ test_expect_success 'reword' ' grep "C changed" actual ' +test_expect_success 'reword fast-forwarded empty commit' ' + git commit --allow-empty -m "empty commit" --only && + ( + set_fake_editor && + FAKE_COMMIT_AMEND=edited FAKE_LINES="reword 1" \ + git rebase -i HEAD^ + ) && + test_commit_message HEAD <<-\EOF + empty commit + + edited + EOF +' + test_expect_success 'no uncommitted changes when rewording and the todo list is reloaded' ' git checkout E && test_when_finished "git checkout @{-1}" && diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh index 2593711fec..b84d68c4b9 100755 --- a/t/t3430-rebase-merges.sh +++ b/t/t3430-rebase-merges.sh @@ -610,4 +610,24 @@ test_expect_success 'truncate label names' ' grep "label 0123456789-$" out ' +test_expect_success 'reword fast-forwarded empty merge commit' ' + oid="$(git commit-tree -m "D1" -p A D^{tree})" && + oid="$(git commit-tree -m "empty merge" -p D -p $oid D^{tree})" && + + write_script sequence-editor.sh <<-\EOF && + sed /^merge/s/-C/-c/ "$1" >"$1.tmp" + mv "$1.tmp" "$1" + EOF + + ( + test_set_sequence_editor "$(pwd)/sequence-editor.sh" && + GIT_EDITOR="echo edited >>" git rebase -i -r D $oid + ) && + test_commit_message HEAD <<-\EOF + empty merge + + edited + EOF +' + test_done diff --git a/t/t4070-diff-pairs.sh b/t/t4070-diff-pairs.sh new file mode 100755 index 0000000000..70deafb860 --- /dev/null +++ b/t/t4070-diff-pairs.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description='basic diff-pairs tests' +. ./test-lib.sh + +# This creates a diff with added, modified, deleted, renamed, copied, and +# typechange entries. This includes a submodule to test submodule diff support. +test_expect_success 'setup' ' + test_config_global protocol.file.allow always && + git init sub && + test_commit -C sub initial && + + git init main && + cd main && + echo to-be-gone >deleted && + echo original >modified && + echo now-a-file >symlink && + test_seq 200 >two-hundred && + test_seq 201 500 >five-hundred && + git add . && + test_tick && + git commit -m base && + git tag base && + + git submodule add ../sub && + echo now-here >added && + echo new >modified && + rm deleted && + mkdir subdir && + echo content >subdir/file && + mv two-hundred renamed && + test_seq 201 500 | sed s/300/modified/ >copied && + rm symlink && + git add -A . && + test_ln_s_add dest symlink && + test_tick && + git commit -m new && + git tag new +' + +test_expect_success 'diff-pairs recreates --raw' ' + git diff-tree -r -M -C -C -z base new >expect && + git diff-pairs --raw -z >actual <expect && + test_cmp expect actual +' + +test_expect_success 'diff-pairs can create -p output' ' + git diff-tree -p -M -C -C base new >expect && + git diff-tree -r -M -C -C -z base new | + git diff-pairs -p -z >actual && + test_cmp expect actual +' + +test_expect_success 'diff-pairs does not support normal raw diff input' ' + git diff-tree -r base new | + test_must_fail git diff-pairs >out 2>err && + + echo "usage: working without -z is not supported" >expect && + test_must_be_empty out && + test_cmp expect err +' + +test_expect_success 'diff-pairs does not support tree objects as input' ' + git diff-tree -z base new | + test_must_fail git diff-pairs -z >out 2>err && + + echo "fatal: tree objects not supported" >expect && + test_must_be_empty out && + test_cmp expect err +' + +test_expect_success 'diff-pairs does not support pathspec arguments' ' + git diff-tree -r -z base new | + test_must_fail git diff-pairs -z -- new >out 2>err && + + echo "usage: pathspec arguments not supported" >expect && + test_must_be_empty out && + test_cmp expect err +' + +test_expect_success 'diff-pairs explicit queue flush' ' + git diff-tree -r -M -C -C -z base new >expect && + printf "\0" >>expect && + git diff-tree -r -M -C -C -z base new >>expect && + + git diff-pairs --raw -z <expect >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 2421491931..4a6242ff99 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -113,6 +113,18 @@ test_expect_success 'check-mailmap --stdin simple address: no mapping' ' test_cmp expect actual ' +test_expect_success 'check-mailmap name and address: mapping' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-EOF && + Bug Reports <bugs-new@company.xx> Bugs <bugs@company.xx> + EOF + cat >expect <<-EOF && + <bugs@company.xx> + EOF + git check-mailmap "bugs@company.xx" >actual && + test_cmp expect actual +' + test_expect_success 'No mailmap' ' cat >expect <<-EOF && $GIT_AUTHOR_NAME (1): diff --git a/t/t4209-log-pickaxe.sh b/t/t4209-log-pickaxe.sh index a675ace081..0e2f80a268 100755 --- a/t/t4209-log-pickaxe.sh +++ b/t/t4209-log-pickaxe.sh @@ -93,6 +93,22 @@ test_expect_success 'usage: --no-pickaxe-regex' ' test_cmp expect actual ' +test_expect_success 'usage: -G and -S with empty argument' ' + cat >expect <<-\EOF && + error: -S requires a non-empty argument + EOF + + test_expect_code 129 git log -S "" 2>actual && + test_cmp expect actual && + + cat >expect <<-\EOF && + error: -G requires a non-empty argument + EOF + + test_expect_code 129 git log -G "" 2>actual && + test_cmp expect actual +' + test_log expect_initial --grep initial test_log expect_nomatch --grep InItial test_log_icase expect_initial --grep InItial diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 3f81f16e13..8f018d2f23 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -55,6 +55,13 @@ test_expect_success setup ' echo Rebase && git log' +test_expect_success 'send-pack does not crash with -h' ' + test_expect_code 129 git send-pack -h >usage && + test_grep "[Uu]sage: git send-pack " usage && + test_expect_code 129 nongit git send-pack -h >usage && + test_grep "[Uu]sage: git send-pack " usage +' + test_expect_success 'pack the source repository' ' git repack -a -d && git prune diff --git a/t/t5503-tagfollow.sh b/t/t5503-tagfollow.sh index 195fc64dd4..845ca43ea0 100755 --- a/t/t5503-tagfollow.sh +++ b/t/t5503-tagfollow.sh @@ -160,4 +160,18 @@ test_expect_success 'new clone fetch main and tags' ' test_cmp expect actual ' +test_expect_success 'fetch specific OID with tag following' ' + git init --bare clone3.git && + ( + cd clone3.git && + git remote add origin .. && + git fetch origin $B:refs/heads/main && + + git -C .. for-each-ref >expect && + git for-each-ref >actual && + + test_cmp expect actual + ) +' + test_done diff --git a/t/t5540-http-push-webdav.sh b/t/t5540-http-push-webdav.sh index 37db3dec0c..3fa05ff185 100755 --- a/t/t5540-http-push-webdav.sh +++ b/t/t5540-http-push-webdav.sh @@ -201,4 +201,14 @@ test_expect_failure 'push to password-protected repository (no user in URL)' ' test_cmp expect actual ' +test_expect_success 'push to password-protected repository (netrc)' ' + test_commit pw-netrc && + echo "default login user@host password pass@host" >"$HOME/.netrc" && + GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push "$HTTPD_URL/auth/dumb/test_repo.git" HEAD && + git rev-parse --verify HEAD >expect && + git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \ + rev-parse --verify HEAD >actual && + test_cmp expect actual +' + test_done diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh index de904c1655..678a346ed0 100755 --- a/t/t5701-git-serve.sh +++ b/t/t5701-git-serve.sh @@ -7,24 +7,40 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh -test_expect_success 'test capability advertisement' ' +test_expect_success 'setup to generate files with expected content' ' + printf "agent=git/%s" "$(git version | cut -d" " -f3)" >agent_capability && + test_oid_cache <<-EOF && wrong_algo sha1:sha256 wrong_algo sha256:sha1 EOF + + if test_have_prereq WINDOWS + then + printf "agent=FAKE\n" >agent_capability + else + printf -- "-%s\n" $(uname -s | test_redact_non_printables) >>agent_capability + fi && cat >expect.base <<-EOF && version 2 - agent=git/$(git version | cut -d" " -f3) + $(cat agent_capability) ls-refs=unborn fetch=shallow wait-for-done server-option object-format=$(test_oid algo) EOF - cat >expect.trailer <<-EOF && + cat >expect.trailer <<-EOF 0000 EOF +' + +test_expect_success 'test capability advertisement' ' cat expect.base expect.trailer >expect && + if test_have_prereq WINDOWS + then + GIT_USER_AGENT=FAKE && export GIT_USER_AGENT + fi && GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \ --advertise-capabilities >out && test-tool pkt-line unpack <out >actual && @@ -355,6 +371,10 @@ test_expect_success 'test capability advertisement with uploadpack.advertiseBund expect.extra \ expect.trailer >expect && + if test_have_prereq WINDOWS + then + GIT_USER_AGENT=FAKE && export GIT_USER_AGENT + fi && GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \ --advertise-capabilities >out && test-tool pkt-line unpack <out >actual && diff --git a/t/t5710-promisor-remote-capability.sh b/t/t5710-promisor-remote-capability.sh new file mode 100755 index 0000000000..d2cc69a17e --- /dev/null +++ b/t/t5710-promisor-remote-capability.sh @@ -0,0 +1,312 @@ +#!/bin/sh + +test_description='handling of promisor remote advertisement' + +. ./test-lib.sh + +GIT_TEST_MULTI_PACK_INDEX=0 +GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 + +# Setup the repository with three commits, this way HEAD is always +# available and we can hide commit 1 or 2. +test_expect_success 'setup: create "template" repository' ' + git init template && + test_commit -C template 1 && + test_commit -C template 2 && + test_commit -C template 3 && + test-tool genrandom foo 10240 >template/foo && + git -C template add foo && + git -C template commit -m foo +' + +# A bare repo will act as a server repo with unpacked objects. +test_expect_success 'setup: create bare "server" repository' ' + git clone --bare --no-local template server && + mv server/objects/pack/pack-* . && + packfile=$(ls pack-*.pack) && + git -C server unpack-objects --strict <"$packfile" +' + +check_missing_objects () { + git -C "$1" rev-list --objects --all --missing=print > all.txt && + perl -ne 'print if s/^[?]//' all.txt >missing.txt && + test_line_count = "$2" missing.txt && + if test "$2" -lt 2 + then + test "$3" = "$(cat missing.txt)" + else + test -f "$3" && + sort <"$3" >expected_sorted && + sort <missing.txt >actual_sorted && + test_cmp expected_sorted actual_sorted + fi +} + +initialize_server () { + count="$1" + missing_oids="$2" + + # Repack everything first + git -C server -c repack.writebitmaps=false repack -a -d && + + # Remove promisor file in case they exist, useful when reinitializing + rm -rf server/objects/pack/*.promisor && + + # Repack without the largest object and create a promisor pack on server + git -C server -c repack.writebitmaps=false repack -a -d \ + --filter=blob:limit=5k --filter-to="$(pwd)/pack" && + promisor_file=$(ls server/objects/pack/*.pack | sed "s/\.pack/.promisor/") && + >"$promisor_file" && + + # Check objects missing on the server + check_missing_objects server "$count" "$missing_oids" +} + +copy_to_lop () { + oid_path="$(test_oid_to_path $1)" && + path="server/objects/$oid_path" && + path2="lop/objects/$oid_path" && + mkdir -p $(dirname "$path2") && + cp "$path" "$path2" +} + +test_expect_success "setup for testing promisor remote advertisement" ' + # Create another bare repo called "lop" (for Large Object Promisor) + git init --bare lop && + + # Copy the largest object from server to lop + obj="HEAD:foo" && + oid="$(git -C server rev-parse $obj)" && + copy_to_lop "$oid" && + + initialize_server 1 "$oid" && + + # Configure lop as promisor remote for server + git -C server remote add lop "file://$(pwd)/lop" && + git -C server config remote.lop.promisor true && + + git -C lop config uploadpack.allowFilter true && + git -C lop config uploadpack.allowAnySHA1InWant true && + git -C server config uploadpack.allowFilter true && + git -C server config uploadpack.allowAnySHA1InWant true +' + +test_expect_success "clone with promisor.advertise set to 'true'" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=All \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "clone with promisor.advertise set to 'false'" ' + git -C server config promisor.advertise false && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=All \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is not missing on the server + check_missing_objects server 0 "" && + + # Reinitialize server so that the largest object is missing again + initialize_server 1 "$oid" +' + +test_expect_success "clone with promisor.acceptfromserver set to 'None'" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=None \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is not missing on the server + check_missing_objects server 0 "" && + + # Reinitialize server so that the largest object is missing again + initialize_server 1 "$oid" +' + +test_expect_success "init + fetch with promisor.advertise set to 'true'" ' + git -C server config promisor.advertise true && + + test_when_finished "rm -rf client" && + mkdir client && + git -C client init && + git -C client config remote.lop.promisor true && + git -C client config remote.lop.fetch "+refs/heads/*:refs/remotes/lop/*" && + git -C client config remote.lop.url "file://$(pwd)/lop" && + git -C client config remote.server.url "file://$(pwd)/server" && + git -C client config remote.server.fetch "+refs/heads/*:refs/remotes/server/*" && + git -C client config promisor.acceptfromserver All && + GIT_NO_LAZY_FETCH=0 git -C client fetch --filter="blob:limit=5k" server && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "clone with promisor.acceptfromserver set to 'KnownName'" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=KnownName \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "clone with 'KnownName' and different remote names" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.serverTwo.promisor=true \ + -c remote.serverTwo.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.serverTwo.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=KnownName \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is not missing on the server + check_missing_objects server 0 "" && + + # Reinitialize server so that the largest object is missing again + initialize_server 1 "$oid" +' + +test_expect_success "clone with promisor.acceptfromserver set to 'KnownUrl'" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=KnownUrl \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "clone with 'KnownUrl' and different remote urls" ' + ln -s lop serverTwo && + + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/serverTwo" \ + -c promisor.acceptfromserver=KnownUrl \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is not missing on the server + check_missing_objects server 0 "" && + + # Reinitialize server so that the largest object is missing again + initialize_server 1 "$oid" +' + +test_expect_success "clone with promisor.advertise set to 'true' but don't delete the client" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=All \ + --no-local --filter="blob:limit=5k" server client && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "setup for subsequent fetches" ' + # Generate new commit with large blob + test-tool genrandom bar 10240 >template/bar && + git -C template add bar && + git -C template commit -m bar && + + # Fetch new commit with large blob + git -C server fetch origin && + git -C server update-ref HEAD FETCH_HEAD && + git -C server rev-parse HEAD >expected_head && + + # Repack everything twice and remove .promisor files before + # each repack. This makes sure everything gets repacked + # into a single packfile. The second repack is necessary + # because the first one fetches from lop and creates a new + # packfile and its associated .promisor file. + + rm -f server/objects/pack/*.promisor && + git -C server -c repack.writebitmaps=false repack -a -d && + rm -f server/objects/pack/*.promisor && + git -C server -c repack.writebitmaps=false repack -a -d && + + # Unpack everything + rm pack-* && + mv server/objects/pack/pack-* . && + packfile=$(ls pack-*.pack) && + git -C server unpack-objects --strict <"$packfile" && + + # Copy new large object to lop + obj_bar="HEAD:bar" && + oid_bar="$(git -C server rev-parse $obj_bar)" && + copy_to_lop "$oid_bar" && + + # Reinitialize server so that the 2 largest objects are missing + printf "%s\n" "$oid" "$oid_bar" >expected_missing.txt && + initialize_server 2 expected_missing.txt && + + # Create one more client + cp -r client client2 +' + +test_expect_success "subsequent fetch from a client when promisor.advertise is true" ' + git -C server config promisor.advertise true && + + GIT_NO_LAZY_FETCH=0 git -C client pull origin && + + git -C client rev-parse HEAD >actual && + test_cmp expected_head actual && + + cat client/bar >/dev/null && + + check_missing_objects server 2 expected_missing.txt +' + +test_expect_success "subsequent fetch from a client when promisor.advertise is false" ' + git -C server config promisor.advertise false && + + GIT_NO_LAZY_FETCH=0 git -C client2 pull origin && + + git -C client2 rev-parse HEAD >actual && + test_cmp expected_head actual && + + cat client2/bar >/dev/null && + + check_missing_objects server 1 "$oid" +' + +test_done diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh index de1e87f162..4cecb6224c 100755 --- a/t/t6012-rev-list-simplify.sh +++ b/t/t6012-rev-list-simplify.sh @@ -177,7 +177,7 @@ test_expect_success '--full-diff is not affected by --parents' ' # \ / /\ / # `---X--' `---Y--' # -# This example is explained in Documentation/rev-list-options.txt +# This example is explained in Documentation/rev-list-options.adoc test_expect_success 'setup rebuild repo' ' rm -rf .git * && diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index a5c7794385..9b4f4306c4 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -292,6 +292,13 @@ test_expect_success 'Check invalid atoms names are errors' ' test_must_fail git for-each-ref --format="%(INVALID)" refs/heads ' +test_expect_success 'for-each-ref does not crash with -h' ' + test_expect_code 129 git for-each-ref -h >usage && + test_grep "[Uu]sage: git for-each-ref " usage && + test_expect_code 129 nongit git for-each-ref -h >usage && + test_grep "[Uu]sage: git for-each-ref " usage +' + test_expect_success 'Check format specifiers are ignored in naming date atoms' ' git for-each-ref --format="%(authordate)" refs/heads && git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads && diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh index 94080c65d1..79d889b94c 100755 --- a/t/t6423-merge-rename-directories.sh +++ b/t/t6423-merge-rename-directories.sh @@ -5363,6 +5363,47 @@ test_expect_merge_algorithm failure success '12m: Change parent of renamed-dir t ) ' +test_setup_12n () { + git init 12n && + ( + cd 12n && + + mkdir tools && + echo hello >tools/hello && + git add tools/hello && + git commit -m "O" && + + git branch O && + git branch A && + git branch B && + + git switch A && + echo world >world && + git add world && + git commit -q world -m 'Add world' && + + git mv world tools/world && + git commit -m "Move world into tools/" && + + git switch B && + git mv tools/hello hello && + git commit -m "Move hello from tools/ to toplevel" + ) +} + +test_expect_success '12n: Directory rename transitively makes rename back to self' ' + test_setup_12n && + ( + cd 12n && + + git checkout -q B^0 && + + test_must_fail git cherry-pick A^0 >out && + grep "CONFLICT (file location).*should perhaps be moved" out + ) +' + + ########################################################################### # SECTION 13: Checking informational and conflict messages # diff --git a/t/t6434-merge-recursive-rename-options.sh b/t/t6434-merge-recursive-rename-options.sh index a11707835b..6e913c30a1 100755 --- a/t/t6434-merge-recursive-rename-options.sh +++ b/t/t6434-merge-recursive-rename-options.sh @@ -22,7 +22,7 @@ R075 2-old 2-new R100 3-old 3-new Actual similarity indices are parsed from diff output. We rely on the fact that -they are rounded down (see, e.g., Documentation/diff-generate-patch.txt, which +they are rounded down (see, e.g., Documentation/diff-generate-patch.adoc, which mentions this in a different context). ' diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh index 6f526c37c2..2c147072c1 100755 --- a/t/t7030-verify-tag.sh +++ b/t/t7030-verify-tag.sh @@ -7,6 +7,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY/lib-gpg.sh" +test_expect_success GPG 'verify-tag does not crash with -h' ' + test_expect_code 129 git verify-tag -h >usage && + test_grep "[Uu]sage: git verify-tag " usage && + test_expect_code 129 nongit git verify-tag -h >usage && + test_grep "[Uu]sage: git verify-tag " usage +' + test_expect_success GPG 'create signed tags' ' echo 1 >file && git add file && test_tick && git commit -m initial && diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh index 0d2dd29fe6..39677e859a 100755 --- a/t/t7510-signed-commit.sh +++ b/t/t7510-signed-commit.sh @@ -8,6 +8,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME GNUPGHOME_NOT_USED=$GNUPGHOME . "$TEST_DIRECTORY/lib-gpg.sh" +test_expect_success GPG 'verify-commit does not crash with -h' ' + test_expect_code 129 git verify-commit -h >usage && + test_grep "[Uu]sage: git verify-commit " usage && + test_expect_code 129 nongit git verify-commit -h >usage && + test_grep "[Uu]sage: git verify-commit " usage +' + test_expect_success GPG 'create signed commits' ' test_oid_cache <<-\EOF && header sha1:gpgsig diff --git a/t/t7609-mergetool--lib.sh b/t/t7609-mergetool--lib.sh index e8e205707e..af3ad284ee 100755 --- a/t/t7609-mergetool--lib.sh +++ b/t/t7609-mergetool--lib.sh @@ -7,7 +7,7 @@ Testing basic merge tools options' . ./test-lib.sh test_expect_success 'mergetool --tool=vimdiff creates the expected layout' ' - . "$GIT_TEST_MERGE_TOOLS_DIR"/vimdiff && + . "$GIT_SOURCE_DIR"/mergetools/vimdiff && run_unit_tests ' diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index b93736e0d5..79377bc0fc 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -2043,3 +2043,11 @@ test_trailing_hash () { test-tool hexdump | sed "s/ //g" } + +# Trim and replace each character with ascii code below 32 or above +# 127 (included) using a dot '.' character. +# Octal intervals \001-\040 and \177-\377 +# correspond to decimal intervals 1-32 and 127-255 +test_redact_non_printables () { + tr -d "\n\r" | tr "[\001-\040][\177-\377]" "." +} diff --git a/t/unit-tests/lib-oid.c b/t/unit-tests/lib-oid.c index 8f0ccac532..e0b3180f23 100644 --- a/t/unit-tests/lib-oid.c +++ b/t/unit-tests/lib-oid.c @@ -1,9 +1,9 @@ -#include "test-lib.h" +#include "unit-test.h" #include "lib-oid.h" #include "strbuf.h" #include "hex.h" -int init_hash_algo(void) +int cl_setup_hash_algo(void) { static int algo = -1; @@ -11,42 +11,32 @@ int init_hash_algo(void) const char *algo_name = getenv("GIT_TEST_DEFAULT_HASH"); algo = algo_name ? hash_algo_by_name(algo_name) : GIT_HASH_SHA1; - if (!check(algo != GIT_HASH_UNKNOWN)) - test_msg("BUG: invalid GIT_TEST_DEFAULT_HASH value ('%s')", - algo_name); + cl_assert(algo != GIT_HASH_UNKNOWN); } return algo; } -static int get_oid_arbitrary_hex_algop(const char *hex, struct object_id *oid, +static void cl_parse_oid(const char *hex, struct object_id *oid, const struct git_hash_algo *algop) { - int ret; size_t sz = strlen(hex); struct strbuf buf = STRBUF_INIT; - if (!check(sz <= algop->hexsz)) { - test_msg("BUG: hex string (%s) bigger than maximum allowed (%lu)", - hex, (unsigned long)algop->hexsz); - return -1; - } + cl_assert(sz <= algop->hexsz); strbuf_add(&buf, hex, sz); strbuf_addchars(&buf, '0', algop->hexsz - sz); - ret = get_oid_hex_algop(buf.buf, oid, algop); - if (!check_int(ret, ==, 0)) - test_msg("BUG: invalid hex input (%s) provided", hex); + cl_assert_equal_i(get_oid_hex_algop(buf.buf, oid, algop), 0); strbuf_release(&buf); - return ret; } -int get_oid_arbitrary_hex(const char *hex, struct object_id *oid) + +void cl_parse_any_oid(const char *hex, struct object_id *oid) { - int hash_algo = init_hash_algo(); + int hash_algo = cl_setup_hash_algo(); - if (!check_int(hash_algo, !=, GIT_HASH_UNKNOWN)) - return -1; - return get_oid_arbitrary_hex_algop(hex, oid, &hash_algos[hash_algo]); + cl_assert(hash_algo != GIT_HASH_UNKNOWN); + cl_parse_oid(hex, oid, &hash_algos[hash_algo]); } diff --git a/t/unit-tests/lib-oid.h b/t/unit-tests/lib-oid.h index 4e77c04bd2..4031775104 100644 --- a/t/unit-tests/lib-oid.h +++ b/t/unit-tests/lib-oid.h @@ -5,6 +5,7 @@ /* * Convert arbitrary hex string to object_id. + * * For example, passing "abc12" will generate * "abc1200000000000000000000000000000000000" hex of length 40 for SHA-1 and * create object_id with that. @@ -12,14 +13,16 @@ * algo is not allowed. The hash algo is decided based on GIT_TEST_DEFAULT_HASH * environment variable. */ -int get_oid_arbitrary_hex(const char *s, struct object_id *oid); + +void cl_parse_any_oid (const char *s, struct object_id *oid); /* * Returns one of GIT_HASH_{SHA1, SHA256, UNKNOWN} based on the value of * GIT_TEST_DEFAULT_HASH environment variable. The fallback value in the * absence of GIT_TEST_DEFAULT_HASH is GIT_HASH_SHA1. It also uses - * check(algo != GIT_HASH_UNKNOWN) before returning to verify if the + * cl_assert(algo != GIT_HASH_UNKNOWN) before returning to verify if the * GIT_TEST_DEFAULT_HASH's value is valid or not. */ -int init_hash_algo(void); + +int cl_setup_hash_algo(void); #endif /* LIB_OID_H */ diff --git a/t/unit-tests/t-oid-array.c b/t/unit-tests/t-oid-array.c deleted file mode 100644 index 45b59a2a51..0000000000 --- a/t/unit-tests/t-oid-array.c +++ /dev/null @@ -1,126 +0,0 @@ -#define USE_THE_REPOSITORY_VARIABLE - -#include "test-lib.h" -#include "lib-oid.h" -#include "oid-array.h" -#include "hex.h" - -static int fill_array(struct oid_array *array, const char *hexes[], size_t n) -{ - for (size_t i = 0; i < n; i++) { - struct object_id oid; - - if (!check_int(get_oid_arbitrary_hex(hexes[i], &oid), ==, 0)) - return -1; - oid_array_append(array, &oid); - } - if (!check_uint(array->nr, ==, n)) - return -1; - return 0; -} - -static int add_to_oid_array(const struct object_id *oid, void *data) -{ - struct oid_array *array = data; - - oid_array_append(array, oid); - return 0; -} - -static void t_enumeration(const char **input_args, size_t input_sz, - const char **expect_args, size_t expect_sz) -{ - struct oid_array input = OID_ARRAY_INIT, expect = OID_ARRAY_INIT, - actual = OID_ARRAY_INIT; - size_t i; - - if (fill_array(&input, input_args, input_sz)) - return; - if (fill_array(&expect, expect_args, expect_sz)) - return; - - oid_array_for_each_unique(&input, add_to_oid_array, &actual); - if (!check_uint(actual.nr, ==, expect.nr)) - return; - - for (i = 0; i < actual.nr; i++) { - if (!check(oideq(&actual.oid[i], &expect.oid[i]))) - test_msg("expected: %s\n got: %s\n index: %" PRIuMAX, - oid_to_hex(&expect.oid[i]), oid_to_hex(&actual.oid[i]), - (uintmax_t)i); - } - - oid_array_clear(&actual); - oid_array_clear(&input); - oid_array_clear(&expect); -} - -#define TEST_ENUMERATION(input, expect, desc) \ - TEST(t_enumeration(input, ARRAY_SIZE(input), expect, ARRAY_SIZE(expect)), \ - desc " works") - -static void t_lookup(const char **input_hexes, size_t n, const char *query_hex, - int lower_bound, int upper_bound) -{ - struct oid_array array = OID_ARRAY_INIT; - struct object_id oid_query; - int ret; - - if (!check_int(get_oid_arbitrary_hex(query_hex, &oid_query), ==, 0)) - return; - if (fill_array(&array, input_hexes, n)) - return; - ret = oid_array_lookup(&array, &oid_query); - - if (!check_int(ret, <=, upper_bound) || - !check_int(ret, >=, lower_bound)) - test_msg("oid query for lookup: %s", oid_to_hex(&oid_query)); - - oid_array_clear(&array); -} - -#define TEST_LOOKUP(input_hexes, query, lower_bound, upper_bound, desc) \ - TEST(t_lookup(input_hexes, ARRAY_SIZE(input_hexes), query, \ - lower_bound, upper_bound), \ - desc " works") - -static void setup(void) -{ - /* The hash algo is used by oid_array_lookup() internally */ - int algo = init_hash_algo(); - if (check_int(algo, !=, GIT_HASH_UNKNOWN)) - repo_set_hash_algo(the_repository, algo); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - const char *arr_input[] = { "88", "44", "aa", "55" }; - const char *arr_input_dup[] = { "88", "44", "aa", "55", - "88", "44", "aa", "55", - "88", "44", "aa", "55" }; - const char *res_sorted[] = { "44", "55", "88", "aa" }; - const char *nearly_55; - - if (!TEST(setup(), "setup")) - test_skip_all("hash algo initialization failed"); - - TEST_ENUMERATION(arr_input, res_sorted, "ordered enumeration"); - TEST_ENUMERATION(arr_input_dup, res_sorted, - "ordered enumeration with duplicate suppression"); - - TEST_LOOKUP(arr_input, "55", 1, 1, "lookup"); - TEST_LOOKUP(arr_input, "33", INT_MIN, -1, "lookup non-existent entry"); - TEST_LOOKUP(arr_input_dup, "55", 3, 5, "lookup with duplicates"); - TEST_LOOKUP(arr_input_dup, "66", INT_MIN, -1, - "lookup non-existent entry with duplicates"); - - nearly_55 = init_hash_algo() == GIT_HASH_SHA1 ? - "5500000000000000000000000000000000000001" : - "5500000000000000000000000000000000000000000000000000000000000001"; - TEST_LOOKUP(((const char *[]){ "55", nearly_55 }), "55", 0, 0, - "lookup with almost duplicate values"); - TEST_LOOKUP(((const char *[]){ "55", "55" }), "55", 0, 1, - "lookup with single duplicate value"); - - return test_done(); -} diff --git a/t/unit-tests/t-oidmap.c b/t/unit-tests/t-oidmap.c deleted file mode 100644 index b22e52d08b..0000000000 --- a/t/unit-tests/t-oidmap.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "test-lib.h" -#include "lib-oid.h" -#include "oidmap.h" -#include "hash.h" -#include "hex.h" - -/* - * Elements we will put in oidmap structs are made of a key: the entry.oid - * field, which is of type struct object_id, and a value: the name field (could - * be a refname for example). - */ -struct test_entry { - struct oidmap_entry entry; - char name[FLEX_ARRAY]; -}; - -static const char *const key_val[][2] = { { "11", "one" }, - { "22", "two" }, - { "33", "three" } }; - -static void setup(void (*f)(struct oidmap *map)) -{ - struct oidmap map = OIDMAP_INIT; - int ret = 0; - - for (size_t i = 0; i < ARRAY_SIZE(key_val); i++){ - struct test_entry *entry; - - FLEX_ALLOC_STR(entry, name, key_val[i][1]); - if ((ret = get_oid_arbitrary_hex(key_val[i][0], &entry->entry.oid))) { - free(entry); - break; - } - entry = oidmap_put(&map, entry); - if (!check(entry == NULL)) - free(entry); - } - - if (!ret) - f(&map); - oidmap_free(&map, 1); -} - -static void t_replace(struct oidmap *map) -{ - struct test_entry *entry, *prev; - - FLEX_ALLOC_STR(entry, name, "un"); - if (get_oid_arbitrary_hex("11", &entry->entry.oid)) - return; - prev = oidmap_put(map, entry); - if (!check(prev != NULL)) - return; - check_str(prev->name, "one"); - free(prev); - - FLEX_ALLOC_STR(entry, name, "deux"); - if (get_oid_arbitrary_hex("22", &entry->entry.oid)) - return; - prev = oidmap_put(map, entry); - if (!check(prev != NULL)) - return; - check_str(prev->name, "two"); - free(prev); -} - -static void t_get(struct oidmap *map) -{ - struct test_entry *entry; - struct object_id oid; - - if (get_oid_arbitrary_hex("22", &oid)) - return; - entry = oidmap_get(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "two"); - - if (get_oid_arbitrary_hex("44", &oid)) - return; - check(oidmap_get(map, &oid) == NULL); - - if (get_oid_arbitrary_hex("11", &oid)) - return; - entry = oidmap_get(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "one"); -} - -static void t_remove(struct oidmap *map) -{ - struct test_entry *entry; - struct object_id oid; - - if (get_oid_arbitrary_hex("11", &oid)) - return; - entry = oidmap_remove(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "one"); - check(oidmap_get(map, &oid) == NULL); - free(entry); - - if (get_oid_arbitrary_hex("22", &oid)) - return; - entry = oidmap_remove(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "two"); - check(oidmap_get(map, &oid) == NULL); - free(entry); - - if (get_oid_arbitrary_hex("44", &oid)) - return; - check(oidmap_remove(map, &oid) == NULL); -} - -static int key_val_contains(struct test_entry *entry, char seen[]) -{ - for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { - struct object_id oid; - - if (get_oid_arbitrary_hex(key_val[i][0], &oid)) - return -1; - - if (oideq(&entry->entry.oid, &oid)) { - if (seen[i]) - return 2; - seen[i] = 1; - return 0; - } - } - return 1; -} - -static void t_iterate(struct oidmap *map) -{ - struct oidmap_iter iter; - struct test_entry *entry; - char seen[ARRAY_SIZE(key_val)] = { 0 }; - int count = 0; - - oidmap_iter_init(map, &iter); - while ((entry = oidmap_iter_next(&iter))) { - int ret; - if (!check_int((ret = key_val_contains(entry, seen)), ==, 0)) { - switch (ret) { - case -1: - break; /* error message handled by get_oid_arbitrary_hex() */ - case 1: - test_msg("obtained entry was not given in the input\n" - " name: %s\n oid: %s\n", - entry->name, oid_to_hex(&entry->entry.oid)); - break; - case 2: - test_msg("duplicate entry detected\n" - " name: %s\n oid: %s\n", - entry->name, oid_to_hex(&entry->entry.oid)); - break; - default: - test_msg("BUG: invalid return value (%d) from key_val_contains()", - ret); - break; - } - } else { - count++; - } - } - check_int(count, ==, ARRAY_SIZE(key_val)); - check_int(hashmap_get_size(&map->map), ==, ARRAY_SIZE(key_val)); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(setup(t_replace), "replace works"); - TEST(setup(t_get), "get works"); - TEST(setup(t_remove), "remove works"); - TEST(setup(t_iterate), "iterate works"); - return test_done(); -} diff --git a/t/unit-tests/t-oidtree.c b/t/unit-tests/t-oidtree.c deleted file mode 100644 index a38754b066..0000000000 --- a/t/unit-tests/t-oidtree.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "test-lib.h" -#include "lib-oid.h" -#include "oidtree.h" -#include "hash.h" -#include "hex.h" -#include "strvec.h" - -#define FILL_TREE(tree, ...) \ - do { \ - const char *hexes[] = { __VA_ARGS__ }; \ - if (fill_tree_loc(tree, hexes, ARRAY_SIZE(hexes))) \ - return; \ - } while (0) - -static int fill_tree_loc(struct oidtree *ot, const char *hexes[], size_t n) -{ - for (size_t i = 0; i < n; i++) { - struct object_id oid; - if (!check_int(get_oid_arbitrary_hex(hexes[i], &oid), ==, 0)) - return -1; - oidtree_insert(ot, &oid); - } - return 0; -} - -static void check_contains(struct oidtree *ot, const char *hex, int expected) -{ - struct object_id oid; - - if (!check_int(get_oid_arbitrary_hex(hex, &oid), ==, 0)) - return; - if (!check_int(oidtree_contains(ot, &oid), ==, expected)) - test_msg("oid: %s", oid_to_hex(&oid)); -} - -struct expected_hex_iter { - size_t i; - struct strvec expected_hexes; - const char *query; -}; - -static enum cb_next check_each_cb(const struct object_id *oid, void *data) -{ - struct expected_hex_iter *hex_iter = data; - struct object_id expected; - - if (!check_int(hex_iter->i, <, hex_iter->expected_hexes.nr)) { - test_msg("error: extraneous callback for query: ('%s'), object_id: ('%s')", - hex_iter->query, oid_to_hex(oid)); - return CB_BREAK; - } - - if (!check_int(get_oid_arbitrary_hex(hex_iter->expected_hexes.v[hex_iter->i], - &expected), ==, 0)) - ; /* the data is bogus and cannot be used */ - else if (!check(oideq(oid, &expected))) - test_msg("expected: %s\n got: %s\n query: %s", - oid_to_hex(&expected), oid_to_hex(oid), hex_iter->query); - - hex_iter->i += 1; - return CB_CONTINUE; -} - -LAST_ARG_MUST_BE_NULL -static void check_each(struct oidtree *ot, const char *query, ...) -{ - struct object_id oid; - struct expected_hex_iter hex_iter = { .expected_hexes = STRVEC_INIT, - .query = query }; - const char *arg; - va_list hex_args; - - va_start(hex_args, query); - while ((arg = va_arg(hex_args, const char *))) - strvec_push(&hex_iter.expected_hexes, arg); - va_end(hex_args); - - if (!check_int(get_oid_arbitrary_hex(query, &oid), ==, 0)) - return; - oidtree_each(ot, &oid, strlen(query), check_each_cb, &hex_iter); - - if (!check_int(hex_iter.i, ==, hex_iter.expected_hexes.nr)) - test_msg("error: could not find some 'object_id's for query ('%s')", query); - strvec_clear(&hex_iter.expected_hexes); -} - -static void setup(void (*f)(struct oidtree *ot)) -{ - struct oidtree ot; - - oidtree_init(&ot); - f(&ot); - oidtree_clear(&ot); -} - -static void t_contains(struct oidtree *ot) -{ - FILL_TREE(ot, "444", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e"); - check_contains(ot, "44", 0); - check_contains(ot, "441", 0); - check_contains(ot, "440", 0); - check_contains(ot, "444", 1); - check_contains(ot, "4440", 1); - check_contains(ot, "4444", 0); -} - -static void t_each(struct oidtree *ot) -{ - FILL_TREE(ot, "f", "9", "8", "123", "321", "320", "a", "b", "c", "d", "e"); - check_each(ot, "12300", "123", NULL); - check_each(ot, "3211", NULL); /* should not reach callback */ - check_each(ot, "3210", "321", NULL); - check_each(ot, "32100", "321", NULL); - check_each(ot, "32", "320", "321", NULL); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(setup(t_contains), "oidtree insert and contains works"); - TEST(setup(t_each), "oidtree each works"); - return test_done(); -} diff --git a/t/unit-tests/u-oid-array.c b/t/unit-tests/u-oid-array.c new file mode 100644 index 0000000000..e48a433f21 --- /dev/null +++ b/t/unit-tests/u-oid-array.c @@ -0,0 +1,129 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "unit-test.h" +#include "lib-oid.h" +#include "oid-array.h" +#include "hex.h" + +static void fill_array(struct oid_array *array, const char *hexes[], size_t n) +{ + for (size_t i = 0; i < n; i++) { + struct object_id oid; + + cl_parse_any_oid(hexes[i], &oid); + oid_array_append(array, &oid); + } + cl_assert_equal_i(array->nr, n); +} + +static int add_to_oid_array(const struct object_id *oid, void *data) +{ + struct oid_array *array = data; + + oid_array_append(array, oid); + return 0; +} + +static void t_enumeration(const char **input_args, size_t input_sz, + const char **expect_args, size_t expect_sz) +{ + struct oid_array input = OID_ARRAY_INIT, expect = OID_ARRAY_INIT, + actual = OID_ARRAY_INIT; + size_t i; + + fill_array(&input, input_args, input_sz); + fill_array(&expect, expect_args, expect_sz); + + oid_array_for_each_unique(&input, add_to_oid_array, &actual); + cl_assert_equal_i(actual.nr, expect.nr); + + for (i = 0; i < actual.nr; i++) + cl_assert(oideq(&actual.oid[i], &expect.oid[i])); + + oid_array_clear(&actual); + oid_array_clear(&input); + oid_array_clear(&expect); +} + +#define TEST_ENUMERATION(input, expect) \ + t_enumeration(input, ARRAY_SIZE(input), expect, ARRAY_SIZE(expect)); + +static void t_lookup(const char **input_hexes, size_t n, const char *query_hex, + int lower_bound, int upper_bound) +{ + struct oid_array array = OID_ARRAY_INIT; + struct object_id oid_query; + int ret; + + cl_parse_any_oid(query_hex, &oid_query); + fill_array(&array, input_hexes, n); + ret = oid_array_lookup(&array, &oid_query); + + cl_assert(ret <= upper_bound); + cl_assert(ret >= lower_bound); + + oid_array_clear(&array); +} + +#define TEST_LOOKUP(input_hexes, query, lower_bound, upper_bound) \ + t_lookup(input_hexes, ARRAY_SIZE(input_hexes), query, \ + lower_bound, upper_bound); + +void test_oid_array__initialize(void) +{ + /* The hash algo is used by oid_array_lookup() internally */ + int algo = cl_setup_hash_algo(); + repo_set_hash_algo(the_repository, algo); +} + +static const char *arr_input[] = { "88", "44", "aa", "55" }; +static const char *arr_input_dup[] = { "88", "44", "aa", "55", + "88", "44", "aa", "55", + "88", "44", "aa", "55" }; +static const char *res_sorted[] = { "44", "55", "88", "aa" }; + +void test_oid_array__enumerate_unique(void) +{ + TEST_ENUMERATION(arr_input, res_sorted); +} + +void test_oid_array__enumerate_duplicate(void) +{ + TEST_ENUMERATION(arr_input_dup, res_sorted); +} + +void test_oid_array__lookup(void) +{ + TEST_LOOKUP(arr_input, "55", 1, 1); +} + +void test_oid_array__lookup_non_existent(void) +{ + TEST_LOOKUP(arr_input, "33", INT_MIN, -1); +} + +void test_oid_array__lookup_duplicates(void) +{ + TEST_LOOKUP(arr_input_dup, "55", 3, 5); +} + +void test_oid_array__lookup_non_existent_dup(void) +{ + TEST_LOOKUP(arr_input_dup, "66", INT_MIN, -1); +} + +void test_oid_array__lookup_almost_dup(void) +{ + const char *nearly_55; + + nearly_55 = cl_setup_hash_algo() == GIT_HASH_SHA1 ? + "5500000000000000000000000000000000000001" : + "5500000000000000000000000000000000000000000000000000000000000001"; + + TEST_LOOKUP(((const char *[]){ "55", nearly_55 }), "55", 0, 0); +} + +void test_oid_array__lookup_single_dup(void) +{ + TEST_LOOKUP(((const char *[]){ "55", "55" }), "55", 0, 1); +} diff --git a/t/unit-tests/u-oidmap.c b/t/unit-tests/u-oidmap.c new file mode 100644 index 0000000000..dc805b7e3c --- /dev/null +++ b/t/unit-tests/u-oidmap.c @@ -0,0 +1,136 @@ +#include "unit-test.h" +#include "lib-oid.h" +#include "oidmap.h" +#include "hash.h" +#include "hex.h" + +/* + * Elements we will put in oidmap structs are made of a key: the entry.oid + * field, which is of type struct object_id, and a value: the name field (could + * be a refname for example). + */ +struct test_entry { + struct oidmap_entry entry; + char name[FLEX_ARRAY]; +}; + +static const char *const key_val[][2] = { { "11", "one" }, + { "22", "two" }, + { "33", "three" } }; + +static struct oidmap map; + +void test_oidmap__initialize(void) +{ + oidmap_init(&map, 0); + + for (size_t i = 0; i < ARRAY_SIZE(key_val); i++){ + struct test_entry *entry; + + FLEX_ALLOC_STR(entry, name, key_val[i][1]); + cl_parse_any_oid(key_val[i][0], &entry->entry.oid); + cl_assert(oidmap_put(&map, entry) == NULL); + } +} + +void test_oidmap__cleanup(void) +{ + oidmap_free(&map, 1); +} + +void test_oidmap__replace(void) +{ + struct test_entry *entry, *prev; + + FLEX_ALLOC_STR(entry, name, "un"); + cl_parse_any_oid("11", &entry->entry.oid); + prev = oidmap_put(&map, entry); + cl_assert(prev != NULL); + cl_assert_equal_s(prev->name, "one"); + free(prev); + + FLEX_ALLOC_STR(entry, name, "deux"); + cl_parse_any_oid("22", &entry->entry.oid); + prev = oidmap_put(&map, entry); + cl_assert(prev != NULL); + cl_assert_equal_s(prev->name, "two"); + free(prev); +} + +void test_oidmap__get(void) +{ + struct test_entry *entry; + struct object_id oid; + + cl_parse_any_oid("22", &oid); + entry = oidmap_get(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "two"); + + cl_parse_any_oid("44", &oid); + cl_assert(oidmap_get(&map, &oid) == NULL); + + cl_parse_any_oid("11", &oid); + entry = oidmap_get(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "one"); +} + +void test_oidmap__remove(void) +{ + struct test_entry *entry; + struct object_id oid; + + cl_parse_any_oid("11", &oid); + entry = oidmap_remove(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "one"); + cl_assert(oidmap_get(&map, &oid) == NULL); + free(entry); + + cl_parse_any_oid("22", &oid); + entry = oidmap_remove(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "two"); + cl_assert(oidmap_get(&map, &oid) == NULL); + free(entry); + + cl_parse_any_oid("44", &oid); + cl_assert(oidmap_remove(&map, &oid) == NULL); +} + +static int key_val_contains(struct test_entry *entry, char seen[]) +{ + for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { + struct object_id oid; + + cl_parse_any_oid(key_val[i][0], &oid); + + if (oideq(&entry->entry.oid, &oid)) { + if (seen[i]) + return 2; + seen[i] = 1; + return 0; + } + } + return 1; +} + +void test_oidmap__iterate(void) +{ + struct oidmap_iter iter; + struct test_entry *entry; + char seen[ARRAY_SIZE(key_val)] = { 0 }; + int count = 0; + + oidmap_iter_init(&map, &iter); + while ((entry = oidmap_iter_next(&iter))) { + if (key_val_contains(entry, seen) != 0) { + cl_failf("Unexpected entry: name = %s, oid = %s", + entry->name, oid_to_hex(&entry->entry.oid)); + } + count++; + } + cl_assert_equal_i(count, ARRAY_SIZE(key_val)); + cl_assert_equal_i(hashmap_get_size(&map.map), ARRAY_SIZE(key_val)); +} diff --git a/t/unit-tests/u-oidtree.c b/t/unit-tests/u-oidtree.c new file mode 100644 index 0000000000..e6eede2740 --- /dev/null +++ b/t/unit-tests/u-oidtree.c @@ -0,0 +1,107 @@ +#include "unit-test.h" +#include "lib-oid.h" +#include "oidtree.h" +#include "hash.h" +#include "hex.h" +#include "strvec.h" + +static struct oidtree ot; + +#define FILL_TREE(tree, ...) \ + do { \ + const char *hexes[] = { __VA_ARGS__ }; \ + if (fill_tree_loc(tree, hexes, ARRAY_SIZE(hexes))) \ + return; \ + } while (0) + +static int fill_tree_loc(struct oidtree *ot, const char *hexes[], size_t n) +{ + for (size_t i = 0; i < n; i++) { + struct object_id oid; + cl_parse_any_oid(hexes[i], &oid); + oidtree_insert(ot, &oid); + } + return 0; +} + +static void check_contains(struct oidtree *ot, const char *hex, int expected) +{ + struct object_id oid; + + cl_parse_any_oid(hex, &oid); + cl_assert_equal_i(oidtree_contains(ot, &oid), expected); +} + +struct expected_hex_iter { + size_t i; + struct strvec expected_hexes; + const char *query; +}; + +static enum cb_next check_each_cb(const struct object_id *oid, void *data) +{ + struct expected_hex_iter *hex_iter = data; + struct object_id expected; + + cl_assert(hex_iter->i < hex_iter->expected_hexes.nr); + + cl_parse_any_oid(hex_iter->expected_hexes.v[hex_iter->i], + &expected); + cl_assert_equal_s(oid_to_hex(oid), oid_to_hex(&expected)); + hex_iter->i += 1; + return CB_CONTINUE; +} + +LAST_ARG_MUST_BE_NULL +static void check_each(struct oidtree *ot, const char *query, ...) +{ + struct object_id oid; + struct expected_hex_iter hex_iter = { .expected_hexes = STRVEC_INIT, + .query = query }; + const char *arg; + va_list hex_args; + + va_start(hex_args, query); + while ((arg = va_arg(hex_args, const char *))) + strvec_push(&hex_iter.expected_hexes, arg); + va_end(hex_args); + + cl_parse_any_oid(query, &oid); + oidtree_each(ot, &oid, strlen(query), check_each_cb, &hex_iter); + + if (hex_iter.i != hex_iter.expected_hexes.nr) + cl_failf("error: could not find some 'object_id's for query ('%s')", query); + + strvec_clear(&hex_iter.expected_hexes); +} + +void test_oidtree__initialize(void) +{ + oidtree_init(&ot); +} + +void test_oidtree__cleanup(void) +{ + oidtree_clear(&ot); +} + +void test_oidtree__contains(void) +{ + FILL_TREE(&ot, "444", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e"); + check_contains(&ot, "44", 0); + check_contains(&ot, "441", 0); + check_contains(&ot, "440", 0); + check_contains(&ot, "444", 1); + check_contains(&ot, "4440", 1); + check_contains(&ot, "4444", 0); +} + +void test_oidtree__each(void) +{ + FILL_TREE(&ot, "f", "9", "8", "123", "321", "320", "a", "b", "c", "d", "e"); + check_each(&ot, "12300", "123", NULL); + check_each(&ot, "3211", NULL); /* should not reach callback */ + check_each(&ot, "3210", "321", NULL); + check_each(&ot, "32100", "321", NULL); + check_each(&ot, "32", "320", "321", NULL); +} diff --git a/t/unit-tests/unit-test.c b/t/unit-tests/unit-test.c index fa8818842a..5af645048a 100644 --- a/t/unit-tests/unit-test.c +++ b/t/unit-tests/unit-test.c @@ -1,5 +1,7 @@ #include "unit-test.h" +#include "hex.h" #include "parse-options.h" +#include "strbuf.h" #include "string-list.h" #include "strvec.h" diff --git a/tempfile.c b/tempfile.c index ed88cf8431..82dfa3d82f 100644 --- a/tempfile.c +++ b/tempfile.c @@ -42,6 +42,8 @@ * file created by its parent. */ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "abspath.h" #include "path.h" @@ -148,7 +150,7 @@ struct tempfile *create_tempfile_mode(const char *path, int mode) return NULL; } activate_tempfile(tempfile); - if (adjust_shared_perm(tempfile->filename.buf)) { + if (adjust_shared_perm(the_repository, tempfile->filename.buf)) { int save_errno = errno; error("cannot fix permission bits on %s", tempfile->filename.buf); delete_tempfile(&tempfile); diff --git a/templates/Makefile b/templates/Makefile index bd1e9e30c1..722755338d 100644 --- a/templates/Makefile +++ b/templates/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +all:: + # Import tree-wide shared Makefile behavior and libraries include ../shared.mak @@ -23,7 +26,7 @@ PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) template_instdir_SQ = $(subst ','\'',$(template_instdir)) -all: boilerplates.made custom +all:: boilerplates.made custom # Put templates that can be copied straight from the source # in a file direc--tory--file in the source. They will be diff --git a/tmp-objdir.c b/tmp-objdir.c index 0ea078a5c5..31d16a4c2c 100644 --- a/tmp-objdir.c +++ b/tmp-objdir.c @@ -207,10 +207,12 @@ static int read_dir_paths(struct string_list *out, const char *path) return 0; } -static int migrate_paths(struct strbuf *src, struct strbuf *dst, +static int migrate_paths(struct tmp_objdir *t, + struct strbuf *src, struct strbuf *dst, enum finalize_object_file_flags flags); -static int migrate_one(struct strbuf *src, struct strbuf *dst, +static int migrate_one(struct tmp_objdir *t, + struct strbuf *src, struct strbuf *dst, enum finalize_object_file_flags flags) { struct stat st; @@ -219,11 +221,11 @@ static int migrate_one(struct strbuf *src, struct strbuf *dst, return -1; if (S_ISDIR(st.st_mode)) { if (!mkdir(dst->buf, 0777)) { - if (adjust_shared_perm(dst->buf)) + if (adjust_shared_perm(t->repo, dst->buf)) return -1; } else if (errno != EEXIST) return -1; - return migrate_paths(src, dst, flags); + return migrate_paths(t, src, dst, flags); } return finalize_object_file_flags(src->buf, dst->buf, flags); } @@ -233,7 +235,8 @@ static int is_loose_object_shard(const char *name) return strlen(name) == 2 && isxdigit(name[0]) && isxdigit(name[1]); } -static int migrate_paths(struct strbuf *src, struct strbuf *dst, +static int migrate_paths(struct tmp_objdir *t, + struct strbuf *src, struct strbuf *dst, enum finalize_object_file_flags flags) { size_t src_len = src->len, dst_len = dst->len; @@ -255,7 +258,7 @@ static int migrate_paths(struct strbuf *src, struct strbuf *dst, if (is_loose_object_shard(name)) flags_copy |= FOF_SKIP_COLLISION_CHECK; - ret |= migrate_one(src, dst, flags_copy); + ret |= migrate_one(t, src, dst, flags_copy); strbuf_setlen(src, src_len); strbuf_setlen(dst, dst_len); @@ -283,7 +286,7 @@ int tmp_objdir_migrate(struct tmp_objdir *t) strbuf_addbuf(&src, &t->path); strbuf_addstr(&dst, repo_get_object_directory(t->repo)); - ret = migrate_paths(&src, &dst, 0); + ret = migrate_paths(t, &src, &dst, 0); strbuf_release(&src); strbuf_release(&dst); @@ -31,7 +31,7 @@ * * For more info about: trace2 targets, conventions for public functions and * macros, trace2 target formats and examples on trace2 API usage refer to - * Documentation/technical/api-trace2.txt + * Documentation/technical/api-trace2.adoc * */ diff --git a/trace2/tr2_sysenv.c b/trace2/tr2_sysenv.c index 01379c5cad..4abc218514 100644 --- a/trace2/tr2_sysenv.c +++ b/trace2/tr2_sysenv.c @@ -7,7 +7,7 @@ /* * Each entry represents a trace2 setting. - * See Documentation/technical/api-trace2.txt + * See Documentation/technical/api-trace2.adoc */ struct tr2_sysenv_entry { const char *env_var_name; diff --git a/transport.h b/transport.h index 44100fa9b7..892f19454a 100644 --- a/transport.h +++ b/transport.h @@ -168,7 +168,7 @@ struct transport *transport_get(struct remote *, const char *); * Check whether a transport is allowed by the environment. * * Type should generally be the URL scheme, as described in - * Documentation/git.txt + * Documentation/git.adoc * * from_user specifies if the transport was given by the user. If unknown pass * a -1 to read from the environment to determine if the transport was given by diff --git a/unpack-trees.c b/unpack-trees.c index 334cb84f65..cf5b73c84b 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -2904,7 +2904,7 @@ int threeway_merge(const struct cache_entry * const *stages, * The rule is to "carry forward" what is in the index without losing * information across a "fast-forward", favoring a successful merge * over a merge failure when it makes sense. For details of the - * "carry forward" rule, please see <Documentation/git-read-tree.txt>. + * "carry forward" rule, please see <Documentation/git-read-tree.adoc>. * */ int twoway_merge(const struct cache_entry * const *src, diff --git a/upload-pack.c b/upload-pack.c index 728b2477fc..7498b45e2e 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -32,6 +32,7 @@ #include "write-or-die.h" #include "json-writer.h" #include "strmap.h" +#include "promisor-remote.h" /* Remember to update object flag allocation in object.h */ #define THEY_HAVE (1u << 11) @@ -319,6 +320,8 @@ static void create_pack_file(struct upload_pack_data *pack_data, strvec_push(&pack_objects.args, "--delta-base-offset"); if (pack_data->use_include_tag) strvec_push(&pack_objects.args, "--include-tag"); + if (repo_has_accepted_promisor_remote(the_repository)) + strvec_push(&pack_objects.args, "--missing=allow-promisor"); if (pack_data->filter_options.choice) { const char *spec = expand_list_objects_filter_spec(&pack_data->filter_options); @@ -1,6 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "version.h" #include "strbuf.h" +#include "gettext.h" #ifndef GIT_VERSION_H # include "version-def.h" @@ -11,6 +14,19 @@ const char git_version_string[] = GIT_VERSION; const char git_built_from_commit_string[] = GIT_BUILT_FROM_COMMIT; +/* + * Trim and replace each character with ascii code below 32 or above + * 127 (included) using a dot '.' character. + */ +static void redact_non_printables(struct strbuf *buf) +{ + strbuf_trim(buf); + for (size_t i = 0; i < buf->len; i++) { + if (!isprint(buf->buf[i]) || buf->buf[i] == ' ') + buf->buf[i] = '.'; + } +} + const char *git_user_agent(void) { static const char *agent = NULL; @@ -24,6 +40,27 @@ const char *git_user_agent(void) return agent; } +/* + Retrieve, sanitize and cache operating system info for subsequent + calls. Return a pointer to the sanitized operating system info + string. +*/ +static const char *os_info(void) +{ + static const char *os = NULL; + + if (!os) { + struct strbuf buf = STRBUF_INIT; + + get_uname_info(&buf, 0); + /* Sanitize the os information immediately */ + redact_non_printables(&buf); + os = strbuf_detach(&buf, NULL); + } + + return os; +} + const char *git_user_agent_sanitized(void) { static const char *agent = NULL; @@ -32,13 +69,35 @@ const char *git_user_agent_sanitized(void) struct strbuf buf = STRBUF_INIT; strbuf_addstr(&buf, git_user_agent()); - strbuf_trim(&buf); - for (size_t i = 0; i < buf.len; i++) { - if (buf.buf[i] <= 32 || buf.buf[i] >= 127) - buf.buf[i] = '.'; + + if (!getenv("GIT_USER_AGENT")) { + strbuf_addch(&buf, '-'); + strbuf_addstr(&buf, os_info()); } - agent = buf.buf; + redact_non_printables(&buf); + agent = strbuf_detach(&buf, NULL); } return agent; } + +int get_uname_info(struct strbuf *buf, unsigned int full) +{ + struct utsname uname_info; + + if (uname(&uname_info)) { + strbuf_addf(buf, _("uname() failed with error '%s' (%d)\n"), + strerror(errno), + errno); + return -1; + } + if (full) + strbuf_addf(buf, "%s %s %s %s\n", + uname_info.sysname, + uname_info.release, + uname_info.version, + uname_info.machine); + else + strbuf_addf(buf, "%s\n", uname_info.sysname); + return 0; +} @@ -1,10 +1,20 @@ #ifndef VERSION_H #define VERSION_H +struct repository; + extern const char git_version_string[]; extern const char git_built_from_commit_string[]; const char *git_user_agent(void); const char *git_user_agent_sanitized(void); +/* + Try to get information about the system using uname(2). + Return -1 and put an error message into 'buf' in case of uname() + error. Return 0 and put uname info into 'buf' otherwise. +*/ +int get_uname_info(struct strbuf *buf, unsigned int full); + + #endif /* VERSION_H */ diff --git a/worktree.c b/worktree.c index d4a68c9c23..c34b9eb74e 100644 --- a/worktree.c +++ b/worktree.c @@ -59,8 +59,9 @@ static void add_head_info(struct worktree *wt) static int is_current_worktree(struct worktree *wt) { char *git_dir = absolute_pathdup(repo_get_git_dir(the_repository)); - const char *wt_git_dir = get_worktree_git_dir(wt); + char *wt_git_dir = get_worktree_git_dir(wt); int is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir)); + free(wt_git_dir); free(git_dir); return is_current; } @@ -127,7 +128,7 @@ struct worktree *get_linked_worktree(const char *id, if (!id) die("Missing linked worktree name"); - strbuf_git_common_path(&path, the_repository, "worktrees/%s/gitdir", id); + repo_common_path_append(the_repository, &path, "worktrees/%s/gitdir", id); if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0) /* invalid gitdir file */ goto done; @@ -198,14 +199,19 @@ struct worktree **get_worktrees(void) return get_worktrees_internal(0); } -const char *get_worktree_git_dir(const struct worktree *wt) +struct worktree **get_worktrees_without_reading_head(void) +{ + return get_worktrees_internal(1); +} + +char *get_worktree_git_dir(const struct worktree *wt) { if (!wt) - return repo_get_git_dir(the_repository); + return xstrdup(repo_get_git_dir(the_repository)); else if (!wt->id) - return repo_get_common_dir(the_repository); + return xstrdup(repo_get_common_dir(the_repository)); else - return git_common_path("worktrees/%s", wt->id); + return repo_common_path(the_repository, "worktrees/%s", wt->id); } static struct worktree *find_worktree_by_suffix(struct worktree **list, @@ -336,6 +342,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, { struct strbuf wt_path = STRBUF_INIT; struct strbuf realpath = STRBUF_INIT; + struct strbuf buf = STRBUF_INIT; char *path = NULL; int err, ret = -1; @@ -365,7 +372,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, if (!is_absolute_path(wt->path)) { strbuf_addf_gently(errmsg, _("'%s' file does not contain absolute path to the working tree location"), - git_common_path("worktrees/%s/gitdir", wt->id)); + repo_common_path_replace(the_repository, &buf, "worktrees/%s/gitdir", wt->id)); goto done; } @@ -387,14 +394,16 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, goto done; } - strbuf_realpath(&realpath, git_common_path("worktrees/%s", wt->id), 1); + strbuf_realpath(&realpath, repo_common_path_replace(the_repository, &buf, "worktrees/%s", wt->id), 1); ret = fspathcmp(path, realpath.buf); if (ret) strbuf_addf_gently(errmsg, _("'%s' does not point back to '%s'"), - wt->path, git_common_path("worktrees/%s", wt->id)); + wt->path, repo_common_path_replace(the_repository, &buf, + "worktrees/%s", wt->id)); done: free(path); + strbuf_release(&buf); strbuf_release(&wt_path); strbuf_release(&realpath); return ret; @@ -406,11 +415,13 @@ void update_worktree_location(struct worktree *wt, const char *path_, struct strbuf path = STRBUF_INIT; struct strbuf dotgit = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT; + char *wt_gitdir; if (is_main_worktree(wt)) BUG("can't relocate main worktree"); - strbuf_realpath(&gitdir, git_common_path("worktrees/%s/gitdir", wt->id), 1); + wt_gitdir = repo_common_path(the_repository, "worktrees/%s/gitdir", wt->id); + strbuf_realpath(&gitdir, wt_gitdir, 1); strbuf_realpath(&path, path_, 1); strbuf_addf(&dotgit, "%s/.git", path.buf); if (fspathcmp(wt->path, path.buf)) { @@ -422,6 +433,7 @@ void update_worktree_location(struct worktree *wt, const char *path_, strbuf_release(&path); strbuf_release(&dotgit); strbuf_release(&gitdir); + free(wt_gitdir); } int is_worktree_being_rebased(const struct worktree *wt, @@ -510,7 +522,8 @@ int submodule_uses_worktrees(const char *path) int ret = 0; struct repository_format format = REPOSITORY_FORMAT_INIT; - submodule_gitdir = git_pathdup_submodule(path, "%s", ""); + submodule_gitdir = repo_submodule_path(the_repository, + path, "%s", ""); if (!submodule_gitdir) return 0; @@ -606,6 +619,7 @@ static void repair_gitfile(struct worktree *wt, struct strbuf backlink = STRBUF_INIT; char *dotgit_contents = NULL; const char *repair = NULL; + char *path = NULL; int err; /* missing worktree can't be repaired */ @@ -617,7 +631,8 @@ static void repair_gitfile(struct worktree *wt, goto done; } - strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); + path = repo_common_path(the_repository, "worktrees/%s", wt->id); + strbuf_realpath(&repo, path, 1); strbuf_addf(&dotgit, "%s/.git", wt->path); strbuf_addf(&gitdir, "%s/gitdir", repo.buf); dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); @@ -647,6 +662,7 @@ static void repair_gitfile(struct worktree *wt, done: free(dotgit_contents); + free(path); strbuf_release(&repo); strbuf_release(&dotgit); strbuf_release(&gitdir); @@ -678,11 +694,13 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path struct strbuf gitdir = STRBUF_INIT; struct strbuf dotgit = STRBUF_INIT; int is_relative_path; + char *path = NULL; if (is_main_worktree(wt)) goto done; - strbuf_realpath(&gitdir, git_common_path("worktrees/%s/gitdir", wt->id), 1); + path = repo_common_path(the_repository, "worktrees/%s/gitdir", wt->id); + strbuf_realpath(&gitdir, path, 1); if (strbuf_read_file(&dotgit, gitdir.buf, 0) < 0) goto done; @@ -701,6 +719,7 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path done: strbuf_release(&gitdir); strbuf_release(&dotgit); + free(path); } void repair_worktrees_after_gitdir_move(const char *old_path) @@ -754,8 +773,7 @@ static ssize_t infer_backlink(const char *gitfile, struct strbuf *inferred) id++; /* advance past '/' to point at <id> */ if (!*id) goto error; - strbuf_reset(inferred); - strbuf_git_common_path(inferred, the_repository, "worktrees/%s", id); + repo_common_path_replace(the_repository, inferred, "worktrees/%s", id); if (!is_directory(inferred->buf)) goto error; @@ -893,7 +911,11 @@ int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, ssize_t read_result; *wtpath = NULL; - strbuf_realpath(&repo, git_common_path("worktrees/%s", id), 1); + + path = repo_common_path(the_repository, "worktrees/%s", id); + strbuf_realpath(&repo, path, 1); + FREE_AND_NULL(path); + strbuf_addf(&gitdir, "%s/gitdir", repo.buf); if (!is_directory(repo.buf)) { strbuf_addstr(reason, _("not a valid directory")); diff --git a/worktree.h b/worktree.h index 38145df80f..e4bcccdc0a 100644 --- a/worktree.h +++ b/worktree.h @@ -31,6 +31,14 @@ struct worktree { struct worktree **get_worktrees(void); /* + * Like `get_worktrees`, but does not read HEAD. Skip reading HEAD allows to + * get the worktree without worrying about failures pertaining to parsing + * the HEAD ref. This is useful in contexts where it is assumed that the + * refdb may not be in a consistent state. + */ +struct worktree **get_worktrees_without_reading_head(void); + +/* * Returns 1 if linked worktrees exist, 0 otherwise. */ int submodule_uses_worktrees(const char *path); @@ -39,7 +47,7 @@ int submodule_uses_worktrees(const char *path); * Return git dir of the worktree. Note that the path may be relative. * If wt is NULL, git dir of current worktree is returned. */ -const char *get_worktree_git_dir(const struct worktree *wt); +char *get_worktree_git_dir(const struct worktree *wt); /* * Search for the worktree identified unambiguously by `arg` -- typically diff --git a/wt-status.c b/wt-status.c index 3ee9181764..1da5732f57 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1289,7 +1289,8 @@ static void show_am_in_progress(struct wt_status *s, static char *read_line_from_git_path(const char *filename) { struct strbuf buf = STRBUF_INIT; - FILE *fp = fopen_or_warn(git_path("%s", filename), "r"); + FILE *fp = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "%s", filename), "r"); if (!fp) { strbuf_release(&buf); @@ -1383,27 +1384,33 @@ static void abbrev_oid_in_line(struct strbuf *line) static int read_rebase_todolist(const char *fname, struct string_list *lines) { - struct strbuf line = STRBUF_INIT; - FILE *f = fopen(git_path("%s", fname), "r"); + struct strbuf buf = STRBUF_INIT; + FILE *f = fopen(repo_git_path_append(the_repository, &buf, "%s", fname), "r"); + int ret; if (!f) { - if (errno == ENOENT) - return -1; + if (errno == ENOENT) { + ret = -1; + goto out; + } die_errno("Could not open file %s for reading", - git_path("%s", fname)); + repo_git_path_replace(the_repository, &buf, "%s", fname)); } - while (!strbuf_getline_lf(&line, f)) { - if (starts_with(line.buf, comment_line_str)) + while (!strbuf_getline_lf(&buf, f)) { + if (starts_with(buf.buf, comment_line_str)) continue; - strbuf_trim(&line); - if (!line.len) + strbuf_trim(&buf); + if (!buf.len) continue; - abbrev_oid_in_line(&line); - string_list_append(lines, line.buf); + abbrev_oid_in_line(&buf); + string_list_append(lines, buf.buf); } fclose(f); - strbuf_release(&line); - return 0; + + ret = 0; +out: + strbuf_release(&buf); + return ret; } static void show_rebase_information(struct wt_status *s, @@ -1434,9 +1441,12 @@ static void show_rebase_information(struct wt_status *s, i < have_done.nr; i++) status_printf_ln(s, color, " %s", have_done.items[i].string); - if (have_done.nr > nr_lines_to_show && s->hints) + if (have_done.nr > nr_lines_to_show && s->hints) { + char *path = repo_git_path(the_repository, "rebase-merge/done"); status_printf_ln(s, color, - _(" (see more in file %s)"), git_path("rebase-merge/done")); + _(" (see more in file %s)"), path); + free(path); + } } if (yet_to_do.nr == 0) diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h index bb56b23f34..2cecde5afe 100644 --- a/xdiff/xdiff.h +++ b/xdiff/xdiff.h @@ -85,7 +85,7 @@ typedef struct s_xpparam { regex_t **ignore_regex; size_t ignore_regex_nr; - /* See Documentation/diff-options.txt. */ + /* See Documentation/diff-options.adoc. */ char **anchors; size_t anchors_nr; } xpparam_t; diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c index 4685ba6137..8889b8b62a 100644 --- a/xdiff/xdiffi.c +++ b/xdiff/xdiffi.c @@ -19,7 +19,6 @@ * Davide Libenzi <davidel@xmailserver.org> * */ -#define DISABLE_SIGN_COMPARE_WARNINGS #include "xinclude.h" @@ -1014,7 +1013,7 @@ static void xdl_mark_ignorable_lines(xdchange_t *xscr, xdfenv_t *xe, long flags) static int record_matches_regex(xrecord_t *rec, xpparam_t const *xpp) { regmatch_t regmatch; - int i; + size_t i; for (i = 0; i < xpp->ignore_regex_nr; i++) if (!regexec_buf(xpp->ignore_regex[i], rec->ptr, rec->size, 1, diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 75f0fe4986..f8e3f25b03 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -54,7 +54,7 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg) xdchange_t *xch, *xchp, *lxch; long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen; long max_ignorable = xecfg->ctxlen; - unsigned long ignored = 0; /* number of ignored blank lines */ + long ignored = 0; /* number of ignored blank lines */ /* remove ignorable changes that are too far before other changes */ for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) { diff --git a/xdiff/xhistogram.c b/xdiff/xhistogram.c index 16a8fe2f3f..040d81e0bc 100644 --- a/xdiff/xhistogram.c +++ b/xdiff/xhistogram.c @@ -106,7 +106,7 @@ static int scanA(struct histindex *index, int line1, int count1) unsigned int chain_len; struct record **rec_chain, *rec; - for (ptr = LINE_END(1); line1 <= ptr; ptr--) { + for (ptr = LINE_END(1); (unsigned int)line1 <= ptr; ptr--) { tbl_idx = TABLE_HASH(index, 1, ptr); rec_chain = index->records + tbl_idx; rec = *rec_chain; @@ -181,14 +181,14 @@ static int try_lcs(struct histindex *index, struct region *lcs, int b_ptr, be = bs; rc = rec->cnt; - while (line1 < as && line2 < bs + while ((unsigned int)line1 < as && (unsigned int)line2 < bs && CMP(index, 1, as - 1, 2, bs - 1)) { as--; bs--; if (1 < rc) rc = XDL_MIN(rc, CNT(index, as)); } - while (ae < LINE_END(1) && be < LINE_END(2) + while (ae < (unsigned int)LINE_END(1) && be < (unsigned int)LINE_END(2) && CMP(index, 1, ae + 1, 2, be + 1)) { ae++; be++; @@ -313,7 +313,7 @@ redo: if (count1 <= 0 && count2 <= 0) return 0; - if (LINE_END(1) >= MAX_PTR) + if ((unsigned int)LINE_END(1) >= MAX_PTR) return -1; if (!count1) { diff --git a/xdiff/xinclude.h b/xdiff/xinclude.h index 7e56542526..a4285ac0eb 100644 --- a/xdiff/xinclude.h +++ b/xdiff/xinclude.h @@ -23,8 +23,6 @@ #if !defined(XINCLUDE_H) #define XINCLUDE_H -#define DISABLE_SIGN_COMPARE_WARNINGS - #include "git-compat-util.h" #include "xmacros.h" #include "xdiff.h" diff --git a/xdiff/xpatience.c b/xdiff/xpatience.c index a2d8955537..77dc411d19 100644 --- a/xdiff/xpatience.c +++ b/xdiff/xpatience.c @@ -19,6 +19,7 @@ * Davide Libenzi <davidel@xmailserver.org> * */ + #include "xinclude.h" /* @@ -63,7 +64,7 @@ struct hashmap { /* * If 1, this entry can serve as an anchor. See - * Documentation/diff-options.txt for more information. + * Documentation/diff-options.adoc for more information. */ unsigned anchor : 1; } *entries, *first, *last; @@ -75,7 +76,7 @@ struct hashmap { static int is_anchor(xpparam_t const *xpp, const char *line) { - int i; + size_t i; for (i = 0; i < xpp->anchors_nr; i++) { if (!strncmp(line, xpp->anchors[i], strlen(xpp->anchors[i]))) return 1; diff --git a/xdiff/xutils.c b/xdiff/xutils.c index 9e36f24875..444a108f87 100644 --- a/xdiff/xutils.c +++ b/xdiff/xutils.c @@ -375,7 +375,7 @@ static int xdl_format_hunk_hdr(long s1, long c1, long s2, long c2, nb += 3; if (func && funclen) { buf[nb++] = ' '; - if (funclen > sizeof(buf) - nb - 1) + if ((size_t)funclen > sizeof(buf) - nb - 1) funclen = sizeof(buf) - nb - 1; memcpy(buf + nb, func, funclen); nb += funclen; @@ -437,7 +437,7 @@ void* xdl_alloc_grow_helper(void *p, long nr, long *alloc, size_t size) { void *tmp = NULL; size_t n = ((LONG_MAX - 16) / 2 >= *alloc) ? 2 * *alloc + 16 : LONG_MAX; - if (nr > n) + if ((size_t)nr > n) n = nr; if (SIZE_MAX / size >= n) tmp = xdl_realloc(p, n * size); |
